KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > baseadaptor > loader > ClasspathManager


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.baseadaptor.loader;
13
14 import java.io.*;
15 import java.net.URL JavaDoc;
16 import java.security.ProtectionDomain JavaDoc;
17 import java.util.*;
18 import org.eclipse.osgi.baseadaptor.BaseData;
19 import org.eclipse.osgi.baseadaptor.bundlefile.*;
20 import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
21 import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
22 import org.eclipse.osgi.framework.adaptor.BundleData;
23 import org.eclipse.osgi.framework.debug.Debug;
24 import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
25 import org.eclipse.osgi.util.NLS;
26 import org.osgi.framework.BundleException;
27 import org.osgi.framework.FrameworkEvent;
28
29 /**
30  * A helper class for <code>BaseClassLoader</code> implementations. This class will keep track of
31  * <code>ClasspathEntry</code> objects for the host bundle and any attached fragment bundles. This
32  * class takes care of seaching the <code>ClasspathEntry</code> objects for a base class loader
33  * implementation. Additional behavior may be added to a classpath manager by configuring
34  * <code>ClassLoadingHook</code> and <code>ClassLoadingStatsHook</code>.
35  * @see BaseClassLoader
36  * @see ClassLoadingHook
37  * @see ClassLoadingStatsHook
38  * @since 3.2
39  */

40 public class ClasspathManager {
41     private static final FragmentClasspath[] emptyFragments = new FragmentClasspath[0];
42
43     private BaseData data;
44     private String JavaDoc[] classpath;
45     private ClasspathEntry[] entries;
46     private BaseClassLoader classloader;
47     private FragmentClasspath[] fragments = emptyFragments;
48     // a colloction of String[2], each element is {"libname", "libpath"}
49
private Collection loadedLibraries = null;
50
51     /**
52      * Constructs a classpath manager for the given host base data, classpath and base class loader
53      * @param data the host base data for this classpath manager
54      * @param classpath the host classpath for this classpath manager
55      * @param classloader the BaseClassLoader for this classpath manager
56      */

57     public ClasspathManager(BaseData data, String JavaDoc[] classpath, BaseClassLoader classloader) {
58         this.data = data;
59         this.classpath = classpath;
60         this.classloader = classloader;
61     }
62
63     /**
64      * initializes this classpath manager. This must be called after all existing fragments have been
65      * attached and before any resources/classes are loaded using this classpath manager.
66      * <p>
67      * After the classpath manager is initialized all configured class loading hooks
68      * {@link ClassLoadingHook#initializedClassLoader(BaseClassLoader, BaseData)} methods are called.
69      * </p>
70      */

71     public void initialize() {
72         entries = buildClasspath(classpath, this, data, classloader.getDomain());
73         ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
74         for (int i = 0; i < hooks.length; i++)
75             hooks[i].initializedClassLoader(classloader, data);
76     }
77
78     /**
79      * Closes all the classpath entry resources for this classpath manager.
80      *
81      */

82     public void close() {
83         if (entries != null) {
84             for (int i = 0; i < entries.length; i++) {
85                 if (entries[i] != null) {
86                     try {
87                         entries[i].getBundleFile().close();
88                     } catch (IOException e) {
89                         data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
90                     }
91                 }
92             }
93         }
94         for (int i = 0; i < fragments.length; i++)
95             fragments[i].close();
96     }
97
98     /**
99      * Attaches the specified sourcedata, sourcedomain and sourceclasspath to this classpath manager
100      * @param sourcedata the source fragment BundleData that should be attached.
101      * @param sourcedomain the source fragment domain that should be attached.
102      * @param sourceclasspath the source fragment classpath that should be attached.
103      */

104     public void attachFragment(BundleData sourcedata, ProtectionDomain JavaDoc sourcedomain, String JavaDoc[] sourceclasspath) {
105         try {
106             sourcedata.open(); /* make sure the BundleData is open */
107         } catch (IOException e) {
108             ((BaseData) sourcedata).getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, ((BaseData) sourcedata).getBundle(), e);
109         }
110         ClasspathEntry[] fragEntries = buildClasspath(sourceclasspath, this, (BaseData) sourcedata, sourcedomain);
111         FragmentClasspath fragClasspath = new FragmentClasspath((BaseData) sourcedata, fragEntries, sourcedomain);
112         insertFragment(fragClasspath);
113     }
114
115     private synchronized void insertFragment(FragmentClasspath fragClasspath) {
116         FragmentClasspath[] newFragments = new FragmentClasspath[fragments.length + 1];
117         // Find a place in the fragment list to insert this fragment.
118
long fragID = fragClasspath.getBundleData().getBundleID();
119         int insert = 0;
120         for (int i = 0; i < fragments.length; i++) {
121             long otherID = fragments[i].getBundleData().getBundleID();
122             if (insert == 0 && fragID < otherID) {
123                 newFragments[i] = fragClasspath;
124                 insert = 1;
125             }
126             newFragments[i + insert] = fragments[i];
127         }
128         // This fragment has the highest ID; put it at the end of the list.
129
if (insert == 0)
130             newFragments[fragments.length] = fragClasspath;
131         fragments = newFragments;
132     }
133
134     private static ClasspathEntry[] buildClasspath(String JavaDoc[] cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain JavaDoc sourcedomain) {
135         ArrayList result = new ArrayList(cp.length);
136         // add the regular classpath entries.
137
for (int i = 0; i < cp.length; i++)
138             findClassPathEntry(result, cp[i], hostloader, sourcedata, sourcedomain);
139         return (ClasspathEntry[]) result.toArray(new ClasspathEntry[result.size()]);
140     }
141
142     /**
143      * Finds all the ClasspathEntry objects for the requested classpath. This method will first call all
144      * the configured class loading hooks {@link ClassLoadingHook#addClassPathEntry(ArrayList, String, ClasspathManager, BaseData, ProtectionDomain)}
145      * methods. This allows class loading hooks to add additional ClasspathEntry objects to the result for the
146      * requested classpath. Then the local host classpath entries and attached fragment classpath entries are
147      * searched.
148      * @param result a list of ClasspathEntry objects. This list is used to add new ClasspathEntry objects to.
149      * @param cp the requested classpath.
150      * @param hostloader the host classpath manager for the classpath
151      * @param sourcedata the source EquionoxData to search for the classpath
152      * @param sourcedomain the source domain to used by the new ClasspathEntry
153      */

