History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/misc/ExtensionDependency.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/misc/ExtensionDependency.java+568−0
@@ -0,0 +1,568 @@
1/*
2 * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package sun.misc;
27
28import java.io.File;
29import java.io.FilenameFilter;
30import java.io.IOException;
31import java.io.FileNotFoundException;
32import java.util.StringTokenizer;
33import java.util.Vector;
34import java.util.Enumeration;
35import java.util.jar.JarFile;
36import java.util.jar.Manifest;
37import java.util.jar.Attributes;
38import java.util.jar.Attributes.Name;
39import java.security.AccessController;
40import java.security.PrivilegedAction;
41import java.security.PrivilegedExceptionAction;
42import java.security.PrivilegedActionException;
43import java.net.URL;
44import java.net.MalformedURLException;
45import sun.net.www.ParseUtil;
46
47/**
48 * <p>
49 * This class checks dependent extensions a particular jar file may have
50 * declared through its manifest attributes.
51 * </p>
52 * Jar file declared dependent extensions through the extension-list
53 * attribute. The extension-list contains a list of keys used to
54 * fetch the other attributes describing the required extension.
55 * If key is the extension key declared in the extension-list
56 * attribute, the following describing attribute can be found in
57 * the manifest :
58 * key-Extension-Name: (Specification package name)
59 * key-Specification-Version: (Specification-Version)
60 * key-Implementation-Version: (Implementation-Version)
61 * key-Implementation-Vendor-Id: (Imlementation-Vendor-Id)
62 * key-Implementation-Version: (Implementation version)
63 * key-Implementation-URL: (URL to download the requested extension)
64 * <p>
65 * This class also maintain versioning consistency of installed
66 * extensions dependencies declared in jar file manifest.
67 * </p>
68 * @author Jerome Dochez
69 */
70public class ExtensionDependency {
71
72 /* Callbak interfaces to delegate installation of missing extensions */
73 private static Vector providers;
74
75 /**
76 * <p>
77 * Register an ExtensionInstallationProvider. The provider is responsible
78 * for handling the installation (upgrade) of any missing extensions.
79 * </p>
80 * @param eip ExtensionInstallationProvider implementation
81 */
82 public synchronized static void addExtensionInstallationProvider
83 (ExtensionInstallationProvider eip)
84 {
85 if (providers == null) {
86 providers = new Vector();
87 }
88 providers.add(eip);
89 }
90
91 /**
92 * <p>
93 * Unregister a previously installed installation provider
94 * </p>
95 */
96 public synchronized static void removeExtensionInstallationProvider
97 (ExtensionInstallationProvider eip)
98 {
99 providers.remove(eip);
100 }
101
102 /**
103 * <p>
104 * Checks the dependencies of the jar file on installed extension.
105 * </p>
106 * @param jarFile containing the attriutes declaring the dependencies
107 */
108 public static boolean checkExtensionsDependencies(JarFile jar)
109 {
110 if (providers == null) {
111 // no need to bother, nobody is registered to install missing
112 // extensions
113 return true;
114 }
115
116 try {
117 ExtensionDependency extDep = new ExtensionDependency();
118 return extDep.checkExtensions(jar);
119 } catch (ExtensionInstallationException e) {
120 debug(e.getMessage());
121 }
122 return false;
123 }
124
125 /*
126 * Check for all declared required extensions in the jar file
127 * manifest.
128 */
129 protected boolean checkExtensions(JarFile jar)
130 throws ExtensionInstallationException
131 {
132 Manifest man;
133 try {
134 man = jar.getManifest();
135 } catch (IOException e) {
136 return false;
137 }
138
139 if (man == null) {
140 // The applet does not define a manifest file, so
141 // we just assume all dependencies are satisfied.
142 return true;
143 }
144
145 boolean result = true;
146 Attributes attr = man.getMainAttributes();
147 if (attr != null) {
148 // Let's get the list of declared dependencies
149 String value = attr.getValue(Name.EXTENSION_LIST);
150 if (value != null) {
151 StringTokenizer st = new StringTokenizer(value);
152 // Iterate over all declared dependencies
153 while (st.hasMoreTokens()) {
154 String extensionName = st.nextToken();
155 debug("The file " + jar.getName() +
156 " appears to depend on " + extensionName);
157 // Sanity Check
158 String extName = extensionName + "-" +
159 Name.EXTENSION_NAME.toString();
160 if (attr.getValue(extName) == null) {
161 debug("The jar file " + jar.getName() +
162 " appers to depend on "
163 + extensionName + " but does not define the " +
164 extName + " attribute in its manifest ");
165
166 } else {
167 if (!checkExtension(extensionName, attr)) {
168 debug("Failed installing " + extensionName);
169 result = false;
170 }
171 }
172 }
173 } else {
174 debug("No dependencies for " + jar.getName());
175 }
176 }
177 return result;
178 }
179
180
181 /*
182 * <p>
183 * Check that a particular dependency on an extension is satisfied.
184 * </p>
185 * @param extensionName is the key used for the attributes in the manifest
186 * @param attr is the attributes of the manifest file
187 *
188 * @return true if the dependency is satisfied by the installed extensions
189 */
190 protected synchronized boolean checkExtension(final String extensionName,
191 final Attributes attr)
192 throws ExtensionInstallationException
193 {
194 debug("Checking extension " + extensionName);
195 if (checkExtensionAgainstInstalled(extensionName, attr))
196 return true;
197
198 debug("Extension not currently installed ");
199 ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
200 return installExtension(reqInfo, null);
201 }
202
203 /*
204 * <p>
205 * Check if a particular extension is part of the currently installed
206 * extensions.
207 * </p>
208 * @param extensionName is the key for the attributes in the manifest
209 * @param attr is the attributes of the manifest
210 *
211 * @return true if the requested extension is already installed
212 */
213 boolean checkExtensionAgainstInstalled(String extensionName,
214 Attributes attr)
215 throws ExtensionInstallationException
216 {
217 File fExtension = checkExtensionExists(extensionName);
218
219 if (fExtension != null) {
220 // Extension already installed, just check against this one
221 try {
222 if (checkExtensionAgainst(extensionName, attr, fExtension))
223 return true;
224 } catch (FileNotFoundException e) {
225 debugException(e);
226 } catch (IOException e) {
227 debugException(e);
228 }
229 return false;
230
231 } else {
232 // Not sure if extension is already installed, so check all the
233 // installed extension jar files to see if we get a match
234
235 File[] installedExts;
236
237 try {
238 // Get the list of installed extension jar files so we can
239 // compare the installed versus the requested extension
240 installedExts = getInstalledExtensions();
241 } catch(IOException e) {
242 debugException(e);
243 return false;
244 }
245
246 for (int i=0;i<installedExts.length;i++) {
247 try {
248 if (checkExtensionAgainst(extensionName, attr, installedExts[i]))
249 return true;
250 } catch (FileNotFoundException e) {
251 debugException(e);
252 } catch (IOException e) {
253 debugException(e);
254 // let's continue with the next installed extension
255 }
256 }
257 }
258 return false;
259 }
260
261 /*
262 * <p>
263 * Check if the requested extension described by the attributes
264 * in the manifest under the key extensionName is compatible with
265 * the jar file.
266 * </p>
267 *
268 * @param extensionName key in the attibute list
269 * @param attr manifest file attributes
270 * @param file installed extension jar file to compare the requested
271 * extension against.
272 */
273 protected boolean checkExtensionAgainst(String extensionName,
274 Attributes attr,
275 final File file)
276 throws IOException,
277 FileNotFoundException,
278 ExtensionInstallationException
279 {
280
281 debug("Checking extension " + extensionName +
282 " against " + file.getName());
283
284 // Load the jar file ...
285 Manifest man;
286 try {
287 man = AccessController.doPrivileged(
288 new PrivilegedExceptionAction<Manifest>() {
289 public Manifest run()
290 throws IOException, FileNotFoundException {
291 if (!file.exists())
292 throw new FileNotFoundException(file.getName());
293 JarFile jarFile = new JarFile(file);
294 return jarFile.getManifest();
295 }
296 });
297 } catch(PrivilegedActionException e) {
298 if (e.getException() instanceof FileNotFoundException)
299 throw (FileNotFoundException) e.getException();
300 throw (IOException) e.getException();
301 }
302
303 // Construct the extension information object
304 ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
305 debug("Requested Extension : " + reqInfo);
306
307 int isCompatible = ExtensionInfo.INCOMPATIBLE;
308 ExtensionInfo instInfo = null;
309
310 if (man != null) {
311 Attributes instAttr = man.getMainAttributes();
312 if (instAttr != null) {
313 instInfo = new ExtensionInfo(null, instAttr);
314 debug("Extension Installed " + instInfo);
315 isCompatible = instInfo.isCompatibleWith(reqInfo);
316 switch(isCompatible) {
317 case ExtensionInfo.COMPATIBLE:
318 debug("Extensions are compatible");
319 return true;
320
321 case ExtensionInfo.INCOMPATIBLE:
322 debug("Extensions are incompatible");
323 return false;
324
325 default:
326 // everything else
327 debug("Extensions require an upgrade or vendor switch");
328 return installExtension(reqInfo, instInfo);
329
330 }
331 }
332 }
333 return false;
334 }
335
336 /*
337 * <p>
338 * An required extension is missing, if an ExtensionInstallationProvider is
339 * registered, delegate the installation of that particular extension to it.
340 * </p>
341 *
342 * @param reqInfo Missing extension information
343 * @param instInfo Older installed version information
344 *
345 * @return true if the installation is successful
346 */
347 protected boolean installExtension(ExtensionInfo reqInfo,
348 ExtensionInfo instInfo)
349 throws ExtensionInstallationException
350 {
351
352 Vector currentProviders;
353 synchronized(providers) {
354 currentProviders = (Vector) providers.clone();
355 }
356 for (Enumeration e=currentProviders.elements();e.hasMoreElements();) {
357 ExtensionInstallationProvider eip =
358 (ExtensionInstallationProvider) e.nextElement();
359
360 if (eip!=null) {
361 // delegate the installation to the provider
362 if (eip.installExtension(reqInfo, instInfo)) {
363 debug(reqInfo.name + " installation successful");
364 Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader)
365 Launcher.getLauncher().getClassLoader().getParent();
366 addNewExtensionsToClassLoader(cl);
367 return true;
368 }
369 }
370 }
371 // We have tried all of our providers, noone could install this
372 // extension, we just return failure at this point
373 debug(reqInfo.name + " installation failed");
374 return false;
375 }
376
377 /**
378 * <p>
379 * Checks if the extension, that is specified in the extension-list in
380 * the applet jar manifest, is already installed (i.e. exists in the
381 * extension directory).
382 * </p>
383 *
384 * @param extensionName extension name in the extension-list
385 *
386 * @return the extension if it exists in the extension directory
387 */
388 private File checkExtensionExists(String extensionName) {
389 // Function added to fix bug 4504166
390 final String extName = extensionName;
391 final String[] fileExt = {".jar", ".zip"};
392
393 return AccessController.doPrivileged(
394 new PrivilegedAction<File>() {
395 public File run() {
396 try {
397 File fExtension;
398 File[] dirs = getExtDirs();
399
400 // Search the extension directories for the extension that is specified
401 // in the attribute extension-list in the applet jar manifest
402 for (int i=0;i<dirs.length;i++) {
403 for (int j=0;j<fileExt.length;j++) {
404 if (extName.toLowerCase().endsWith(fileExt[j])) {
405 fExtension = new File(dirs[i], extName);
406 } else {
407 fExtension = new File(dirs[i], extName+fileExt[j]);
408 }
409 debug("checkExtensionExists:fileName " + fExtension.getName());
410 if (fExtension.exists()) {
411 return fExtension;
412 }
413 }
414 }
415 return null;
416
417 } catch(Exception e) {
418 debugException(e);
419 return null;
420 }
421 }
422 });
423 }
424
425 /**
426 * <p>
427 * @return the java.ext.dirs property as a list of directory
428 * </p>
429 */
430 private static File[] getExtDirs() {
431 String s = java.security.AccessController.doPrivileged(
432 new sun.security.action.GetPropertyAction("java.ext.dirs"));
433
434 File[] dirs;
435 if (s != null) {
436 StringTokenizer st =
437 new StringTokenizer(s, File.pathSeparator);
438 int count = st.countTokens();
439 debug("getExtDirs count " + count);
440 dirs = new File[count];
441 for (int i = 0; i < count; i++) {
442 dirs[i] = new File(st.nextToken());
443 debug("getExtDirs dirs["+i+"] "+ dirs[i]);
444 }
445 } else {
446 dirs = new File[0];
447 debug("getExtDirs dirs " + dirs);
448 }
449 debug("getExtDirs dirs.length " + dirs.length);
450 return dirs;
451 }
452
453 /*
454 * <p>
455 * Scan the directories and return all files installed in those
456 * </p>
457 * @param dirs list of directories to scan
458 *
459 * @return the list of files installed in all the directories
460 */
461 private static File[] getExtFiles(File[] dirs) throws IOException {
462 Vector<File> urls = new Vector<File>();
463 for (int i = 0; i < dirs.length; i++) {
464 String[] files = dirs[i].list(new JarFilter());
465 if (files != null) {
466 debug("getExtFiles files.length " + files.length);
467 for (int j = 0; j < files.length; j++) {
468 File f = new File(dirs[i], files[j]);
469 urls.add(f);
470 debug("getExtFiles f["+j+"] "+ f);
471 }
472 }
473 }
474 File[] ua = new File[urls.size()];
475 urls.copyInto(ua);
476 debug("getExtFiles ua.length " + ua.length);
477 return ua;
478 }
479
480 /*
481 * <p>
482 * @return the list of installed extensions jar files
483 * </p>
484 */
485 private File[] getInstalledExtensions() throws IOException {
486 return AccessController.doPrivileged(
487 new PrivilegedAction<File[]>() {
488 public File[] run() {
489 try {
490 return getExtFiles(getExtDirs());
491 } catch(IOException e) {
492 debug("Cannot get list of installed extensions");
493 debugException(e);
494 return new File[0];
495 }
496 }
497 });
498 }
499
500 /*
501 * <p>
502 * Add the newly installed jar file to the extension class loader.
503 * </p>
504 *
505 * @param cl the current installed extension class loader
506 *
507 * @return true if successful
508 */
509 private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) {
510 try {
511 File[] installedExts = getInstalledExtensions();
512 for (int i=0;i<installedExts.length;i++) {
513 final File instFile = installedExts[i];
514 URL instURL = AccessController.doPrivileged(
515 new PrivilegedAction<URL>() {
516 public URL run() {
517 try {
518 return ParseUtil.fileToEncodedURL(instFile);
519 } catch (MalformedURLException e) {
520 debugException(e);
521 return null;
522 }
523 }
524 });
525 if (instURL != null) {
526 URL[] urls = cl.getURLs();
527 boolean found=false;
528 for (int j = 0; j<urls.length; j++) {
529 debug("URL["+j+"] is " + urls[j] + " looking for "+
530 instURL);
531 if (urls[j].toString().compareToIgnoreCase(
532 instURL.toString())==0) {
533 found=true;
534 debug("Found !");
535 }
536 }
537 if (!found) {
538 debug("Not Found ! adding to the classloader " +
539 instURL);
540 cl.addExtURL(instURL);
541 }
542 }
543 }
544 } catch (MalformedURLException e) {
545 e.printStackTrace();
546 } catch (IOException e) {
547 e.printStackTrace();
548 // let's continue with the next installed extension
549 }
550 return Boolean.TRUE;
551 }
552
553 // True to display all debug and trace messages
554 static final boolean DEBUG = false;
555
556 private static void debug(String s) {
557 if (DEBUG) {
558 System.err.println(s);
559 }
560 }
561
562 private void debugException(Throwable e) {
563 if (DEBUG) {
564 e.printStackTrace();
565 }
566 }
567
568}