| JarFiles.java |
1 /*
2 * JarFileMerger.java
3 *
4 * Copyright (c) 1998-2004, The University of Sheffield.
5 *
6 * This file is part of GATE (see http://gate.ac.uk/), and is free
7 * software, licenced under the GNU Library General Public License,
8 * Version 2, June 1991 (in the distribution as file licence.html,
9 * and also available at http://gate.ac.uk/gate/licence.html).
10 *
11 * Oana Hamza, 09/06/00
12 *
13 * $Id: JarFiles.java,v 1.16 2004/07/21 17:10:09 akshay Exp $
14 */
15
16 package gate.util;
17
18 import java.io.*;
19 import java.util.*;
20 import java.util.jar.*;
21
22 /** This class is used to merge a set of Jar/Zip Files in a Jar File
23 * It is ignored the manifest.
24 */
25 public class JarFiles {
26
27 /** Debug flag */
28 private static final boolean DEBUG = false;
29 private StringBuffer dbgString = new StringBuffer();
30 private boolean warning = false;
31 String buggyJar = null;
32
33 private final static int BUFF_SIZE = 65000;
34
35 private Set directorySet = null;
36
37 private byte buffer[] = null;
38
39 public JarFiles(){
40 directorySet = new HashSet();
41 buffer = new byte[BUFF_SIZE];
42 }
43
44 /** This method takes the content of all jar/zip files from the set
45 * jarFileNames and put them in a file with the name outputFileName.
46 * If the jar entry is manifest then this information isn't added.
47 * @param jarFileNames is a set of names of files (jar/zip)
48 * @param destinationJarName is the name of the file which contains all the
49 * classes of jarFilesNames
50 */
51 public void merge(Set jarFileNames, String destinationJarName)
52 throws GateException {
53 String sourceJarName = null;
54 JarOutputStream jarFileDestination = null;
55 JarFile jarFileSource = null;
56
57 try {
58 // create the output jar file
59 jarFileDestination =
60 new JarOutputStream(new FileOutputStream(destinationJarName));
61
62 dbgString.append("Creating " + destinationJarName + " from these JARs:\n");
63 // iterate through the Jar files set
64 Iterator jarFileNamesIterator = jarFileNames.iterator();
65
66 while (jarFileNamesIterator.hasNext()) {
67 sourceJarName = (String) jarFileNamesIterator.next();
68
69 // create the new input jar files based on the file name
70 jarFileSource = new JarFile(sourceJarName);
71
72 // Out.println("Adding " + sourceJarName + " to "
73 // + destinationJarName);
74 addJar(jarFileDestination, jarFileSource);
75 if (jarFileSource.getName().equals(buggyJar))
76 dbgString.append(sourceJarName + "...problems occured ! \n");
77 else
78 dbgString.append(sourceJarName + "...added OK ! \n");
79 jarFileSource.close();
80 }//End while
81
82 jarFileDestination.close();
83
84 } catch(IOException ioe) {
85 ioe.printStackTrace(Err.getPrintWriter());
86 //System.exit(1);
87 }
88 if (warning == true)
89 Out.prln(dbgString);
90 }// merge
91
92
93 /**
94 * This method adds all entries from sourceJar to destinationJar
95 * NOTE: that manifest information is not added, method will throw
96 * a gate Exception if a duplicate entry file is found.
97 * @param destinationJar the jar that will collect all the entries
98 * from source jar
99 * @param sourceJar doesn't need any explanation ... DOES it?
100 */
101 private void addJar(JarOutputStream destinationJar, JarFile sourceJar)
102 throws GateException {
103 try {
104
105 // get an enumeration of all entries from the sourceJar
106 Enumeration jarFileEntriesEnum = sourceJar.entries();
107
108 JarEntry currentJarEntry = null;
109 while (jarFileEntriesEnum.hasMoreElements()) {
110
111 // get a JarEntry
112 currentJarEntry = (JarEntry) jarFileEntriesEnum.nextElement();
113
114 // if current entry is manifest then it is skipped
115 if(currentJarEntry.getName().equalsIgnoreCase("META-INF/") ||
116 currentJarEntry.getName().equalsIgnoreCase("META-INF/MANIFEST.MF"))
117 continue;
118
119 // if current entry is a directory that was previously added to the
120 // destination JAR then it is skipped
121 if( currentJarEntry.isDirectory() &&
122 directorySet.contains(currentJarEntry.getName())
123 ) continue;
124
125 // otherwise the current entry is added to the final jar file
126 try {
127 // if the entry is directory then is added to the directorySet
128 // NOTE: files entries are not added to this set
129 if (currentJarEntry.isDirectory())
130 directorySet.add(currentJarEntry.getName());
131
132 // put the entry into the destination JAR
133 destinationJar.putNextEntry(new JarEntry(currentJarEntry.getName()));
134
135 // add the binary data from the entry
136 // NOTE: if the entry is a directory there will be no binary data
137 // get an input stream from the entry
138 InputStream currentEntryStream =
139 sourceJar.getInputStream(currentJarEntry);
140
141 // write data to destinationJar
142 int bytesRead = 0;
143 while((bytesRead = currentEntryStream.read(buffer,0,BUFF_SIZE)) != -1)
144 destinationJar.write(buffer,0,bytesRead);
145
146 // close the input stream
147 currentEntryStream.close();
148
149 // flush the destinationJar in order to be sure that
150 // everything is there
151 destinationJar.flush();
152
153 // close the new added entry and prepare to read and write
154 // another one
155 // NOTE: destinationJar.putNextEntry automaticaly closes any previous
156 // opened entry
157 destinationJar.closeEntry();
158
159 } catch (java.util.zip.ZipException ze) {
160 if(!currentJarEntry.isDirectory()){
161 warning = true;
162 buggyJar = sourceJar.getName();
163 Out.prln("WARNING: Duplicate file entry " +
164 currentJarEntry.getName() + " (this file will be discarded)..." +
165 "It happened while adding " +
166 sourceJar.getName() + " !\n");
167 dbgString.append(currentJarEntry.getName() +" file from " +
168 sourceJar.getName() + " was discarded :( !\n");
169 }// End if
170 }
171 }// while(jarFileEntriesEnum.hasMoreElements())
172 } catch (java.io.IOException e) {
173 e.printStackTrace(Err.getPrintWriter());
174 // System.exit(1);
175 }
176 }// addJar
177
178 /** args[0] is the final jar file and the other are the set of
179 * jar file names
180 * e.g. java gate.util.JarFiles libs.jar ../lib/*.jar ../lib/*.zip
181 * will create a file calls libs.jar which will contain all
182 * jar files and zip files
183 */
184
185 public static void main(String[] args) {
186 if(args.length < 2) {
187 Err.println("USAGE : JarFiles arg0 arg1 ... argN" +
188 "(must be at least 2 args)");
189 //System.exit(1);
190 } else {
191 JarFiles jarFiles = new JarFiles();
192 Set filesToMerge = new HashSet();
193 for (int i=1; i<args.length; i++) {
194 filesToMerge.add(args[i]);
195 }
196 try {
197 jarFiles.merge(filesToMerge, args[0]);
198 } catch (GateException ge) {
199 ge.printStackTrace(Err.getPrintWriter());
200 }
201 }// if
202 }// main
203
204 }// class JarFiles
205