154     public static void findClassPathEntry(ArrayList result, String JavaDoc cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain JavaDoc sourcedomain) {
155         // look in classpath manager hooks first
156
ClassLoadingHook[] loaderHooks = sourcedata.getAdaptor().getHookRegistry().getClassLoadingHooks();
157         boolean hookAdded = false;
158         for (int i = 0; i < loaderHooks.length; i++)
159             hookAdded |= loaderHooks[i].addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain);
160         if (!addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain) && !hookAdded) {
161             BundleException be = new BundleException(NLS.bind(AdaptorMsg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourcedata.getLocation()));
162             sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.INFO, sourcedata.getBundle(), be);
163         }
164     }
165
166     /**
167      * Adds a ClasspathEntry for the requested classpath to the result. The local host classpath entries
168      * are searched first and then attached fragments classpath entries are searched. The search stops once the first
169      * classpath entry is found.
170      * @param result a list of ClasspathEntry objects. This list is used to add new ClasspathEntry objects to.
171      * @param cp the requested classpath.
172      * @param hostloader the host classpath manager for the classpath
173      * @param sourcedata the source EquionoxData to search for the classpath
174      * @param sourcedomain the source domain to used by the new ClasspathEntry
175      * @return true if a ClasspathEntry was added to the result
176      */

