KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > java > plugin > standard > StandardPluginClassLoader


1 /*****************************************************************************
2  * Java Plug-in Framework (JPF)
3  * Copyright (C) 2004-2007 Dmitry Olshansky
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *****************************************************************************/

19 package org.java.plugin.standard;
20
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.net.URLClassLoader JavaDoc;
30 import java.security.AccessController JavaDoc;
31 import java.security.CodeSource JavaDoc;
32 import java.security.PrivilegedAction JavaDoc;
33 import java.security.ProtectionDomain JavaDoc;
34 import java.util.Arrays JavaDoc;
35 import java.util.Collections JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.HashMap JavaDoc;
38 import java.util.HashSet JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.LinkedList JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Map JavaDoc;
43 import java.util.Set JavaDoc;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.java.plugin.PathResolver;
48 import org.java.plugin.PluginClassLoader;
49 import org.java.plugin.PluginManager;
50 import org.java.plugin.registry.Library;
51 import org.java.plugin.registry.PluginDescriptor;
52 import org.java.plugin.registry.PluginPrerequisite;
53 import org.java.plugin.registry.PluginRegistry;
54 import org.java.plugin.util.IoUtil;
55
56 /**
57  * Standard implementation of plug-in class loader.
58  * @version $Id: StandardPluginClassLoader.java,v 1.22 2007/01/05 13:32:09 ddimon Exp $
59  */

