author | alanb |
Tue, 08 Feb 2011 19:31:44 +0000 | |
changeset 8189 | 5fd29d2cbc4b |
parent 8169 | 0dc88a086893 |
child 8387 | f0fa7bbf889e |
permissions | -rw-r--r-- |
2 | 1 |
/* |
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
2 |
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.misc; |
|
27 |
||
28 |
import java.io.*; |
|
29 |
import java.util.*; |
|
30 |
import java.util.jar.*; |
|
31 |
import java.util.zip.*; |
|
32 |
||
33 |
/** |
|
34 |
* This class is used to maintain mappings from packages, classes |
|
35 |
* and resources to their enclosing JAR files. Mappings are kept |
|
36 |
* at the package level except for class or resource files that |
|
37 |
* are located at the root directory. URLClassLoader uses the mapping |
|
38 |
* information to determine where to fetch an extension class or |
|
39 |
* resource from. |
|
40 |
* |
|
41 |
* @author Zhenghua Li |
|
42 |
* @since 1.3 |
|
43 |
*/ |
|
44 |
||
45 |
public class JarIndex { |
|
46 |
||
47 |
/** |
|
48 |
* The hash map that maintains mappings from |
|
49 |
* package/classe/resource to jar file list(s) |
|
50 |
*/ |
|
51 |
private HashMap indexMap; |
|
52 |
||
53 |
/** |
|
54 |
* The hash map that maintains mappings from |
|
55 |
* jar file to package/class/resource lists |
|
56 |
*/ |
|
57 |
private HashMap jarMap; |
|
58 |
||
59 |
/* |
|
60 |
* An ordered list of jar file names. |
|
61 |
*/ |
|
62 |
private String[] jarFiles; |
|
63 |
||
64 |
/** |
|
65 |
* The index file name. |
|
66 |
*/ |
|
67 |
public static final String INDEX_NAME = "META-INF/INDEX.LIST"; |
|
68 |
||
69 |
/** |
|
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
70 |
* true if, and only if, sun.misc.JarIndex.metaInfFilenames is set to true. |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
71 |
* If true, the names of the files in META-INF, and its subdirectories, will |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
72 |
* be added to the index. Otherwise, just the directory names are added. |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
73 |
*/ |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
74 |
private static final boolean metaInfFilenames = |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
75 |
"true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames")); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
76 |
|
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
77 |
/** |
2 | 78 |
* Constructs a new, empty jar index. |
79 |
*/ |
|
80 |
public JarIndex() { |
|
81 |
indexMap = new HashMap(); |
|
82 |
jarMap = new HashMap(); |
|
83 |
} |
|
84 |
||
85 |
/** |
|
86 |
* Constructs a new index from the specified input stream. |
|
87 |
* |
|
88 |
* @param is the input stream containing the index data |
|
89 |
*/ |
|
90 |
public JarIndex(InputStream is) throws IOException { |
|
91 |
this(); |
|
92 |
read(is); |
|
93 |
} |
|
94 |
||
95 |
/** |
|
96 |
* Constructs a new index for the specified list of jar files. |
|
97 |
* |
|
98 |
* @param files the list of jar files to construct the index from. |
|
99 |
*/ |
|
100 |
public JarIndex(String[] files) throws IOException { |
|
101 |
this(); |
|
102 |
this.jarFiles = files; |
|
103 |
parseJars(files); |
|
104 |
} |
|
105 |
||
106 |
/** |
|
107 |
* Returns the jar index, or <code>null</code> if none. |
|
108 |
* |
|
109 |
* @param jar the JAR file to get the index from. |
|
110 |
* @exception IOException if an I/O error has occurred. |
|
111 |
*/ |
|
112 |
public static JarIndex getJarIndex(JarFile jar, MetaIndex metaIndex) throws IOException { |
|
113 |
JarIndex index = null; |
|
114 |
/* If metaIndex is not null, check the meta index to see |
|
115 |
if META-INF/INDEX.LIST is contained in jar file or not. |
|
116 |
*/ |
|
117 |
if (metaIndex != null && |
|
118 |
!metaIndex.mayContain(INDEX_NAME)) { |
|
119 |
return null; |
|
120 |
} |
|
121 |
JarEntry e = jar.getJarEntry(INDEX_NAME); |
|
122 |
// if found, then load the index |
|
123 |
if (e != null) { |
|
124 |
index = new JarIndex(jar.getInputStream(e)); |
|
125 |
} |
|
126 |
return index; |
|
127 |
} |
|
128 |
||
129 |
/** |
|
130 |
* Returns the jar files that are defined in this index. |
|
131 |
*/ |
|
132 |
public String[] getJarFiles() { |
|
133 |
return jarFiles; |
|
134 |
} |
|
135 |
||
136 |
/* |
|
137 |
* Add the key, value pair to the hashmap, the value will |
|
138 |
* be put in a linked list which is created if necessary. |
|
139 |
*/ |
|
140 |
private void addToList(String key, String value, HashMap t) { |
|
141 |
LinkedList list = (LinkedList)t.get(key); |
|
142 |
if (list == null) { |
|
143 |
list = new LinkedList(); |
|
144 |
list.add(value); |
|
145 |
t.put(key, list); |
|
146 |
} else if (!list.contains(value)) { |
|
147 |
list.add(value); |
|
148 |
} |
|
149 |
} |
|
150 |
||
151 |
/** |
|
152 |
* Returns the list of jar files that are mapped to the file. |
|
153 |
* |
|
154 |
* @param fileName the key of the mapping |
|
155 |
*/ |
|
156 |
public LinkedList get(String fileName) { |
|
157 |
LinkedList jarFiles = null; |
|
158 |
if ((jarFiles = (LinkedList)indexMap.get(fileName)) == null) { |
|
159 |
/* try the package name again */ |
|
160 |
int pos; |
|
161 |
if((pos = fileName.lastIndexOf("/")) != -1) { |
|
162 |
jarFiles = (LinkedList)indexMap.get(fileName.substring(0, pos)); |
|
163 |
} |
|
164 |
} |
|
165 |
return jarFiles; |
|
166 |
} |
|
167 |
||
168 |
/** |
|
169 |
* Add the mapping from the specified file to the specified |
|
170 |
* jar file. If there were no mapping for the package of the |
|
171 |
* specified file before, a new linked list will be created, |
|
172 |
* the jar file is added to the list and a new mapping from |
|
173 |
* the package to the jar file list is added to the hashmap. |
|
174 |
* Otherwise, the jar file will be added to the end of the |
|
175 |
* existing list. |
|
176 |
* |
|
177 |
* @param fileName the file name |
|
178 |
* @param jarName the jar file that the file is mapped to |
|
179 |
* |
|
180 |
*/ |
|
181 |
public void add(String fileName, String jarName) { |
|
182 |
String packageName; |
|
183 |
int pos; |
|
184 |
if((pos = fileName.lastIndexOf("/")) != -1) { |
|
185 |
packageName = fileName.substring(0, pos); |
|
186 |
} else { |
|
187 |
packageName = fileName; |
|
188 |
} |
|
189 |
||
190 |
// add the mapping to indexMap |
|
191 |
addToList(packageName, jarName, indexMap); |
|
192 |
||
193 |
// add the mapping to jarMap |
|
194 |
addToList(jarName, packageName, jarMap); |
|
195 |
} |
|
196 |
||
197 |
/** |
|
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
198 |
* Same as add(String,String) except that it doesn't strip off from the |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
199 |
* last index of '/'. It just adds the filename. |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
200 |
*/ |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
201 |
private void addExplicit(String fileName, String jarName) { |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
202 |
// add the mapping to indexMap |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
203 |
addToList(fileName, jarName, indexMap); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
204 |
|
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
205 |
// add the mapping to jarMap |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
206 |
addToList(jarName, fileName, jarMap); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
207 |
} |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
208 |
|
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
209 |
/** |
2 | 210 |
* Go through all the jar files and construct the |
211 |
* index table. |
|
212 |
*/ |
|
213 |
private void parseJars(String[] files) throws IOException { |
|
214 |
if (files == null) { |
|
215 |
return; |
|
216 |
} |
|
217 |
||
218 |
String currentJar = null; |
|
219 |
||
220 |
for (int i = 0; i < files.length; i++) { |
|
221 |
currentJar = files[i]; |
|
222 |
ZipFile zrf = new ZipFile(currentJar.replace |
|
223 |
('/', File.separatorChar)); |
|
224 |
||
225 |
Enumeration entries = zrf.entries(); |
|
226 |
while(entries.hasMoreElements()) { |
|
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
227 |
ZipEntry entry = (ZipEntry) entries.nextElement(); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
228 |
String fileName = entry.getName(); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
229 |
|
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
230 |
// Skip the META-INF directory, the index, and manifest. |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
231 |
// Any files in META-INF/ will be indexed explicitly |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
232 |
if (fileName.equals("META-INF/") || |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
233 |
fileName.equals(INDEX_NAME) || |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
234 |
fileName.equals(JarFile.MANIFEST_NAME)) |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
235 |
continue; |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
236 |
|
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
237 |
if (!metaInfFilenames) { |
2 | 238 |
add(fileName, currentJar); |
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
239 |
} else { |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
240 |
if (!fileName.startsWith("META-INF/")) { |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
241 |
add(fileName, currentJar); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
242 |
} else if (!entry.isDirectory()) { |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
243 |
// Add files under META-INF explicitly so that certain |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
244 |
// services, like ServiceLoader, etc, can be located |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
245 |
// with greater accuracy. Directories can be skipped |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
246 |
// since each file will be added explicitly. |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
247 |
addExplicit(fileName, currentJar); |
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
248 |
} |
2 | 249 |
} |
250 |
} |
|
8169
0dc88a086893
6887710: Jar index should avoid putting META-INF in the INDEX.LIST
chegar
parents:
5506
diff
changeset
|
251 |
|
2 | 252 |
zrf.close(); |
253 |
} |
|
254 |
} |
|
255 |
||
256 |
/** |
|
257 |
* Writes the index to the specified OutputStream |
|
258 |
* |
|
259 |
* @param out the output stream |
|
260 |
* @exception IOException if an I/O error has occurred |
|
261 |
*/ |
|
262 |
public void write(OutputStream out) throws IOException { |
|
263 |
BufferedWriter bw = new BufferedWriter |
|
264 |
(new OutputStreamWriter(out, "UTF8")); |
|
265 |
bw.write("JarIndex-Version: 1.0\n\n"); |
|
266 |
||
267 |
if (jarFiles != null) { |
|
268 |
for (int i = 0; i < jarFiles.length; i++) { |
|
269 |
/* print out the jar file name */ |
|
270 |
String jar = jarFiles[i]; |
|
271 |
bw.write(jar + "\n"); |
|
272 |
LinkedList jarlist = (LinkedList)jarMap.get(jar); |
|
273 |
if (jarlist != null) { |
|
274 |
Iterator listitr = jarlist.iterator(); |
|
275 |
while(listitr.hasNext()) { |
|
276 |
bw.write((String)(listitr.next()) + "\n"); |
|
277 |
} |
|
278 |
} |
|
279 |
bw.write("\n"); |
|
280 |
} |
|
281 |
bw.flush(); |
|
282 |
} |
|
283 |
} |
|
284 |
||
285 |
||
286 |
/** |
|
287 |
* Reads the index from the specified InputStream. |
|
288 |
* |
|
289 |
* @param is the input stream |
|
290 |
* @exception IOException if an I/O error has occurred |
|
291 |
*/ |
|
292 |
public void read(InputStream is) throws IOException { |
|
293 |
BufferedReader br = new BufferedReader |
|
294 |
(new InputStreamReader(is, "UTF8")); |
|
295 |
String line = null; |
|
296 |
String currentJar = null; |
|
297 |
||
298 |
/* an ordered list of jar file names */ |
|
299 |
Vector jars = new Vector(); |
|
300 |
||
301 |
/* read until we see a .jar line */ |
|
302 |
while((line = br.readLine()) != null && !line.endsWith(".jar")); |
|
303 |
||
304 |
for(;line != null; line = br.readLine()) { |
|
305 |
if (line.length() == 0) |
|
306 |
continue; |
|
307 |
||
308 |
if (line.endsWith(".jar")) { |
|
309 |
currentJar = line; |
|
310 |
jars.add(currentJar); |
|
311 |
} else { |
|
312 |
String name = line; |
|
313 |
addToList(name, currentJar, indexMap); |
|
314 |
addToList(currentJar, name, jarMap); |
|
315 |
} |
|
316 |
} |
|
317 |
||
318 |
jarFiles = (String[])jars.toArray(new String[jars.size()]); |
|
319 |
} |
|
320 |
||
321 |
/** |
|
322 |
* Merges the current index into another index, taking into account |
|
323 |
* the relative path of the current index. |
|
324 |
* |
|
325 |
* @param toIndex The destination index which the current index will |
|
326 |
* merge into. |
|
327 |
* @param path The relative path of the this index to the destination |
|
328 |
* index. |
|
329 |
* |
|
330 |
*/ |
|
331 |
public void merge(JarIndex toIndex, String path) { |
|
332 |
Iterator itr = indexMap.entrySet().iterator(); |
|
333 |
while(itr.hasNext()) { |
|
334 |
Map.Entry e = (Map.Entry)itr.next(); |
|
335 |
String packageName = (String)e.getKey(); |
|
336 |
LinkedList from_list = (LinkedList)e.getValue(); |
|
337 |
Iterator listItr = from_list.iterator(); |
|
338 |
while(listItr.hasNext()) { |
|
339 |
String jarName = (String)listItr.next(); |
|
340 |
if (path != null) { |
|
341 |
jarName = path.concat(jarName); |
|
342 |
} |
|
343 |
toIndex.add(packageName, jarName); |
|
344 |
} |
|
345 |
} |
|
346 |
} |
|
347 |
} |