KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > csdl > jblanket > util > JarFactory


1 package csdl.jblanket.util;
2
3 import java.io.File JavaDoc;
4 import java.io.FileInputStream JavaDoc;
5 import java.io.FileOutputStream JavaDoc;
6 import java.io.InputStream JavaDoc;
7 import java.io.IOException JavaDoc;
8
9 import java.util.Enumeration JavaDoc;
10 import java.util.jar.JarEntry JavaDoc;
11 import java.util.jar.JarException JavaDoc;
12 import java.util.jar.JarFile JavaDoc;
13 import java.util.jar.JarOutputStream JavaDoc;
14 import java.util.zip.CRC32 JavaDoc;
15
16 import org.apache.tools.ant.DirectoryScanner;
17
18 /**
19  * Provides utilities to extract or package JAR files.
20  * <p>
21  * Methods are provided to either extract or package JAR files using the JDK1.2 java.util.jar
22  * package. Noted that JAR files created with the <code>jar</code> method are smaller than their
23  * counterpart created by using the <code>jar</code> command provided by Java. This is probably
24  * because the <code>jar</code> method here does not include any options.
25  * <p>
26  * Code snips from: Java Cookbook, pp 268-270 and The Java Class Libraries, pp 487-488
27  *
28  * @author Joy M. Agustin
29  * @version $Id: JarFactory.java,v 1.1 2004/11/07 00:32:24 timshadel Exp $
30  */