60 public class StandardPluginClassLoader extends PluginClassLoader {
61     static Log log = LogFactory.getLog(StandardPluginClassLoader.class);
62     
63     private static File JavaDoc libCacheFolder;
64     private static boolean libCacheFolderInitialized = false;
65     
66     private static URL JavaDoc getClassBaseUrl(final Class JavaDoc cls) {
67         ProtectionDomain JavaDoc pd = cls.getProtectionDomain();
68         if (pd != null) {
69             CodeSource JavaDoc cs = pd.getCodeSource();
70             if (cs != null) {
71                 return cs.getLocation();
72             }
73         }
74         return null;
75     }
76
77     private static URL JavaDoc[] getUrls(final PluginManager manager,
78             final PluginDescriptor descr) {
79         List JavaDoc result = new LinkedList JavaDoc();
80         for (Iterator JavaDoc it = descr.getLibraries().iterator(); it.hasNext();) {
81             Library lib = (Library) it.next();
82             if (!lib.isCodeLibrary()) {
83                 continue;
84             }
85             result.add(manager.getPathResolver().resolvePath(lib,
86                     lib.getPath()));
87         }
88         if (log.isDebugEnabled()) {
89             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
90             buf.append("Code URL's populated for plug-in " //$NON-NLS-1$
91
+ descr + ":\r\n"); //$NON-NLS-1$
92
for (Iterator JavaDoc it = result.iterator(); it.hasNext();) {
93                 buf.append("\t"); //$NON-NLS-1$
94
buf.append(it.next());
95                 buf.append("\r\n"); //$NON-NLS-1$
96
}
97             log.debug(buf.toString());
98         }
99         return (URL JavaDoc[]) result.toArray(new URL JavaDoc[result.size()]);
100     }
101     
102     private static URL JavaDoc[] getUrls(final PluginManager manager,
103             final PluginDescriptor descr, final URL JavaDoc[] existingUrls) {
104         List JavaDoc urls = Arrays.asList(existingUrls);
105         List JavaDoc result = new LinkedList JavaDoc();
106         for (Iterator JavaDoc it = descr.getLibraries().iterator(); it.hasNext();) {
107             Library lib = (Library) it.next();
108             if (!lib.isCodeLibrary()) {
109                 continue;
110             }
111             URL JavaDoc url = manager.getPathResolver().resolvePath(lib, lib.getPath());
112             if (!urls.contains(url)) {
113                 result.add(url);
114             }
115         }
116         return (URL JavaDoc[]) result.toArray(new URL JavaDoc[result.size()]);
117     }
118     
119     private static File JavaDoc getLibCacheFolder() {
120         if (libCacheFolder != null) {
121             return libCacheFolderInitialized ? libCacheFolder : null;
122         }
123         synchronized (StandardPluginClassLoader.class) {
124             libCacheFolder = new File JavaDoc(System.getProperty("java.io.tmpdir"), //$NON-NLS-1$
125
System.currentTimeMillis() + ".jpf-lib-cache"); //$NON-NLS-1$
126
log.debug("libraries cache folder is " + libCacheFolder); //$NON-NLS-1$
127
File JavaDoc lockFile = new File JavaDoc(libCacheFolder, "lock"); //$NON-NLS-1$
128
if (lockFile.exists()) {
129                 log.error("can't initialize libraries cache folder " //$NON-NLS-1$
130
+ libCacheFolder + " as lock file indicates that it" //$NON-NLS-1$
131
+ " is owned by another JPF instance"); //$NON-NLS-1$
132
return null;
133             }
134             if (libCacheFolder.exists()) {
135                 // clean up folder
136
IoUtil.emptyFolder(libCacheFolder);
137             } else {
138                 libCacheFolder.mkdirs();
139             }
140             try {
141                 if (!lockFile.createNewFile()) {
142                     log.error("can\'t create lock file in JPF libraries cache" //$NON-NLS-1$
143
+ " folder " + libCacheFolder); //$NON-NLS-1$
144
return null;
145                 }
146             } catch (IOException JavaDoc ioe) {
147                 log.error("can\'t create lock file in JPF libraries cache" //$NON-NLS-1$
148
+ " folder " + libCacheFolder, ioe); //$NON-NLS-1$
149
return null;
150             }
151             lockFile.deleteOnExit();
152             libCacheFolder.deleteOnExit();
153             libCacheFolderInitialized = true;
154         }
155         return libCacheFolder;
156     }
157     
158     private PluginDescriptor[] publicImports;
159     private PluginDescriptor[] privateImports;
160     private PluginDescriptor[] reverseLookups;
161     private PluginResourceLoader resourceLoader;
162     private Map JavaDoc resourceFilters; // <lib URL, ResourceFilter>
163
private Map JavaDoc libraryCache; // <lib URL, File>
164
private boolean probeParentLoaderLast;
165
166     /**
167      * Creates class instance configured to load classes and resources for
168      * given plug-in.
169      * @param aManager plug-in manager instance
170      * @param descr plug-in descriptor
171      * @param parent parent class loader, usually this is JPF "host"
172      * application class loader
173      */

174     public StandardPluginClassLoader(final PluginManager aManager,
175             final PluginDescriptor descr, final ClassLoader JavaDoc parent) {
176         super(aManager, descr, getUrls(aManager, descr), parent);
177         collectImports();
178         resourceLoader = PluginResourceLoader.get(aManager, descr);
179         collectFilters();
180         libraryCache = new HashMap JavaDoc();
181     }
182     
183     protected void collectImports() {
184         // collect imported plug-ins (exclude duplicates)
185
Map JavaDoc publicImportsMap = new HashMap JavaDoc(); //<plug-in ID, PluginDescriptor>
186
Map JavaDoc privateImportsMap = new HashMap JavaDoc(); //<plug-in ID, PluginDescriptor>
187
PluginRegistry registry = getPluginDescriptor().getRegistry();
188         for (Iterator JavaDoc it = getPluginDescriptor().getPrerequisites().iterator();
189                 it.hasNext();) {
190             PluginPrerequisite pre = (PluginPrerequisite) it.next();
191             if (!pre.matches()) {
192                 continue;
193             }
194             PluginDescriptor preDescr =
195                 registry.getPluginDescriptor(pre.getPluginId());
196             if (pre.isExported()) {
197                 publicImportsMap.put(preDescr.getId(), preDescr);
198             } else {
199                 privateImportsMap.put(preDescr.getId(), preDescr);
200             }
201         }
202         publicImports = (PluginDescriptor[]) publicImportsMap.values().toArray(
203                 new PluginDescriptor[publicImportsMap.size()]);
204         privateImports =
205             (PluginDescriptor[]) privateImportsMap.values().toArray(
206                 new PluginDescriptor[privateImportsMap.size()]);
207         // collect reverse look up plug-ins (exclude duplicates)
208
Map JavaDoc reverseLookupsMap = new HashMap JavaDoc(); //<plug-in ID, PluginDescriptor>
209
for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
210                 it.hasNext();) {
211             PluginDescriptor descr = (PluginDescriptor) it.next();
212             if (descr.equals(getPluginDescriptor())
213                     || publicImportsMap.containsKey(descr.getId())
214                     || privateImportsMap.containsKey(descr.getId())) {
215                 continue;
216             }
217             for (Iterator JavaDoc it2 = descr.getPrerequisites().iterator();
218                     it2.hasNext();) {
219                 PluginPrerequisite pre = (PluginPrerequisite) it2.next();
220                 if (!pre.getPluginId().equals(getPluginDescriptor().getId())
221                         || !pre.isReverseLookup()) {
222                     continue;
223                 }
224                 if (!pre.matches()) {
225                     continue;
226                 }
227                 reverseLookupsMap.put(descr.getId(), descr);
228                 break;
229             }
230         }
231         reverseLookups =
232             (PluginDescriptor[]) reverseLookupsMap.values().toArray(
233                 new PluginDescriptor[reverseLookupsMap.size()]);
234     }
235     
236     protected void collectFilters() {
237         if (resourceFilters == null) {
238             resourceFilters = new HashMap JavaDoc();
239         } else {
240             resourceFilters.clear();
241         }
242         for (Iterator JavaDoc it = getPluginDescriptor().getLibraries().iterator();
243                 it.hasNext();) {
244             Library lib = (Library) it.next();
245             resourceFilters.put(
246                     getPluginManager().getPathResolver().resolvePath(lib,
247                             lib.getPath()).toExternalForm(),
248                             new ResourceFilter(lib));
249         }
250     }
251     
252     /**
253      * @see org.java.plugin.PluginClassLoader#pluginsSetChanged()
254      */

