28 import java.io.File;
29 import java.io.FilenameFilter;
30 import java.io.IOException;
31 import java.io.FileNotFoundException;
32 import java.util.StringTokenizer;
33 import java.util.Vector;
34 import java.util.Enumeration;
35 import java.util.jar.JarFile;
36 import java.util.jar.Manifest;
37 import java.util.jar.Attributes;
38 import java.util.jar.Attributes.Name;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.security.PrivilegedExceptionAction;
42 import java.security.PrivilegedActionException;
43 import java.net.URL;
44 import java.net.MalformedURLException;
45 import 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 *
69 * @deprecated this class will be removed in a future release.
70 * @author Jerome Dochez
71 */
72 @Deprecated
73 public class ExtensionDependency {
74
75 /* Callbak interfaces to delegate installation of missing extensions */
76 private static Vector<ExtensionInstallationProvider> providers;
77
78 /**
79 * <p>
80 * Register an ExtensionInstallationProvider. The provider is responsible
81 * for handling the installation (upgrade) of any missing extensions.
82 * </p>
83 * @param eip ExtensionInstallationProvider implementation
84 */
85 public synchronized static void addExtensionInstallationProvider
86 (ExtensionInstallationProvider eip)
87 {
88 if (providers == null) {
89 providers = new Vector<>();
90 }
91 providers.add(eip);
92 }
93
94 /**
95 * <p>
96 * Unregister a previously installed installation provider
97 * </p>
98 */
99 public synchronized static void removeExtensionInstallationProvider
100 (ExtensionInstallationProvider eip)
101 {
102 providers.remove(eip);
103 }
104
105 /**
106 * <p>
107 * Checks the dependencies of the jar file on installed extension.
108 * </p>
109 * @param jarFile containing the attriutes declaring the dependencies
110 */
111 public static boolean checkExtensionsDependencies(JarFile jar)
112 {
113 if (providers == null) {
114 // no need to bother, nobody is registered to install missing
115 // extensions
116 return true;
117 }
118
119 try {
120 ExtensionDependency extDep = new ExtensionDependency();
121 return extDep.checkExtensions(jar);
122 } catch (ExtensionInstallationException e) {
123 debug(e.getMessage());
124 }
125 return false;
126 }
127
128 /*
129 * Check for all declared required extensions in the jar file
165 " appers to depend on "
166 + extensionName + " but does not define the " +
167 extName + " attribute in its manifest ");
168
169 } else {
170 if (!checkExtension(extensionName, attr)) {
171 debug("Failed installing " + extensionName);
172 result = false;
173 }
174 }
175 }
176 } else {
177 debug("No dependencies for " + jar.getName());
178 }
179 }
180 return result;
181 }
182
183
184 /*
185 * <p>
186 * Check that a particular dependency on an extension is satisfied.
187 * </p>
188 * @param extensionName is the key used for the attributes in the manifest
189 * @param attr is the attributes of the manifest file
190 *
191 * @return true if the dependency is satisfied by the installed extensions
192 */
193 protected synchronized boolean checkExtension(final String extensionName,
194 final Attributes attr)
195 throws ExtensionInstallationException
196 {
197 debug("Checking extension " + extensionName);
198 if (checkExtensionAgainstInstalled(extensionName, attr))
199 return true;
200
201 debug("Extension not currently installed ");
202 ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
203 return installExtension(reqInfo, null);
204 }
205
206 /*
207 * <p>
208 * Check if a particular extension is part of the currently installed
209 * extensions.
210 * </p>
211 * @param extensionName is the key for the attributes in the manifest
212 * @param attr is the attributes of the manifest
213 *
214 * @return true if the requested extension is already installed
215 */
216 boolean checkExtensionAgainstInstalled(String extensionName,
217 Attributes attr)
218 throws ExtensionInstallationException
219 {
220 File fExtension = checkExtensionExists(extensionName);
221
222 if (fExtension != null) {
223 // Extension already installed, just check against this one
224 try {
225 if (checkExtensionAgainst(extensionName, attr, fExtension))
226 return true;
227 } catch (FileNotFoundException e) {
228 debugException(e);
229 } catch (IOException e) {
230 debugException(e);
245 debugException(e);
246 return false;
247 }
248
249 for (int i=0;i<installedExts.length;i++) {
250 try {
251 if (checkExtensionAgainst(extensionName, attr, installedExts[i]))
252 return true;
253 } catch (FileNotFoundException e) {
254 debugException(e);
255 } catch (IOException e) {
256 debugException(e);
257 // let's continue with the next installed extension
258 }
259 }
260 }
261 return false;
262 }
263
264 /*
265 * <p>
266 * Check if the requested extension described by the attributes
267 * in the manifest under the key extensionName is compatible with
268 * the jar file.
269 * </p>
270 *
271 * @param extensionName key in the attribute list
272 * @param attr manifest file attributes
273 * @param file installed extension jar file to compare the requested
274 * extension against.
275 */
276 protected boolean checkExtensionAgainst(String extensionName,
277 Attributes attr,
278 final File file)
279 throws IOException,
280 FileNotFoundException,
281 ExtensionInstallationException
282 {
283
284 debug("Checking extension " + extensionName +
285 " against " + file.getName());
286
287 // Load the jar file ...
288 Manifest man;
289 try {
320 case ExtensionInfo.COMPATIBLE:
321 debug("Extensions are compatible");
322 return true;
323
324 case ExtensionInfo.INCOMPATIBLE:
325 debug("Extensions are incompatible");
326 return false;
327
328 default:
329 // everything else
330 debug("Extensions require an upgrade or vendor switch");
331 return installExtension(reqInfo, instInfo);
332
333 }
334 }
335 }
336 return false;
337 }
338
339 /*
340 * <p>
341 * An required extension is missing, if an ExtensionInstallationProvider is
342 * registered, delegate the installation of that particular extension to it.
343 * </p>
344 *
345 * @param reqInfo Missing extension information
346 * @param instInfo Older installed version information
347 *
348 * @return true if the installation is successful
349 */
350 protected boolean installExtension(ExtensionInfo reqInfo,
351 ExtensionInfo instInfo)
352 throws ExtensionInstallationException
353 {
354 Vector<ExtensionInstallationProvider> currentProviders;
355 synchronized(providers) {
356 @SuppressWarnings("unchecked")
357 Vector<ExtensionInstallationProvider> tmp =
358 (Vector<ExtensionInstallationProvider>) providers.clone();
359 currentProviders = tmp;
360 }
361 for (Enumeration<ExtensionInstallationProvider> e = currentProviders.elements();
362 e.hasMoreElements();) {
363 ExtensionInstallationProvider eip = e.nextElement();
364
365 if (eip!=null) {
366 // delegate the installation to the provider
367 if (eip.installExtension(reqInfo, instInfo)) {
368 debug(reqInfo.name + " installation successful");
369 Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader)
370 Launcher.getLauncher().getClassLoader().getParent();
371 addNewExtensionsToClassLoader(cl);
372 return true;
373 }
374 }
375 }
376 // We have tried all of our providers, noone could install this
377 // extension, we just return failure at this point
378 debug(reqInfo.name + " installation failed");
379 return false;
380 }
381
382 /**
383 * <p>
384 * Checks if the extension, that is specified in the extension-list in
385 * the applet jar manifest, is already installed (i.e. exists in the
386 * extension directory).
387 * </p>
388 *
389 * @param extensionName extension name in the extension-list
390 *
391 * @return the extension if it exists in the extension directory
392 */
393 private File checkExtensionExists(String extensionName) {
394 // Function added to fix bug 4504166
395 final String extName = extensionName;
396 final String[] fileExt = {".jar", ".zip"};
397
398 return AccessController.doPrivileged(
399 new PrivilegedAction<File>() {
400 public File run() {
401 try {
402 File fExtension;
403 File[] dirs = getExtDirs();
404
405 // Search the extension directories for the extension that is specified
406 // in the attribute extension-list in the applet jar manifest
407 for (int i=0;i<dirs.length;i++) {
411 } else {
412 fExtension = new File(dirs[i], extName+fileExt[j]);
413 }
414 debug("checkExtensionExists:fileName " + fExtension.getName());
415 if (fExtension.exists()) {
416 return fExtension;
417 }
418 }
419 }
420 return null;
421
422 } catch(Exception e) {
423 debugException(e);
424 return null;
425 }
426 }
427 });
428 }
429
430 /**
431 * <p>
432 * @return the java.ext.dirs property as a list of directory
433 * </p>
434 */
435 private static File[] getExtDirs() {
436 String s = java.security.AccessController.doPrivileged(
437 new sun.security.action.GetPropertyAction("java.ext.dirs"));
438
439 File[] dirs;
440 if (s != null) {
441 StringTokenizer st =
442 new StringTokenizer(s, File.pathSeparator);
443 int count = st.countTokens();
444 debug("getExtDirs count " + count);
445 dirs = new File[count];
446 for (int i = 0; i < count; i++) {
447 dirs[i] = new File(st.nextToken());
448 debug("getExtDirs dirs["+i+"] "+ dirs[i]);
449 }
450 } else {
451 dirs = new File[0];
452 debug("getExtDirs dirs " + dirs);
453 }
454 debug("getExtDirs dirs.length " + dirs.length);
455 return dirs;
456 }
457
458 /*
459 * <p>
460 * Scan the directories and return all files installed in those
461 * </p>
462 * @param dirs list of directories to scan
463 *
464 * @return the list of files installed in all the directories
465 */
466 private static File[] getExtFiles(File[] dirs) throws IOException {
467 Vector<File> urls = new Vector<File>();
468 for (int i = 0; i < dirs.length; i++) {
469 String[] files = dirs[i].list(new JarFilter());
470 if (files != null) {
471 debug("getExtFiles files.length " + files.length);
472 for (int j = 0; j < files.length; j++) {
473 File f = new File(dirs[i], files[j]);
474 urls.add(f);
475 debug("getExtFiles f["+j+"] "+ f);
476 }
477 }
478 }
479 File[] ua = new File[urls.size()];
480 urls.copyInto(ua);
481 debug("getExtFiles ua.length " + ua.length);
482 return ua;
483 }
484
485 /*
486 * <p>
487 * @return the list of installed extensions jar files
488 * </p>
489 */
490 private File[] getInstalledExtensions() throws IOException {
491 return AccessController.doPrivileged(
492 new PrivilegedAction<File[]>() {
493 public File[] run() {
494 try {
495 return getExtFiles(getExtDirs());
496 } catch(IOException e) {
497 debug("Cannot get list of installed extensions");
498 debugException(e);
499 return new File[0];
500 }
501 }
502 });
503 }
504
505 /*
506 * <p>
507 * Add the newly installed jar file to the extension class loader.
508 * </p>
509 *
510 * @param cl the current installed extension class loader
511 *
512 * @return true if successful
513 */
514 private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) {
515 try {
516 File[] installedExts = getInstalledExtensions();
517 for (int i=0;i<installedExts.length;i++) {
518 final File instFile = installedExts[i];
519 URL instURL = AccessController.doPrivileged(
520 new PrivilegedAction<URL>() {
521 public URL run() {
522 try {
523 return ParseUtil.fileToEncodedURL(instFile);
524 } catch (MalformedURLException e) {
525 debugException(e);
526 return null;
527 }
528 }
|
28 import java.io.File;
29 import java.io.FilenameFilter;
30 import java.io.IOException;
31 import java.io.FileNotFoundException;
32 import java.util.StringTokenizer;
33 import java.util.Vector;
34 import java.util.Enumeration;
35 import java.util.jar.JarFile;
36 import java.util.jar.Manifest;
37 import java.util.jar.Attributes;
38 import java.util.jar.Attributes.Name;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.security.PrivilegedExceptionAction;
42 import java.security.PrivilegedActionException;
43 import java.net.URL;
44 import java.net.MalformedURLException;
45 import sun.net.www.ParseUtil;
46
47 /**
48 * This class checks dependent extensions a particular jar file may have
49 * declared through its manifest attributes.
50 * <p>
51 * Jar file declared dependent extensions through the extension-list
52 * attribute. The extension-list contains a list of keys used to
53 * fetch the other attributes describing the required extension.
54 * If key is the extension key declared in the extension-list
55 * attribute, the following describing attribute can be found in
56 * the manifest:
57 * <ul>
58 * <li>key-Extension-Name: (Specification package name)</li>
59 * <li>key-Specification-Version: (Specification-Version)</li>
60 * <li>key-Implementation-Version: (Implementation-Version)</li>
61 * <li>key-Implementation-Vendor-Id: (Imlementation-Vendor-Id)</li>
62 * <li>key-Implementation-Version: (Implementation version)</li>
63 * <li>key-Implementation-URL: (URL to download the requested extension)</li>
64 * </ul>
65 * <p>
66 * This class also maintain versioning consistency of installed
67 * extensions dependencies declared in jar file manifest.
68 *
69 * @deprecated this class will be removed in a future release.
70 * @author Jerome Dochez
71 */
72 @Deprecated
73 public class ExtensionDependency {
74
75 /* Callbak interfaces to delegate installation of missing extensions */
76 private static Vector<ExtensionInstallationProvider> providers;
77
78 /**
79 * Register an ExtensionInstallationProvider. The provider is responsible
80 * for handling the installation (upgrade) of any missing extensions.
81 *
82 * @param eip ExtensionInstallationProvider implementation
83 */
84 public synchronized static void addExtensionInstallationProvider
85 (ExtensionInstallationProvider eip)
86 {
87 if (providers == null) {
88 providers = new Vector<>();
89 }
90 providers.add(eip);
91 }
92
93 /**
94 * Unregister a previously installed installation provider
95 */
96 public synchronized static void removeExtensionInstallationProvider
97 (ExtensionInstallationProvider eip)
98 {
99 providers.remove(eip);
100 }
101
102 /**
103 * Checks the dependencies of the jar file on installed extension.
104 *
105 * @param jar containing the attributes declaring the dependencies
106 */
107 public static boolean checkExtensionsDependencies(JarFile jar)
108 {
109 if (providers == null) {
110 // no need to bother, nobody is registered to install missing
111 // extensions
112 return true;
113 }
114
115 try {
116 ExtensionDependency extDep = new ExtensionDependency();
117 return extDep.checkExtensions(jar);
118 } catch (ExtensionInstallationException e) {
119 debug(e.getMessage());
120 }
121 return false;
122 }
123
124 /*
125 * Check for all declared required extensions in the jar file
161 " appers to depend on "
162 + extensionName + " but does not define the " +
163 extName + " attribute in its manifest ");
164
165 } else {
166 if (!checkExtension(extensionName, attr)) {
167 debug("Failed installing " + extensionName);
168 result = false;
169 }
170 }
171 }
172 } else {
173 debug("No dependencies for " + jar.getName());
174 }
175 }
176 return result;
177 }
178
179
180 /*
181 * Check that a particular dependency on an extension is satisfied.
182 *
183 * @param extensionName is the key used for the attributes in the manifest
184 * @param attr is the attributes of the manifest file
185 *
186 * @return true if the dependency is satisfied by the installed extensions
187 */
188 protected synchronized boolean checkExtension(final String extensionName,
189 final Attributes attr)
190 throws ExtensionInstallationException
191 {
192 debug("Checking extension " + extensionName);
193 if (checkExtensionAgainstInstalled(extensionName, attr))
194 return true;
195
196 debug("Extension not currently installed ");
197 ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
198 return installExtension(reqInfo, null);
199 }
200
201 /*
202 * Check if a particular extension is part of the currently installed
203 * extensions.
204 *
205 * @param extensionName is the key for the attributes in the manifest
206 * @param attr is the attributes of the manifest
207 *
208 * @return true if the requested extension is already installed
209 */
210 boolean checkExtensionAgainstInstalled(String extensionName,
211 Attributes attr)
212 throws ExtensionInstallationException
213 {
214 File fExtension = checkExtensionExists(extensionName);
215
216 if (fExtension != null) {
217 // Extension already installed, just check against this one
218 try {
219 if (checkExtensionAgainst(extensionName, attr, fExtension))
220 return true;
221 } catch (FileNotFoundException e) {
222 debugException(e);
223 } catch (IOException e) {
224 debugException(e);
239 debugException(e);
240 return false;
241 }
242
243 for (int i=0;i<installedExts.length;i++) {
244 try {
245 if (checkExtensionAgainst(extensionName, attr, installedExts[i]))
246 return true;
247 } catch (FileNotFoundException e) {
248 debugException(e);
249 } catch (IOException e) {
250 debugException(e);
251 // let's continue with the next installed extension
252 }
253 }
254 }
255 return false;
256 }
257
258 /*
259 * Check if the requested extension described by the attributes
260 * in the manifest under the key extensionName is compatible with
261 * the jar file.
262 *
263 * @param extensionName key in the attribute list
264 * @param attr manifest file attributes
265 * @param file installed extension jar file to compare the requested
266 * extension against.
267 */
268 protected boolean checkExtensionAgainst(String extensionName,
269 Attributes attr,
270 final File file)
271 throws IOException,
272 FileNotFoundException,
273 ExtensionInstallationException
274 {
275
276 debug("Checking extension " + extensionName +
277 " against " + file.getName());
278
279 // Load the jar file ...
280 Manifest man;
281 try {
312 case ExtensionInfo.COMPATIBLE:
313 debug("Extensions are compatible");
314 return true;
315
316 case ExtensionInfo.INCOMPATIBLE:
317 debug("Extensions are incompatible");
318 return false;
319
320 default:
321 // everything else
322 debug("Extensions require an upgrade or vendor switch");
323 return installExtension(reqInfo, instInfo);
324
325 }
326 }
327 }
328 return false;
329 }
330
331 /*
332 * An required extension is missing, if an ExtensionInstallationProvider is
333 * registered, delegate the installation of that particular extension to it.
334 *
335 * @param reqInfo Missing extension information
336 * @param instInfo Older installed version information
337 *
338 * @return true if the installation is successful
339 */
340 protected boolean installExtension(ExtensionInfo reqInfo,
341 ExtensionInfo instInfo)
342 throws ExtensionInstallationException
343 {
344 Vector<ExtensionInstallationProvider> currentProviders;
345 synchronized(providers) {
346 @SuppressWarnings("unchecked")
347 Vector<ExtensionInstallationProvider> tmp =
348 (Vector<ExtensionInstallationProvider>) providers.clone();
349 currentProviders = tmp;
350 }
351 for (Enumeration<ExtensionInstallationProvider> e = currentProviders.elements();
352 e.hasMoreElements();) {
353 ExtensionInstallationProvider eip = e.nextElement();
354
355 if (eip!=null) {
356 // delegate the installation to the provider
357 if (eip.installExtension(reqInfo, instInfo)) {
358 debug(reqInfo.name + " installation successful");
359 Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader)
360 Launcher.getLauncher().getClassLoader().getParent();
361 addNewExtensionsToClassLoader(cl);
362 return true;
363 }
364 }
365 }
366 // We have tried all of our providers, noone could install this
367 // extension, we just return failure at this point
368 debug(reqInfo.name + " installation failed");
369 return false;
370 }
371
372 /**
373 * Checks if the extension, that is specified in the extension-list in
374 * the applet jar manifest, is already installed (i.e. exists in the
375 * extension directory).
376 *
377 * @param extensionName extension name in the extension-list
378 *
379 * @return the extension if it exists in the extension directory
380 */
381 private File checkExtensionExists(String extensionName) {
382 // Function added to fix bug 4504166
383 final String extName = extensionName;
384 final String[] fileExt = {".jar", ".zip"};
385
386 return AccessController.doPrivileged(
387 new PrivilegedAction<File>() {
388 public File run() {
389 try {
390 File fExtension;
391 File[] dirs = getExtDirs();
392
393 // Search the extension directories for the extension that is specified
394 // in the attribute extension-list in the applet jar manifest
395 for (int i=0;i<dirs.length;i++) {
399 } else {
400 fExtension = new File(dirs[i], extName+fileExt[j]);
401 }
402 debug("checkExtensionExists:fileName " + fExtension.getName());
403 if (fExtension.exists()) {
404 return fExtension;
405 }
406 }
407 }
408 return null;
409
410 } catch(Exception e) {
411 debugException(e);
412 return null;
413 }
414 }
415 });
416 }
417
418 /**
419 * @return the java.ext.dirs property as a list of directory
420 */
421 private static File[] getExtDirs() {
422 String s = java.security.AccessController.doPrivileged(
423 new sun.security.action.GetPropertyAction("java.ext.dirs"));
424
425 File[] dirs;
426 if (s != null) {
427 StringTokenizer st =
428 new StringTokenizer(s, File.pathSeparator);
429 int count = st.countTokens();
430 debug("getExtDirs count " + count);
431 dirs = new File[count];
432 for (int i = 0; i < count; i++) {
433 dirs[i] = new File(st.nextToken());
434 debug("getExtDirs dirs["+i+"] "+ dirs[i]);
435 }
436 } else {
437 dirs = new File[0];
438 debug("getExtDirs dirs " + dirs);
439 }
440 debug("getExtDirs dirs.length " + dirs.length);
441 return dirs;
442 }
443
444 /*
445 * Scan the directories and return all files installed in those
446 *
447 * @param dirs list of directories to scan
448 *
449 * @return the list of files installed in all the directories
450 */
451 private static File[] getExtFiles(File[] dirs) throws IOException {
452 Vector<File> urls = new Vector<File>();
453 for (int i = 0; i < dirs.length; i++) {
454 String[] files = dirs[i].list(new JarFilter());
455 if (files != null) {
456 debug("getExtFiles files.length " + files.length);
457 for (int j = 0; j < files.length; j++) {
458 File f = new File(dirs[i], files[j]);
459 urls.add(f);
460 debug("getExtFiles f["+j+"] "+ f);
461 }
462 }
463 }
464 File[] ua = new File[urls.size()];
465 urls.copyInto(ua);
466 debug("getExtFiles ua.length " + ua.length);
467 return ua;
468 }
469
470 /*
471 * @return the list of installed extensions jar files
472 */
473 private File[] getInstalledExtensions() throws IOException {
474 return AccessController.doPrivileged(
475 new PrivilegedAction<File[]>() {
476 public File[] run() {
477 try {
478 return getExtFiles(getExtDirs());
479 } catch(IOException e) {
480 debug("Cannot get list of installed extensions");
481 debugException(e);
482 return new File[0];
483 }
484 }
485 });
486 }
487
488 /*
489 * Add the newly installed jar file to the extension class loader.
490 *
491 * @param cl the current installed extension class loader
492 *
493 * @return true if successful
494 */
495 private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) {
496 try {
497 File[] installedExts = getInstalledExtensions();
498 for (int i=0;i<installedExts.length;i++) {
499 final File instFile = installedExts[i];
500 URL instURL = AccessController.doPrivileged(
501 new PrivilegedAction<URL>() {
502 public URL run() {
503 try {
504 return ParseUtil.fileToEncodedURL(instFile);
505 } catch (MalformedURLException e) {
506 debugException(e);
507 return null;
508 }
509 }
|