001 ///////////////////////////////////////////////// 002 // This file is part of Sears project. 003 // Subtitle Editor And Re-Synch 004 // A tool to easily modify and resynch movies subtitles. 005 ///////////////////////////////////////////////// 006 //This program is free software; 007 //you can redistribute it and/or modify it under the terms 008 //of the GNU General Public License 009 //as published by the Free Software Foundation; 010 //either version 2 of the License, or (at your option) any later version. 011 ///////////////////////////////////////////////// 012 //Sears project is availbale under sourceforge 013 // at adress: http://sourceforge.net/projects/sears/ 014 //Copyright (C) 2005 Booba Skaya 015 //Mail: booba.skaya@gmail.com 016 //////////////////////////////////////////////// 017 package sears.tools; 018 019 import java.io.*; 020 import java.util.*; 021 import java.util.zip.*; 022 023 /** 024 * JarResources: JarResources maps all resources included in a Zip or Jar file. 025 * Additionaly, it provides a method to extract one as a blob. 026 */ 027 public final class JarResources { 028 029 // external debug flag 030 public boolean debugOn = false; 031 032 // jar resource mapping tables 033 private Hashtable<String, Integer> htSizes = new Hashtable<String, Integer>(); 034 035 private Hashtable<String, byte[]> htJarContents = new Hashtable<String, byte[]>(); 036 037 // a jar file 038 private String jarFileName; 039 040 /** 041 * creates a JarResources. It extracts all resources from a Jar into an 042 * internal hashtable, keyed by resource names. 043 * 044 * @param jarFileName 045 * a jar or zip file 046 */ 047 public JarResources(String jarFileName) { 048 this.jarFileName = jarFileName; 049 init(); 050 } 051 052 /** 053 * Extracts a jar resource as a blob. 054 * 055 * @param name 056 * a resource name. 057 */ 058 public byte[] getResource(String name) { 059 return (byte[]) htJarContents.get(name); 060 } 061 062 /** 063 * initializes internal hash tables with Jar file resources. 064 */ 065 private void init() { 066 try { 067 // extracts just sizes only. 068 ZipFile zf = new ZipFile(jarFileName); 069 Enumeration<?> e = zf.entries(); 070 while (e.hasMoreElements()) { 071 ZipEntry ze = (ZipEntry) e.nextElement(); 072 if (debugOn) { 073 System.out.println(dumpZipEntry(ze)); 074 } 075 htSizes.put(ze.getName(), new Integer((int) ze.getSize())); 076 } 077 zf.close(); 078 079 // extract resources and put them into the hashtable. 080 FileInputStream fis = new FileInputStream(jarFileName); 081 BufferedInputStream bis = new BufferedInputStream(fis); 082 ZipInputStream zis = new ZipInputStream(bis); 083 ZipEntry ze = null; 084 while ((ze = zis.getNextEntry()) != null) { 085 if (ze.isDirectory()) { 086 continue; 087 } 088 if (debugOn) { 089 System.out.println("ze.getName()=" + ze.getName() + "," 090 + "getSize()=" + ze.getSize()); 091 } 092 int size = (int) ze.getSize(); 093 // -1 means unknown size. 094 if (size == -1) { 095 size = ((Integer) htSizes.get(ze.getName())).intValue(); 096 } 097 byte[] b = new byte[(int) size]; 098 int rb = 0; 099 int chunk = 0; 100 while (((int) size - rb) > 0) { 101 chunk = zis.read(b, rb, (int) size - rb); 102 if (chunk == -1) { 103 break; 104 } 105 rb += chunk; 106 } 107 // add to internal resource hashtable 108 htJarContents.put(ze.getName(), b); 109 if (debugOn) { 110 System.out.println(ze.getName() + " rb=" + rb + ",size=" 111 + size + ",csize=" + ze.getCompressedSize()); 112 } 113 } 114 } catch (ZipException e) { 115 Trace.trace("Can't find " + jarFileName, Trace.WARNING_PRIORITY); 116 } catch (NullPointerException e) { 117 System.out.println("done."); 118 } catch (FileNotFoundException e) { 119 e.printStackTrace(); 120 } catch (IOException e) { 121 e.printStackTrace(); 122 } 123 } 124 125 /** 126 * Dumps a zip entry into a string. 127 * 128 * @param ze 129 * a ZipEntry 130 */ 131 private String dumpZipEntry(ZipEntry ze) { 132 StringBuffer sb = new StringBuffer(); 133 if (ze.isDirectory()) { 134 sb.append("d "); 135 } else { 136 sb.append("f "); 137 } 138 if (ze.getMethod() == ZipEntry.STORED) { 139 sb.append("stored "); 140 } else { 141 sb.append("defalted "); 142 } 143 sb.append(ze.getName()); 144 sb.append("\t"); 145 sb.append("" + ze.getSize()); 146 if (ze.getMethod() == ZipEntry.DEFLATED) { 147 sb.append("/" + ze.getCompressedSize()); 148 } 149 return (sb.toString()); 150 } 151 152 /** 153 * Is a test driver. Given a jar file and a resource name, it trys to 154 * extract the resource and then tells us whether it could or not. 155 * 156 * <strong>Example</strong> Let's say you have a JAR file which jarred up a 157 * bunch of gif image files. Now, by using JarResources, you could extract, 158 * create, and display those images on-the-fly. 159 * 160 * <pre> 161 * ... 162 * JarResources JR=new JarResources("GifBundle.jar"); 163 * Image image=Toolkit.createImage(JR.getResource("logo.gif"); 164 * Image logo=Toolkit.getDefaultToolkit().createImage( 165 * JR.getResources("logo.gif") 166 * ); 167 * ... 168 * </pre> 169 */ 170 public static void main(String[] args) throws IOException { 171 if (args.length != 2) { 172 System.err 173 .println("usage: java JarResources <jar file name> <resource name>"); 174 System.exit(1); 175 } 176 JarResources jr = new JarResources(args[0]); 177 byte[] buff = jr.getResource(args[1]); 178 if (buff == null) { 179 System.out.println("Could not find " + args[1] + "."); 180 } else { 181 System.out.println("Found " + args[1] + " (length=" + buff.length 182 + ")."); 183 } 184 } 185 186 } // End of JarResources class. 187