255     protected void pluginsSetChanged() {
256         URL JavaDoc[] newUrls = getUrls(getPluginManager(), getPluginDescriptor(),
257                 getURLs());
258         for (int i = 0; i < newUrls.length; i++) {
259             addURL(newUrls[i]);
260         }
261         if (log.isDebugEnabled()) {
262             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
263             buf.append("New code URL's populated for plug-in " //$NON-NLS-1$
264
+ getPluginDescriptor() + ":\r\n"); //$NON-NLS-1$
265
for (int i = 0; i < newUrls.length; i++) {
266                 buf.append("\t"); //$NON-NLS-1$
267
buf.append(newUrls[i]);
268                 buf.append("\r\n"); //$NON-NLS-1$
269
}
270             log.debug(buf.toString());
271         }
272         collectImports();
273         // repopulate resource URLs
274
resourceLoader =
275             PluginResourceLoader.get(getPluginManager(), getPluginDescriptor());
276         collectFilters();
277         for (Iterator JavaDoc it = libraryCache.entrySet().iterator(); it.hasNext();) {
278             if (((Map.Entry JavaDoc) it.next()).getValue() == null) {
279                 it.remove();
280             }
281         }
282     }
283     
284     /**
285      * @see org.java.plugin.PluginClassLoader#dispose()
286      */

287     protected void dispose() {
288         for (Iterator JavaDoc it = libraryCache.values().iterator(); it.hasNext();) {
289             ((File JavaDoc) it.next()).delete();
290         }
291         libraryCache.clear();
292         resourceFilters.clear();
293         privateImports = null;
294         publicImports = null;
295         resourceLoader = null;
296     }
297     
298     protected void setProbeParentLoaderLast(final boolean value) {
299         probeParentLoaderLast = value;
300     }
301     
302     /**
303      * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
304      */

