View Javadoc

1   /*
2    * $Id: ClassLoaderFactory.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.registry;
12  
13  import org.mule.util.FileUtils;
14  
15  import java.net.MalformedURLException;
16  import java.net.URL;
17  import java.net.URLClassLoader;
18  import java.security.SecureClassLoader;
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  
25  /**
26   * @author <a href="mailto:gnt@codehaus.org">Guillaume Nodet</a>
27   */
28  public class ClassLoaderFactory
29  {
30  
31      private static ClassLoaderFactory factory;
32      private Map sharedClassLoaders;
33  
34      public static ClassLoaderFactory getInstance()
35      {
36          if (factory == null)
37          {
38              factory = new ClassLoaderFactory();
39          }
40          return factory;
41      }
42  
43      private ClassLoaderFactory()
44      {
45          this.sharedClassLoaders = new HashMap();
46      }
47  
48      public ClassLoader createComponentClassLoader(RegistryComponent component) throws MalformedURLException
49      {
50          DelegatingClassLoader dcl = new DelegatingClassLoader();
51          Library[] libraries = component.getLibraries();
52          for (int i = 0; i < libraries.length; i++)
53          {
54              dcl.addClassLoader(getSharedClassLoader(libraries[i]));
55          }
56          URL[] urls = getUrlsFrom(component.getInstallRoot(), component.getClassPathElements());
57          boolean isParentFirst = component.isClassLoaderParentFirst();
58          JbiClassLoader ccl = new JbiClassLoader(urls, dcl, isParentFirst);
59          return ccl;
60      }
61  
62      private ClassLoader getSharedClassLoader(Library library) throws MalformedURLException
63      {
64          ClassLoader cl = (ClassLoader)this.sharedClassLoaders.get(library.getName());
65          if (cl == null)
66          {
67              URL[] urls = getUrlsFrom(library.getInstallRoot(), library.getClassPathElements());
68              boolean isParentFirst = library.isClassLoaderParentFirst();
69              cl = new JbiClassLoader(urls, null, isParentFirst);
70              this.sharedClassLoaders.put(library.getName(), cl);
71          }
72          return cl;
73      }
74  
75      private URL[] getUrlsFrom(String root, List paths) throws MalformedURLException
76      {
77          URL[] urls = new URL[paths.size()];
78          for (int i = 0; i < urls.length; i++)
79          {
80              String cpElement = (String)paths.get(i);
81              urls[i] = FileUtils.newFile(root, cpElement).toURL();
82          }
83          return urls;
84      }
85  
86      /**
87       * ClassLoader for a component. This class loader is able to resolve class either
88       * by first looking at the parent ot itself.
89       * 
90       * @author <a href="mailto:gnt@codehaus.org">Guillaume Nodet</a>
91       */
92      public static class JbiClassLoader extends URLClassLoader
93      {
94  
95          private boolean parentFirst;
96  
97          public JbiClassLoader(URL[] urls, ClassLoader parent, boolean parentFirst)
98          {
99              super(urls, parent);
100             this.parentFirst = parentFirst;
101         }
102 
103         protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException
104         {
105             // First, check if the class has already been loaded
106             Class clazz = findLoadedClass(name);
107             if (clazz == null)
108             {
109                 if (this.parentFirst)
110                 {
111                     try
112                     {
113                         clazz = getParent().loadClass(name);
114                     }
115                     catch (ClassNotFoundException cnfe)
116                     {
117                         clazz = findClass(name);
118                     }
119                 }
120                 else
121                 {
122                     try
123                     {
124                         clazz = findClass(name);
125                     }
126                     catch (ClassNotFoundException e)
127                     {
128                         clazz = getParent().loadClass(name);
129                     }
130                 }
131             }
132             if (resolve)
133             {
134                 resolveClass(clazz);
135             }
136             return clazz;
137         }
138     }
139 
140     /**
141      * ClassLoader for shared libraries
142      * 
143      * @author <a href="mailto:gnt@codehaus.org">Guillaume Nodet</a>
144      */
145     public static class DelegatingClassLoader extends SecureClassLoader
146     {
147         private List loaders;
148 
149         public DelegatingClassLoader()
150         {
151             this.loaders = new ArrayList();
152         }
153 
154         public void addClassLoader(ClassLoader loader)
155         {
156             if (loader == null)
157             {
158                 throw new IllegalArgumentException("loader can not be null");
159             }
160             loaders.add(loader);
161         }
162 
163         protected Class findClass(String name) throws ClassNotFoundException
164         {
165             for (Iterator iter = this.loaders.iterator(); iter.hasNext();)
166             {
167                 ClassLoader loader = (ClassLoader)iter.next();
168                 try
169                 {
170                     return loader.loadClass(name);
171                 }
172                 catch (ClassNotFoundException e)
173                 {
174                     // expected
175                 }
176             }
177             throw new ClassNotFoundException(name);
178         }
179     }
180 
181 }