177     public static boolean addClassPathEntry(ArrayList result, String JavaDoc cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain JavaDoc sourcedomain) {
178         if (cp.equals(".")) { //$NON-NLS-1$
179
result.add(hostloader.createClassPathEntry(sourcedata.getBundleFile(), sourcedomain));
180             return true;
181         }
182         Object JavaDoc element = hostloader.getClasspath(cp, sourcedata, sourcedomain);
183         if (element != null) {
184             result.add(element);
185             return true;
186         }
187         // need to check in fragments for the classpath entry.
188
// only check for fragments if the data is the host's data.
189
if (hostloader.data == sourcedata)
190             for (int i = 0; i < hostloader.fragments.length; i++) {
191                 FragmentClasspath fragCP = hostloader.fragments[i];
192                 element = hostloader.getClasspath(cp, fragCP.getBundleData(), fragCP.getDomain());
193                 if (element != null) {
194                     result.add(element);
195                     return true;
196                 }
197             }
198         return false;
199     }
200
201     /**
202      * Creates a new ClasspathEntry object for the requested classpath if the source exists.
203      * @param cp the requested classpath.
204      * @param sourcedata the source EquionoxData to search for the classpath
205      * @param sourcedomain the source domain to used by the new ClasspathEntry
206      * @return a new ClasspathEntry for the requested classpath or null if the source does not exist.
207      */

208     public ClasspathEntry getClasspath(String JavaDoc cp, BaseData sourcedata, ProtectionDomain JavaDoc sourcedomain) {
209         BundleFile bundlefile = null;
210         File file;
211         BundleEntry cpEntry = sourcedata.getBundleFile().getEntry(cp);
212         // check for internal library directories in a bundle jar file
213
if (cpEntry != null && cpEntry.getName().endsWith("/")) //$NON-NLS-1$
214
bundlefile = createBundleFile(cp, sourcedata);
215         // check for internal library jars
216
else if ((file = sourcedata.getBundleFile().getFile(cp, false)) != null)
217             bundlefile = createBundleFile(file, sourcedata);
218         if (bundlefile != null)
219             return createClassPathEntry(bundlefile, sourcedomain);
220         return null;
221     }
222
223     /**
224      * Uses the requested classpath as an absolute path to locate a source for a new ClasspathEntry.
225      * @param cp the requested classpath
226      * @param sourcedata the source EquionoxData to search for the classpath
227      * @param sourcedomain the source domain to used by the new ClasspathEntry
228      * @return a classpath entry which uses an absolut path as a source
229      */

230     public ClasspathEntry getExternalClassPath(String JavaDoc cp, BaseData sourcedata, ProtectionDomain JavaDoc sourcedomain) {
231         File file = new File(cp);
232         if (!file.isAbsolute())
233             return null;
234         BundleFile bundlefile = createBundleFile(file, sourcedata);
235         if (bundlefile != null)
236             return createClassPathEntry(bundlefile, sourcedomain);
237         return null;
238     }
239
240     private static BundleFile createBundleFile(Object JavaDoc content, BaseData sourcedata) {
241         if (content == null || (content instanceof File && !((File) content).exists()))
242             return null;
243         try {
244             return sourcedata.getAdaptor().createBundleFile(content, sourcedata);
245         } catch (IOException e) {
246             sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, sourcedata.getBundle(), e);
247         }
248         return null;
249     }
250
251     private ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain JavaDoc cpDomain) {
252         return classloader.createClassPathEntry(bundlefile, cpDomain);
253     }
254
255     /**
256      * Finds a local resource by searching the ClasspathEntry objects of the classpath manager.
257      * This method will first call all the configured class loading stats hooks
258      * {@link ClassLoadingStatsHook#preFindLocalResource(String, ClasspathManager)} methods. Then it
259      * will search for the resource. Finally it will call all the configured class loading stats hooks
260      * {@link ClassLoadingStatsHook#postFindLocalResource(String, URL, ClasspathManager)} methods.
261      * @param resource the requested resource name.
262      * @return the requested resource URL or null if the resource does not exist
263      */