305     protected Class JavaDoc loadClass(final String JavaDoc name, final boolean resolve)
306             throws ClassNotFoundException JavaDoc {
307         /*log.debug("loadClass(String, boolean): name=" + name + ", this="
308                 + this);*/

309         Class JavaDoc result;
310         if (probeParentLoaderLast) {
311             try {
312                 result = loadClass(name, resolve, this, null);
313             } catch (ClassNotFoundException JavaDoc cnfe) {
314                 result = getParent().loadClass(name);
315             }
316             if (result == null) {
317                 result = getParent().loadClass(name);
318             }
319         } else {
320             try {
321                 result = getParent().loadClass(name);
322             } catch (ClassNotFoundException JavaDoc cnfe) {
323                 result = loadClass(name, resolve, this, null);
324             }
325         }
326         if (result != null) {
327             return result;
328         }
329         throw new ClassNotFoundException JavaDoc(name);
330     }
331     
332     protected Class JavaDoc loadClass(final String JavaDoc name, final boolean resolve,
333             final StandardPluginClassLoader requestor, final Set JavaDoc seenPlugins)
334             throws ClassNotFoundException JavaDoc {
335         /*log.debug("loadClass(String, boolean, ...): name=" + name + ", this="
336                 + this);*/

337         Set JavaDoc seen = seenPlugins;
338         if ((seen != null) && seen.contains(getPluginDescriptor().getId())) {
339             return null;
340         }
341         if ((this != requestor)
342                 && !getPluginManager().isPluginActivated(getPluginDescriptor())
343                 && !getPluginManager().isPluginActivating(
344                         getPluginDescriptor())) {
345             String JavaDoc msg = "can't load class " + name + ", plug-in " //$NON-NLS-1$ //$NON-NLS-2$
346
+ getPluginDescriptor() + " is not activated yet"; //$NON-NLS-1$
347
log.warn(msg);
348             throw new ClassNotFoundException JavaDoc(msg);
349         }
350         Class JavaDoc result = null;
351         synchronized (this) {
352             result = findLoadedClass(name);
353             if (result != null) {
354                 if (log.isDebugEnabled()) {
355                     log.debug("loadClass(...): found loaded class, class=" //$NON-NLS-1$
356
+ result + ", this=" //$NON-NLS-1$
357
+ this + ", requestor=" + requestor); //$NON-NLS-1$
358
}
359                 checkClassVisibility(result, requestor);
360                 /*if (resolve) {
361                     resolveClass(result);
362                 }*/

363                 return result; // found already loaded class in this plug-in
364
}
365             try {
366                 synchronized (getClass()) {
367                     result = findClass(name);
368                 }
369             } catch (LinkageError JavaDoc le) {
370                 if (log.isDebugEnabled()) {
371                     log.debug("loadClass(...): class loading failed," //$NON-NLS-1$
372
+ " name=" + name + ", this=" //$NON-NLS-1$ //$NON-NLS-2$
373
+ this + ", requestor=" + requestor, le); //$NON-NLS-1$
374
}
375                 throw le;
376              } catch (ClassNotFoundException JavaDoc cnfe) {
377                 // ignore
378
}
379             if (result != null) {
380                 if (log.isDebugEnabled()) {
381                     log.debug("loadClass(...): found class, class=" //$NON-NLS-1$
382
+ result + ", this=" //$NON-NLS-1$
383
+ this + ", requestor=" + requestor); //$NON-NLS-1$
384
}
385                 checkClassVisibility(result, requestor);
386                 if (resolve) {
387                     resolveClass(result);
388                 }
389                 return result; // found class in this plug-in
390
}
391         }
392         if (seen == null) {
393             seen = new HashSet JavaDoc();
394         }
395         if (log.isDebugEnabled()) {
396             log.debug("loadClass(...): class not found, name=" //$NON-NLS-1$
397
+ name + ", this=" //$NON-NLS-1$
398
+ this + ", requestor=" + requestor); //$NON-NLS-1$
399
}
400         seen.add(getPluginDescriptor().getId());
401         for (int i = 0; i < publicImports.length; i++) {
402             if (seen.contains(publicImports[i].getId())) {
403                 continue;
404             }
405             result = ((StandardPluginClassLoader) getPluginManager()
406                     .getPluginClassLoader(publicImports[i])).loadClass(
407                             name, resolve, requestor, seen);
408             if (result != null) {
409                 /*if (resolve) {
410                     resolveClass(result);
411                 }*/

412                 break; // found class in publicly imported plug-in
413
}
414         }
415         if ((this == requestor) && (result == null)) {
416             for (int i = 0; i < privateImports.length; i++) {
417                 if (seen.contains(privateImports[i].getId())) {
418                     continue;
419                 }
420                 result = ((StandardPluginClassLoader) getPluginManager()
421                         .getPluginClassLoader(privateImports[i])).loadClass(
422                                 name, resolve, requestor, seen);
423                 if (result != null) {
424                     /*if (resolve) {
425                         resolveClass(result);
426                     }*/

427                     break; // found class in privately imported plug-in
428
}
429             }
430         }
431         if ((this == requestor) && (result == null)) {
432             for (int i = 0; i < reverseLookups.length; i++) {
433                 PluginDescriptor descr = reverseLookups[i];
434                 if (seen.contains(descr.getId())) {
435                     continue;
436                 }
437                 if (!getPluginManager().isPluginActivated(descr)
438                         && !getPluginManager().isPluginActivating(descr)) {
439                     continue;
440                 }
441                 result = ((StandardPluginClassLoader) getPluginManager()
442                         .getPluginClassLoader(descr)).loadClass(
443                                 name, resolve, requestor, seen);
444                 if (result != null) {
445                     /*if (resolve) {
446                         resolveClass(result);
447                     }*/

448                     break; // found class in plug-in that marks itself as
449
// allowed reverse look up
450
}
451             }
452         }
453         return result;
454     }
455     
456     protected void checkClassVisibility(final Class JavaDoc cls,
457             final StandardPluginClassLoader requestor)
458             throws ClassNotFoundException JavaDoc {
459         /*log.debug("checkClassVisibility(Class, PluginClassLoader): class=" //$NON-NLS-1$
460                 + cls.getName() + ", requestor=" + requestor //$NON-NLS-1$
461                 + ", this=" + this); //$NON-NLS-1$*/

462         if (this == requestor) {
463             return;
464         }
465         URL JavaDoc lib = getClassBaseUrl(cls);
466         if (lib == null) {
467             return; // cls is a system class
468
}
469         ClassLoader JavaDoc loader = cls.getClassLoader();
470         if (!(loader instanceof StandardPluginClassLoader)) {
471             return;
472         }
473         if (loader != this) {
474             ((StandardPluginClassLoader) loader).checkClassVisibility(cls,
475                     requestor);
476         } else {
477             ResourceFilter filter =
478                 (ResourceFilter) resourceFilters.get(lib.toExternalForm());
479             if (filter == null) {
480                 log.warn("class not visible, no class filter found, lib=" + lib //$NON-NLS-1$
481
+ ", class=" + cls + ", this=" + this //$NON-NLS-1$ //$NON-NLS-2$
482
+ ", requestor=" + requestor); //$NON-NLS-1$
483
throw new ClassNotFoundException JavaDoc("class " //$NON-NLS-1$
484
+ cls.getName() + " is not visible for plug-in " //$NON-NLS-1$
485
+ requestor.getPluginDescriptor().getId()
486                         + ", no filter found for library " + lib); //$NON-NLS-1$
487
}
488             if (!filter.isClassVisible(cls.getName())) {
489                 log.warn("class not visible, lib=" + lib //$NON-NLS-1$
490
+ ", class=" + cls + ", this=" + this //$NON-NLS-1$ //$NON-NLS-2$
491
+ ", requestor=" + requestor); //$NON-NLS-1$
492
throw new ClassNotFoundException JavaDoc("class " //$NON-NLS-1$
493
+ cls.getName() + " is not visible for plug-in " //$NON-NLS-1$
494
+ requestor.getPluginDescriptor().getId());
495             }
496         }
497     }
498
499     /**
500      * @see java.lang.ClassLoader#findLibrary(java.lang.String)
501      */

