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 (NullPointerException e) {
115                            System.out.println("done.");
116                    } catch (FileNotFoundException e) {
117                            e.printStackTrace();
118                    } catch (IOException e) {
119                            e.printStackTrace();
120                    }
121            }
122    
123            /**
124             * Dumps a zip entry into a string.
125             * 
126             * @param ze
127             *            a ZipEntry
128             */
129            private String dumpZipEntry(ZipEntry ze) {
130                    StringBuffer sb = new StringBuffer();
131                    if (ze.isDirectory()) {
132                            sb.append("d ");
133                    } else {
134                            sb.append("f ");
135                    }
136                    if (ze.getMethod() == ZipEntry.STORED) {
137                            sb.append("stored   ");
138                    } else {
139                            sb.append("defalted ");
140                    }
141                    sb.append(ze.getName());
142                    sb.append("\t");
143                    sb.append("" + ze.getSize());
144                    if (ze.getMethod() == ZipEntry.DEFLATED) {
145                            sb.append("/" + ze.getCompressedSize());
146                    }
147                    return (sb.toString());
148            }
149    
150            /**
151             * Is a test driver. Given a jar file and a resource name, it trys to
152             * extract the resource and then tells us whether it could or not.
153             * 
154             * <strong>Example</strong> Let's say you have a JAR file which jarred up a
155             * bunch of gif image files. Now, by using JarResources, you could extract,
156             * create, and display those images on-the-fly.
157             * 
158             * <pre>
159             *      ...
160             *      JarResources JR=new JarResources(&quot;GifBundle.jar&quot;);
161             *      Image image=Toolkit.createImage(JR.getResource(&quot;logo.gif&quot;);
162             *      Image logo=Toolkit.getDefaultToolkit().createImage(
163             *                    JR.getResources(&quot;logo.gif&quot;)
164             *                    );
165             *      ...
166             * </pre>
167             */
168            public static void main(String[] args) throws IOException {
169                    if (args.length != 2) {
170                            System.err
171                                            .println("usage: java JarResources <jar file name> <resource name>");
172                            System.exit(1);
173                    }
174                    JarResources jr = new JarResources(args[0]);
175                    byte[] buff = jr.getResource(args[1]);
176                    if (buff == null) {
177                            System.out.println("Could not find " + args[1] + ".");
178                    } else {
179                            System.out.println("Found " + args[1] + " (length=" + buff.length
180                                            + ").");
181                    }
182            }
183    
184    } // End of JarResources class.
185