264     public URL JavaDoc findLocalResource(String JavaDoc resource) {
265         ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
266         for (int i = 0; i < hooks.length; i++)
267             hooks[i].preFindLocalResource(resource, this);
268         URL JavaDoc result = null;
269         try {
270             result = findLocalResourceImpl(resource);
271             return result;
272         } finally {
273             for (int i = 0; i < hooks.length; i++)
274                 hooks[i].postFindLocalResource(resource, result, this);
275         }
276     }
277
278     private URL JavaDoc findLocalResourceImpl(String JavaDoc resource) {
279         URL JavaDoc result = null;
280         for (int i = 0; i < entries.length; i++) {
281             if (entries[i] != null) {
282                 result = findResourceImpl(resource, entries[i].getBundleFile());
283                 if (result != null)
284                     return result;
285             }
286         }
287         // look in fragments
288
for (int i = 0; i < fragments.length; i++) {
289             ClasspathEntry[] fragEntries = fragments[i].getEntries();
290             for (int j = 0; j < fragEntries.length; j++) {
291                 result = findResourceImpl(resource, fragEntries[j].getBundleFile());
292                 if (result != null)
293                     return result;
294             }
295         }
296         return null;
297     }
298
299     /**
300      * Finds the local resources by searching the ClasspathEntry objects of the classpath manager.
301      * @param resource the requested resource name.
302      * @return an enumeration of the the requested resources or null if the resources do not exist
303      */

304     public Enumeration findLocalResources(String JavaDoc resource) {
305         Vector resources = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration
306
for (int i = 0; i < entries.length; i++) {
307             if (entries[i] != null) {
308                 URL JavaDoc url = findResourceImpl(resource, entries[i].getBundleFile(), resources.size());
309                 if (url != null)
310                     resources.addElement(url);
311             }
312         }
313         // look in fragments
314
for (int i = 0; i < fragments.length; i++) {
315             ClasspathEntry[] fragEntries = fragments[i].getEntries();
316             for (int j = 0; j < fragEntries.length; j++) {
317                 URL JavaDoc url = findResourceImpl(resource, fragEntries[j].getBundleFile(), resources.size());
318                 if (url != null)
319                     resources.addElement(url);
320             }
321         }
322         if (resources.size() > 0)
323             return resources.elements();
324         return null;
325     }
326
327     private URL JavaDoc findResourceImpl(String JavaDoc name, BundleFile bundlefile) {
328         return findResourceImpl(name, bundlefile, 0);
329     }
330
331     private URL JavaDoc findResourceImpl(String JavaDoc name, BundleFile bundlefile, int index) {
332         return bundlefile.getResourceURL(name, data.getBundleID(), index);
333     }
334
335     /**
336      * Finds a local entry by searching the ClasspathEntry objects of the classpath manager.
337      * @param path the requested entry path.
338      * @return the requested entry or null if the entry does not exist
339      */

340     public BundleEntry findLocalEntry(String JavaDoc path) {
341         BundleEntry result = null;
342         for (int i = 0; i < entries.length; i++) {
343             if (entries[i] != null) {
344                 result = findEntryImpl(path, entries[i].getBundleFile());
345                 if (result != null)
346                     return result;
347             }
348         }
349         // look in fragments
350
for (int i = 0; i < fragments.length; i++) {
351             ClasspathEntry[] fragEntries = fragments[i].getEntries();
352             for (int j = 0; j < fragEntries.length; j++) {
353                 result = findEntryImpl(path, fragEntries[j].getBundleFile());
354                 if (result != null)
355                     return result;
356             }
357         }
358         return null;
359     }
360
361     /**
362      * Finds the local entries by searching the ClasspathEntry objects of the classpath manager.
363      * @param path the requested entry path.
364      * @return an enumeration of the the requested entries or null if the entries do not exist
365      */