31 public class JarFactory {
32
33   /** Buffer for reading/writing the JarFile data */
34   private byte[] buffer;
35
36   /** Directory to that does/will contain the class files */
37   private String JavaDoc dir;
38
39   /** Directory separator */
40   private static final String JavaDoc SLASH = File.separator;
41   /** Name of directory holding manifest file */
42   private static final String JavaDoc MAN_DIR = "META-INF";
43   /** Relative path to the manifest file starting at MAN_DIR */
44   private static final String JavaDoc MAN_FILE_PATH = MAN_DIR + SLASH + "MANIFEST.MF";
45
46   /**
47    * Constructs an JarFactory object.
48    *
49    * @param dir the directory that contains/will contain the class files.
50    */

51   public JarFactory(String JavaDoc dir) {
52
53     this.dir = dir;
54     this.buffer = new byte[8092];
55   }
56
57   /**
58    * Extracts all files in a JAR file.
59    *
60    * @param jarFile the JAR file to unjar.
61    * @throws IOException if cannot unjar <code>fileName</code>.
62    * @throws JarException if error extracting files from JAR file.
63    */

64   public void unJar(File JavaDoc jarFile) throws IOException JavaDoc, JarException JavaDoc {
65
66     if (!jarFile.getName().endsWith(".jar")) {
67       throw new JarException JavaDoc ("Not a zip file? " + jarFile.getName());
68     }
69     
70     // process all entries in that JAR file
71
JarFile JavaDoc jar = new JarFile JavaDoc(jarFile);
72     Enumeration JavaDoc all = jar.entries();
73     while (all.hasMoreElements()) {
74       getEntry(jar, ((JarEntry JavaDoc) (all.nextElement())));
75     }
76     
77     jar.close();
78   }
79
80   /**
81    * Gets one file <code>entry</code> from <code>jarFile</code>.
82    *
83    * @param jarFile the JAR file reference to retrieve <code>entry</code> from.
84    * @param entry the file from the JAR to extract.
85    * @throws IOException if error trying to read entry.
86    */

87   private void getEntry(JarFile JavaDoc jarFile, JarEntry JavaDoc entry) throws IOException JavaDoc {
88
89     String JavaDoc entryName = entry.getName();
90     // if a directory, mkdir it (remember to create intervening subdirectories if needed!)
91
if (entryName.endsWith("/")) {
92       new File JavaDoc(dir, entryName).mkdirs();
93       return;
94     }
95     
96     File JavaDoc f = new File JavaDoc(dir, entryName);
97
98     if (!f.getParentFile().exists()) {
99       f.getParentFile().mkdirs();
100     }
101
102     // Must be a file; create output stream to the file
103
FileOutputStream JavaDoc fostream = new FileOutputStream JavaDoc(f);
104     InputStream JavaDoc istream = jarFile.getInputStream(entry);
105     
106     // extract files
107
int n = 0;
108     while ((n = istream.read(buffer)) > 0) {
109       fostream.write(buffer, 0, n);
110     }
111     
112     try {
113       istream.close();
114       fostream.close();
115     }
116     catch (IOException JavaDoc e) {
117       // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
118
}
119   }
120
121   /**
122    * Creates a JAR file. If the JAR file already exists, it will be overwritten.
123    *
124    * @param jarFile the JAR file to create.
125    * @throws IOException if cannot create JAR file.
126    * @throws JarException if error putting files into JAR file.
127    */

128   public void jar(File JavaDoc jarFile) throws IOException JavaDoc, JarException JavaDoc {
129
130     if (!jarFile.getName().endsWith(".jar")) {
131       throw new JarException JavaDoc ("Not a zip file? " + jarFile.getName());
132     }
133     
134     // get all files to include in JAR file, except for manifest
135
DirectoryScanner scanner = new DirectoryScanner();
136     scanner.setIncludes(new String JavaDoc[] {"**"});
137     scanner.setExcludes(new String JavaDoc[] {"**" + SLASH + MAN_DIR + SLASH + "**"});
138     scanner.setBasedir(new File JavaDoc(this.dir));
139     scanner.setCaseSensitive(true);
140     scanner.scan();
141     String JavaDoc[] directories = scanner.getIncludedDirectories();
142     String JavaDoc[] files = scanner.getIncludedFiles();
143     
144     // create JAR file
145
FileOutputStream JavaDoc fostream = new FileOutputStream JavaDoc(jarFile);
146     JarOutputStream JavaDoc jostream = new JarOutputStream JavaDoc(fostream);
147     
148     // create manifest directory and manifest
149
if ((new File JavaDoc(dir, MAN_DIR)).exists()) {
150       putManifest(jostream);
151     }
152     
153     //create subdirectories
154
String JavaDoc currentDirectory = "";
155     for (int i = 0; i < directories.length; i++) {
156       // do not need to put the current directory in JAR file
157
if (directories[i].equals(currentDirectory)) {
158         continue;
159       }
160       putEntry(directories[i] + SLASH, jostream);
161     }
162     
163     // create files
164
for (int i = 0; i < files.length; i++) {
165       putEntry(files[i], jostream);
166     }
167     
168     jostream.finish();
169     
170     try {
171       jostream.close();
172       fostream.close();
173     }
174     catch (IOException JavaDoc e) {
175       // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
176
}
177   }
178
179   /**
180    * Puts manifest file into a JAR file.
181    *
182    * @param jostream the JAR file to put manifest into.
183    * @throws IOException if error trying to write entry.
184    */

185   private void putManifest(JarOutputStream JavaDoc jostream) throws IOException JavaDoc {
186
187     // begin borrowed code from Ant Jar and Zip classes
188
// put the META-INF directory into JAR file.
189
String JavaDoc manDirPath = MAN_DIR + SLASH;
190     JarEntry JavaDoc manifestDirEntry = new JarEntry JavaDoc(manDirPath.replace(File.separatorChar, '/'));
191     manifestDirEntry.setTime(System.currentTimeMillis());
192     manifestDirEntry.setSize(0);
193     manifestDirEntry.setMethod(JarEntry.STORED);
194
195     // This is faintly ridiculous - empty CRC value
196
manifestDirEntry.setCrc((new CRC32 JavaDoc()).getValue());
197     jostream.putNextEntry(manifestDirEntry);
198
199     // now put the manifest file into JAR file.
200
JarEntry JavaDoc manifestFileEntry = new JarEntry JavaDoc(MAN_FILE_PATH.replace(File.separatorChar, '/'));
201     manifestFileEntry.setTime(System.currentTimeMillis());
202     FileInputStream JavaDoc fistream = new FileInputStream JavaDoc(new File JavaDoc(this.dir, MAN_FILE_PATH));
203     jostream.putNextEntry(manifestFileEntry);
204
205     int n = 0;
206     while ((n = fistream.read(buffer)) >= 0) {
207       jostream.write(buffer, 0, n);
208     }
209     jostream.closeEntry();
210
211     // end borrowed code from Ant Jar and Zip classes
212
try {
213       fistream.close();
214     }
215     catch (IOException JavaDoc e) {
216       // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
217
}
218   }
219
220   /**
221    * Puts a file into a JAR file.
222    *
223    * @param fileName the file to put in the JAR.
224    * @param jostream the JAR file to put <code>fileName</code> into.
225    * @throws IOException if error trying to write entry.
226    */

227   private void putEntry(String JavaDoc fileName, JarOutputStream JavaDoc jostream) throws IOException JavaDoc {
228
229     // prepare fileName for entry into JAR file
230
String JavaDoc entryName = fileName.replace(File.separatorChar, '/');
231
232     // put directory (remember to create intervening subdirectories if needed!)
233
if (entryName.endsWith("/")) {
234       jostream.putNextEntry(new JarEntry JavaDoc(entryName));
235       jostream.closeEntry();
236       return;
237     }
238
239     // put file
240
FileInputStream JavaDoc fistream = new FileInputStream JavaDoc(new File JavaDoc(this.dir, fileName));
241     jostream.putNextEntry(new JarEntry JavaDoc(entryName));
242     int n;
243
244     // now read and write the JAR entry data.
245
while ((n = fistream.read(buffer)) >= 0) {
246       jostream.write(buffer, 0, n);
247     }
248
249     jostream.closeEntry();
250
251     try {
252       fistream.close();
253     }
254     catch (IOException JavaDoc e) {
255       // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
256
}
257   }
258 }
Popular Tags