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(&quot;GifBundle.jar&quot;);
163             *      Image image=Toolkit.createImage(JR.getResource(&quot;logo.gif&quot;);
164             *      Image logo=Toolkit.getDefaultToolkit().createImage(
165             *                    JR.getResources(&quot;logo.gif&quot;)
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