366     public Enumeration findLocalEntries(String JavaDoc path) {
367         Vector objects = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration
368
for (int i = 0; i < entries.length; i++) {
369             if (entries[i] != null) {
370                 BundleEntry result = findEntryImpl(path, entries[i].getBundleFile());
371                 if (result != null)
372                     objects.addElement(result);
373             }
374         }
375         // look in fragments
376
for (int i = 0; i < fragments.length; i++) {
377             ClasspathEntry[] fragEntries = fragments[i].getEntries();
378             for (int j = 0; j < fragEntries.length; j++) {
379                 BundleEntry result = findEntryImpl(path, fragEntries[j].getBundleFile());
380                 if (result != null)
381                     objects.addElement(result);
382             }
383         }
384         if (objects.size() > 0)
385             return objects.elements();
386         return null;
387     }
388
389     private BundleEntry findEntryImpl(String JavaDoc path, BundleFile bundleFile) {
390         return bundleFile.getEntry(path);
391     }
392
393     /**
394      * Finds a local class by searching the ClasspathEntry objects of the classpath manager.
395      * This method will first call all the configured class loading stats hooks
396      * {@link ClassLoadingStatsHook#preFindLocalClass(String, ClasspathManager)} methods. Then it
397      * will search for the class. If a class is found then all configured class loading hooks
398      * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
399      * methods will be called. The class is then defined; if successfully then all configured class loading
400      * stats hooks {@link ClassLoadingStatsHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
401      * methods are called. Finally all the configured class loading stats hooks
402      * {@link ClassLoadingStatsHook#postFindLocalClass(String, Class, ClasspathManager)} methods are called.
403      * @param classname the requested class name.
404      * @return the requested class
405      * @throws ClassNotFoundException if the class does not exist
406      */