502     protected String JavaDoc findLibrary(final String JavaDoc name) {
503         if ((name == null) || "".equals(name.trim())) { //$NON-NLS-1$
504
return null;
505         }
506         if (log.isDebugEnabled()) {
507             log.debug("findLibrary(String): name=" + name //$NON-NLS-1$
508
+ ", this=" + this); //$NON-NLS-1$
509
}
510         String JavaDoc libname = System.mapLibraryName(name);
511         String JavaDoc result = null;
512         PathResolver pathResolver = getPluginManager().getPathResolver();
513         for (Iterator JavaDoc it = getPluginDescriptor().getLibraries().iterator();
514                 it.hasNext();) {
515             Library lib = (Library) it.next();
516             if (lib.isCodeLibrary()) {
517                 continue;
518             }
519             URL JavaDoc libUrl = pathResolver.resolvePath(lib, lib.getPath() + libname);
520             if (log.isDebugEnabled()) {
521                 log.debug("findLibrary(String): trying URL " + libUrl); //$NON-NLS-1$
522
}
523             File JavaDoc libFile = IoUtil.url2file(libUrl);
524             if (libFile != null) {
525                 if (log.isDebugEnabled()) {
526                     log.debug("findLibrary(String): URL " + libUrl //$NON-NLS-1$
527
+ " resolved as local file " + libFile); //$NON-NLS-1$
528
}
529                 if (libFile.isFile()) {
530                     result = libFile.getAbsolutePath();
531                     break;
532                 }
533                 continue;
534             }
535             // we have some kind of non-local URL
536
// try to copy it to local temporary file
537
libFile = (File JavaDoc) libraryCache.get(libUrl.toExternalForm());
538             if (libFile != null) {
539                 if (libFile.isFile()) {
540                     result = libFile.getAbsolutePath();
541                     break;
542                 }
543                 libraryCache.remove(libUrl.toExternalForm());
544             }
545             if (libraryCache.containsKey(libUrl.toExternalForm())) {
546                 // already tried to cache this library
547
break;
548             }
549             libFile = cacheLibrary(libUrl, libname);
550             if (libFile != null) {
551                 result = libFile.getAbsolutePath();
552                 break;
553             }
554         }
555         if (log.isDebugEnabled()) {
556             log.debug("findLibrary(String): name=" + name //$NON-NLS-1$
557
+ ", libname=" + libname //$NON-NLS-1$
558
+ ", result=" + result //$NON-NLS-1$
559
+ ", this=" + this); //$NON-NLS-1$
560
}
561         return result;
562     }
563
564     protected synchronized File JavaDoc cacheLibrary(final URL JavaDoc libUrl,
565             final String JavaDoc libname) {
566         File JavaDoc cacheFolder = getLibCacheFolder();
567         String JavaDoc libUrlStr = libUrl.toExternalForm();
568         if (libraryCache.containsKey(libUrlStr)) {
569             return (File JavaDoc) libraryCache.get(libUrlStr);
570         }
571         File JavaDoc result = null;
572         try {
573             if (cacheFolder == null) {
574                 throw new IOException JavaDoc(
575                         "can't initialize libraries cache folder"); //$NON-NLS-1$
576
}
577             File JavaDoc libCachePluginFolder = new File JavaDoc(cacheFolder,
578                     getPluginDescriptor().getUniqueId());
579             if (!libCachePluginFolder.exists()
580                     && !libCachePluginFolder.mkdirs()) {
581                 throw new IOException JavaDoc("can't create cache folder " //$NON-NLS-1$
582
+ libCachePluginFolder);
583             }
584             result = new File JavaDoc(libCachePluginFolder, libname);
585             InputStream JavaDoc in = IoUtil.getResourceInputStream(libUrl);
586             try {
587                 OutputStream JavaDoc out = new BufferedOutputStream JavaDoc(
588                         new FileOutputStream JavaDoc(result));
589                 try {
590                     IoUtil.copyStream(in, out, 512);
591                 } finally {
592                     out.close();
593                 }
594             } finally {
595                 in.close();
596             }
597             libraryCache.put(libUrlStr, result);
598             if (log.isDebugEnabled()) {
599                 log.debug("library " + libname //$NON-NLS-1$
600
+ " successfully cached from URL " + libUrl //$NON-NLS-1$
601
+ " and saved to local file " + result); //$NON-NLS-1$
602
}
603         } catch (IOException JavaDoc ioe) {
604             log.error("can't cache library " + libname //$NON-NLS-1$
605
+ " from URL " + libUrl, ioe); //$NON-NLS-1$
606
libraryCache.put(libUrlStr, null);
607             result = null;
608         }
609         return result;
610     }
611
612     /**
613      * @see java.lang.ClassLoader#findResource(java.lang.String)
614      */

615     public URL JavaDoc findResource(final String JavaDoc name) {
616         //log.debug("findResource(String): name=" + name); //$NON-NLS-1$
617
URL JavaDoc result = findResource(name, this, null);
618         //log.debug("findResource(String): result=" + result); //$NON-NLS-1$
619
return result;
620     }
621
622     /**
623      * @see java.lang.ClassLoader#findResources(java.lang.String)
624      */

625     public Enumeration JavaDoc findResources(final String JavaDoc name) throws IOException JavaDoc {
626         List JavaDoc result = new LinkedList JavaDoc();
627         findResources(result, name, this, null);
628         return Collections.enumeration(result);
629     }
630
631     protected URL JavaDoc findResource(final String JavaDoc name,
632             final StandardPluginClassLoader requestor, final Set JavaDoc seenPlugins) {
633         /*log.debug("findResource(String,...): name=" + name //$NON-NLS-1$
634                 + ", this=" + this); //$NON-NLS-1$*/

635         Set JavaDoc seen = seenPlugins;
636         if ((seen != null) && seen.contains(getPluginDescriptor().getId())) {
637             return null;
638         }
639         URL JavaDoc result = super.findResource(name);
640         if (result != null) { // found resource in this plug-in class path
641
if (log.isDebugEnabled()) {
642                 log.debug("findResource(...): resource found in classpath, name=" //$NON-NLS-1$
643
+ name + " URL=" + result + ", this=" //$NON-NLS-1$ //$NON-NLS-2$
644
+ this + ", requestor=" + requestor); //$NON-NLS-1$
645
}
646             if (isResourceVisible(name, result, requestor)) {
647                 return result;
648             }
649             return null;
650         }
651         if (resourceLoader != null) {
652             result = resourceLoader.findResource(name);
653             if (result != null) { // found resource in this plug-in resource libraries
654
if (log.isDebugEnabled()) {
655                     log.debug("findResource(...): resource found in libraries, name=" //$NON-NLS-1$
656
+ name + ", URL=" + result + ", this=" //$NON-NLS-1$ //$NON-NLS-2$
657
+ this + ", requestor=" + requestor); //$NON-NLS-1$
658
}
659                 if (isResourceVisible(name, result, requestor)) {
660                     return result;
661                 }
662                 return null;
663             }
664         }
665         if (seen == null) {
666             seen = new HashSet JavaDoc();
667         }
668         if (log.isDebugEnabled()) {
669             log.debug("findResource(...): resource not found, name=" //$NON-NLS-1$
670
+ name + ", this=" //$NON-NLS-1$
671
+ this + ", requestor=" + requestor); //$NON-NLS-1$
672
}
673         seen.add(getPluginDescriptor().getId());
674         for (int i = 0; i < publicImports.length; i++) {
675             if (seen.contains(publicImports[i].getId())) {
676                 continue;
677             }
678             result = ((StandardPluginClassLoader) getPluginManager()
679                     .getPluginClassLoader(publicImports[i])).findResource(
680                             name, requestor, seen);
681             if (result != null) {
682                 break; // found resource in publicly imported plug-in
683
}
684         }
685         if ((this == requestor) && (result == null)) {
686             for (int i = 0; i < privateImports.length; i++) {
687                 if (seen.contains(privateImports[i].getId())) {
688                     continue;
689                 }
690                 result = ((StandardPluginClassLoader) getPluginManager()
691                         .getPluginClassLoader(privateImports[i])).findResource(
692                                 name, requestor, seen);
693                 if (result != null) {
694                     break; // found resource in privately imported plug-in
695
}
696             }
697         }
698         if ((this == requestor) && (result == null)) {
699             for (int i = 0; i < reverseLookups.length; i++) {
700                 if (seen.contains(reverseLookups[i].getId())) {
701                     continue;
702                 }
703                 result = ((StandardPluginClassLoader) getPluginManager()
704                         .getPluginClassLoader(reverseLookups[i])).findResource(
705                                 name, requestor, seen);
706                 if (result != null) {
707                     break; // found resource in plug-in that marks itself as
708
// allowed reverse look up
709
}
710             }
711         }
712         return result;
713     }
714
715     protected void findResources(final List JavaDoc result, final String JavaDoc name,
716             final StandardPluginClassLoader requestor, final Set JavaDoc seenPlugins)
717             throws IOException JavaDoc {
718         Set JavaDoc seen = seenPlugins;
719         if ((seen != null) && seen.contains(getPluginDescriptor().getId())) {
720             return;
721         }
722         for (Enumeration JavaDoc enm = super.findResources(name);
723                 enm.hasMoreElements();) {
724             URL JavaDoc url = (URL JavaDoc) enm.nextElement();
725             if (isResourceVisible(name, url, requestor)) {
726                 result.add(url);
727             }
728         }
729         if (resourceLoader != null) {
730             for (Enumeration JavaDoc enm = resourceLoader.findResources(name);
731                     enm.hasMoreElements();) {
732                 URL JavaDoc url = (URL JavaDoc) enm.nextElement();
733                 if (isResourceVisible(name, url, requestor)) {
734                     result.add(url);
735                 }
736             }
737         }
738         if (seen == null) {
739             seen = new HashSet JavaDoc();
740         }
741         seen.add(getPluginDescriptor().getId());
742         for (int i = 0; i < publicImports.length; i++) {
743             if (seen.contains(publicImports[i].getId())) {
744                 continue;
745             }
746             ((StandardPluginClassLoader) getPluginManager().getPluginClassLoader(
747                     publicImports[i])).findResources(result, name,
748                             requestor, seen);
749         }
750         if (this == requestor) {
751             for (int i = 0; i < privateImports.length; i++) {
752                 if (seen.contains(privateImports[i].getId())) {
753                     continue;
754                 }
755                 ((StandardPluginClassLoader) getPluginManager().getPluginClassLoader(
756                         privateImports[i])).findResources(result, name,
757                                 requestor, seen);
758             }
759             for (int i = 0; i < reverseLookups.length; i++) {
760                 if (seen.contains(reverseLookups[i].getId())) {
761                     continue;
762                 }
763                 ((StandardPluginClassLoader) getPluginManager().getPluginClassLoader(
764                         reverseLookups[i])).findResources(result, name,
765                                 requestor, seen);
766             }
767         }
768     }
769     
770     protected boolean isResourceVisible(final String JavaDoc name, final URL JavaDoc url,
771             final StandardPluginClassLoader requestor) {
772         /*log.debug("isResourceVisible(URL, PluginClassLoader): URL=" + url //$NON-NLS-1$
773                 + ", requestor=" + requestor); //$NON-NLS-1$*/

774         if (this == requestor) {
775             return true;
776         }
777         URL JavaDoc lib;
778         try {
779             String JavaDoc file = url.getFile();
780             lib = new URL JavaDoc(url.getProtocol(), url.getHost(),
781                     file.substring(0, file.length() - name.length()));
782         } catch (MalformedURLException JavaDoc mue) {
783             log.error("can't get resource library URL", mue); //$NON-NLS-1$
784
return false;
785         }
786         ResourceFilter filter =
787             (ResourceFilter) resourceFilters.get(lib.toExternalForm());
788         if (filter == null) {
789             log.warn("no resource filter found for library " //$NON-NLS-1$
790
+ lib + ", name=" + name //$NON-NLS-1$
791
+ ", URL=" + url + ", this=" + this //$NON-NLS-1$ //$NON-NLS-2$
792
+ ", requestor=" + requestor); //$NON-NLS-1$
793
return false;
794         }
795         if (!filter.isResourceVisible(name)) {
796             log.warn("resource not visible, name=" + name //$NON-NLS-1$
797
+ ", URL=" + url + ", this=" + this //$NON-NLS-1$ //$NON-NLS-2$
798
+ ", requestor=" + requestor); //$NON-NLS-1$
799
return false;
800         }
801         return true;
802     }
803     
804     protected static final class ResourceFilter {
805         private boolean isPublic;
806         private Set JavaDoc entries;
807
808         protected ResourceFilter(final Library lib) {
809             entries = new HashSet JavaDoc();
810             for (Iterator JavaDoc it = lib.getExports().iterator(); it.hasNext();) {
811                 String JavaDoc exportPrefix = (String JavaDoc) it.next();
812                 if ("*".equals(exportPrefix)) { //$NON-NLS-1$
813
isPublic = true;
814                     entries.clear();
815                     break;
816                 }
817                 if (!lib.isCodeLibrary()) {
818                     exportPrefix = exportPrefix.replace('\\', '.')
819                         .replace('/', '.');
820                     if (exportPrefix.startsWith(".")) { //$NON-NLS-1$
821
exportPrefix = exportPrefix.substring(1);
822                     }
823                 }
824                 entries.add(exportPrefix);
825             }
826         }
827         
828         protected boolean isClassVisible(final String JavaDoc className) {
829             if (isPublic) {
830                 return true;
831             }
832             if (entries.isEmpty()) {
833                 return false;
834             }
835             if (entries.contains(className)) {
836                 return true;
837             }
838             int p = className.lastIndexOf('.');
839             if (p == -1) {
840                 return false;
841             }
842             return entries.contains(className.substring(0, p) + ".*"); //$NON-NLS-1$
843
}
844
845         protected boolean isResourceVisible(final String JavaDoc resPath) {
846             // quick check
847
if (isPublic) {
848                 return true;
849             }
850             if (entries.isEmpty()) {
851                 return false;
852             }
853             // translate "path spec" -> "full class name"
854
String JavaDoc str = resPath.replace('\\', '.').replace('/', '.');
855             if (str.startsWith(".")) { //$NON-NLS-1$
856
str = str.substring(1);
857             }
858             if (str.endsWith(".")) { //$NON-NLS-1$
859
str = str.substring(0, str.length() - 1);
860             }
861             return isClassVisible(str);
862         }
863     }
864
865     protected static class PluginResourceLoader extends URLClassLoader JavaDoc {
866         private static Log logger =
867             LogFactory.getLog(PluginResourceLoader.class);
868
869         static PluginResourceLoader get(final PluginManager manager,
870                 final PluginDescriptor descr) {
871             final List JavaDoc urls = new LinkedList JavaDoc();
872             for (Iterator JavaDoc it = descr.getLibraries().iterator(); it.hasNext();) {
873                 Library lib = (Library) it.next();
874                 if (lib.isCodeLibrary()) {
875                     continue;
876                 }
877                 urls.add(manager.getPathResolver().resolvePath(lib,
878                         lib.getPath()));
879             }
880             if (logger.isDebugEnabled()) {
881                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
882                 buf.append("Resource URL's populated for plug-in " + descr //$NON-NLS-1$
883
+ ":\r\n"); //$NON-NLS-1$
884
for (Iterator JavaDoc it = urls.iterator(); it.hasNext();) {
885                     buf.append("\t"); //$NON-NLS-1$
886
buf.append(it.next());
887                     buf.append("\r\n"); //$NON-NLS-1$
888
}
889                 logger.trace(buf.toString());
890             }
891             if (urls.isEmpty()) {
892                 return null;
893             }
894             /*return new PluginResourceLoader((URL[]) urls.toArray(
895             new URL[urls.size()]));*/

896             return (PluginResourceLoader) AccessController.doPrivileged(
897                     new PrivilegedAction JavaDoc() {
898                 public Object JavaDoc run() {
899                     return new PluginResourceLoader(
900                             (URL JavaDoc[]) urls.toArray(new URL JavaDoc[urls.size()]));
901                 }
902             });
903         }
904
905         /**
906          * Creates loader instance configured to load resources only from given
907          * URLs.
908          * @param urls array of resource URLs
909          */

910         PluginResourceLoader(final URL JavaDoc[] urls) {
911             super(urls);
912         }
913
914         /**
915          * @see java.lang.ClassLoader#findClass(java.lang.String)
916          */

917         protected Class JavaDoc findClass(final String JavaDoc name)
918                 throws ClassNotFoundException JavaDoc {
919             throw new ClassNotFoundException JavaDoc(name);
920         }
921
922         /**
923          * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
924          */

925         protected Class JavaDoc loadClass(final String JavaDoc name, final boolean resolve)
926                 throws ClassNotFoundException JavaDoc {
927             throw new ClassNotFoundException JavaDoc(name);
928         }
929     }
930 }
931
Popular Tags