407     public Class JavaDoc findLocalClass(String JavaDoc classname) throws ClassNotFoundException JavaDoc {
408         Class JavaDoc result = null;
409         ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
410         try {
411             for (int i = 0; i < hooks.length; i++)
412                 hooks[i].preFindLocalClass(classname, this);
413             result = findLocalClassImpl(classname, hooks);
414             return result;
415         } finally {
416             for (int i = 0; i < hooks.length; i++)
417                 hooks[i].postFindLocalClass(classname, result, this);
418         }
419     }
420
421     private Class JavaDoc findLocalClassImpl(String JavaDoc classname, ClassLoadingStatsHook[] hooks) throws ClassNotFoundException JavaDoc {
422         // must call findLoadedClass here even if it was called earlier,
423
// the findLoadedClass and defineClass calls must be atomic
424
synchronized (classloader) {
425             Class JavaDoc result = classloader.publicFindLoaded(classname);
426             if (result != null)
427                 return result;
428             for (int i = 0; i < entries.length; i++) {
429                 if (entries[i] != null) {
430                     result = findClassImpl(classname, entries[i], hooks);
431                     if (result != null)
432                         return result;
433                 }
434             }
435             // look in fragments.
436
for (int i = 0; i < fragments.length; i++) {
437                 ClasspathEntry[] fragEntries = fragments[i].getEntries();
438                 for (int j = 0; j < fragEntries.length; j++) {
439                     result = findClassImpl(classname, fragEntries[j], hooks);
440                     if (result != null)
441                         return result;
442                 }
443             }
444         }
445         throw new ClassNotFoundException JavaDoc(classname);
446     }
447
448     private Class JavaDoc findClassImpl(String JavaDoc name, ClasspathEntry classpathEntry, ClassLoadingStatsHook[] hooks) {
449         if (Debug.DEBUG && Debug.DEBUG_LOADER)
450             Debug.println("BundleClassLoader[" + data + "].findClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
451
String JavaDoc filename = name.replace('.', '/').concat(".class"); //$NON-NLS-1$
452
BundleEntry entry = classpathEntry.getBundleFile().getEntry(filename);
453         if (entry == null)
454             return null;
455
456         byte[] classbytes;
457         try {
458             classbytes = entry.getBytes();
459         } catch (IOException e) {
460             if (Debug.DEBUG && Debug.DEBUG_LOADER)
461                 Debug.println(" IOException reading " + filename + " from " + data); //$NON-NLS-1$ //$NON-NLS-2$
462
return null;
463         }
464
465         if (Debug.DEBUG && Debug.DEBUG_LOADER) {
466             Debug.println(" read " + classbytes.length + " bytes from " + filename); //$NON-NLS-1$ //$NON-NLS-2$
467
Debug.println(" defining class " + name); //$NON-NLS-1$
468
}
469
470         try {
471             return defineClass(name, classbytes, classpathEntry, entry, hooks);
472         } catch (Error JavaDoc e) {
473             if (Debug.DEBUG && Debug.DEBUG_LOADER)
474                 Debug.println(" error defining class " + name); //$NON-NLS-1$
475
throw e;
476         }
477     }
478
479     /**
480      * Defines the specified class. This method will first call all the configured class loading hooks
481      * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
482      * methods. Then it will call the {@link BaseClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
483      * method to define the class. After that, the class loading stat hooks are called to announce the class
484      * definition.
485      * @param name the name of the class to define
486      * @param classbytes the class bytes
487      * @param classpathEntry the classpath entry used to load the class bytes
488      * @param entry the BundleEntry used to load the class bytes
489      * @param statsHooks the class loading stat hooks
490      * @return the defined class
491      */

492     private Class JavaDoc defineClass(String JavaDoc name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClassLoadingStatsHook[] statsHooks) {
493         ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
494         byte[] modifiedBytes = classbytes;
495         for (int i = 0; i < hooks.length; i++) {
496             modifiedBytes = hooks[i].processClass(name, classbytes, classpathEntry, entry, this);
497             if (modifiedBytes != null)
498                 classbytes = modifiedBytes;
499         }
500
501         Class JavaDoc result = classloader.defineClass(name, classbytes, classpathEntry, entry);
502
503         for (int i = 0; i < statsHooks.length; i++)
504             statsHooks[i].recordClassDefine(name, result, classbytes, classpathEntry, entry, this);
505         return result;
506     }
507
508     /**
509      * Returns the host base data for this classpath manager
510      * @return the host base data for this classpath manager
511      */

512     public BaseData getBaseData() {
513         return data;
514     }
515
516     /**
517      * Returns the fragment classpaths of this classpath manager
518      * @return the fragment classpaths of this classpath manager
519      */

520     public FragmentClasspath[] getFragmentClasspaths() {
521         return fragments;
522     }
523
524     /**
525      * Returns the host classpath entries for this classpath manager
526      * @return the host classpath entries for this classpath manager
527      */

528     public ClasspathEntry[] getHostClasspathEntries() {
529         return entries;
530     }
531
532     /**
533      * Returns the base class loader used by this classpath manager
534      * @return the base class loader used by this classpath manager
535      */

536     public BaseClassLoader getBaseClassLoader() {
537         return classloader;
538     }
539
540     public String JavaDoc findLibrary(String JavaDoc libname) {
541         synchronized (this) {
542             if (loadedLibraries == null)
543                 loadedLibraries = new ArrayList(1);
544         }
545         synchronized (loadedLibraries) {
546             // we assume that each classloader will load a small number of of libraries
547
// instead of wasting space with a map we iterate over our collection of found libraries
548
// each element is a String[2], each array is {"libname", "libpath"}
549
for (Iterator libs = loadedLibraries.iterator(); libs.hasNext();) {
550                 String JavaDoc[] libNameResult = (String JavaDoc[]) libs.next();
551                 if (libNameResult[0].equals(libname))
552                     return libNameResult[1];
553             }
554
555             String JavaDoc result = classloader.getDelegate().findLibrary(libname);
556             if (result != null)
557                 loadedLibraries.add(new String JavaDoc[] {libname, result});
558             return result;
559         }
560     }
561
562 }
563
Popular Tags