KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > virtual > classloading > VFSClassLoader


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.virtual.classloading;
23
24 import java.io.ByteArrayOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.security.CodeSource JavaDoc;
30 import java.security.PermissionCollection JavaDoc;
31 import java.security.ProtectionDomain JavaDoc;
32 import java.security.SecureClassLoader JavaDoc;
33 import java.security.cert.Certificate JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.Arrays JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Vector JavaDoc;
39
40 import org.jboss.classloading.spi.ClassLoadingDomain;
41 import org.jboss.classloading.spi.DomainClassLoader;
42 import org.jboss.logging.Logger;
43 import org.jboss.virtual.VFS;
44 import org.jboss.virtual.VirtualFile;
45
46 /** A class loader that obtains classes and resources from a VFS.
47  *
48  * @author Scott.Stark@jboss.org
49  * @version $Revision: 56428 $
50  */

51 public class VFSClassLoader extends SecureClassLoader JavaDoc
52    implements DomainClassLoader
53 {
54    private static Logger log = Logger.getLogger(VFSClassLoader.class);
55
56    protected static class ClassPathVFS
57    {
58       private ArrayList JavaDoc<String JavaDoc> searchCtxs = new ArrayList JavaDoc<String JavaDoc>();
59       private VFS vfs;
60       protected ClassPathVFS(String JavaDoc[] searchCtxs, VFS vfs)
61       {
62          this.searchCtxs.addAll(Arrays.asList(searchCtxs));
63          this.vfs = vfs;
64       }
65    }
66    protected ArrayList JavaDoc<ClassPathVFS> classpath = new ArrayList JavaDoc<ClassPathVFS>();
67
68    /**
69     * Create a class loader given a search path VFS, and default parent class
70     * loader.
71     * @param searchCtxs - the paths from the VFS that make up the class loader path
72     * @param vfs - the VFS used to resolve and load classes and resources
73     */

74    public VFSClassLoader(String JavaDoc[] searchCtxs, VFS vfs)
75    {
76       String JavaDoc[] resolvedCtxs = searchCtxs;
77       try
78       {
79          resolvedCtxs = resolveSearchCtxs(searchCtxs, vfs);
80       }
81       catch(IOException JavaDoc e)
82       {
83          log.warn("Failed to resolve searchCtxs", e);
84       }
85       ClassPathVFS cp = new ClassPathVFS(resolvedCtxs, vfs);
86       classpath.add(cp);
87    }
88    /**
89     * Create a class loader given a search path VFS, and given parent class
90     * loader.
91     * @param searchCtxs - the paths from the VFS that make up the class loader path
92     * @param vfs - the VFS used to resolve and load classes and resources
93     * @param parent - the parent class loader to use
94     */

95    public VFSClassLoader(String JavaDoc[] searchCtxs, VFS vfs, ClassLoader JavaDoc parent)
96    {
97       super(parent);
98       String JavaDoc[] resolvedCtxs = searchCtxs;
99       try
100       {
101          resolvedCtxs = resolveSearchCtxs(searchCtxs, vfs);
102       }
103       catch(IOException JavaDoc e)
104       {
105          log.warn("Failed to resolve searchCtxs", e);
106       }
107       ClassPathVFS cp = new ClassPathVFS(resolvedCtxs, vfs);
108       classpath.add(cp);
109    }
110
111    
112    /* (non-Javadoc)
113     * @see org.jboss.classloading.spi.DomainClassLoader#getClasspath()
114     */

115    public URL JavaDoc[] getClasspath()
116    {
117       ArrayList JavaDoc<URL JavaDoc> cp = new ArrayList JavaDoc<URL JavaDoc>(classpath.size());
118       for(ClassPathVFS entry : classpath)
119       {
120          try
121          {
122             URL JavaDoc baseURL = entry.vfs.getRoot().toURL();
123             for(String JavaDoc path : entry.searchCtxs)
124             {
125                try
126                {
127                   URL JavaDoc entryURL = new URL JavaDoc(baseURL, path);
128                   cp.add(entryURL);
129                }
130                catch(MalformedURLException JavaDoc e)
131                {
132                   log.debug("Failed to parse path: "+path, e);
133                }
134             }
135          }
136          catch(Exception JavaDoc e)
137          {
138             log.debug("Failed to parse entry: "+entry, e);
139          }
140       }
141       URL JavaDoc[] theClasspath = new URL JavaDoc[cp.size()];
142       cp.toArray(theClasspath);
143       return theClasspath;
144    }
145
146    /**
147     * TODO getPackageNames
148     *
149     * @see org.jboss.classloading.spi.DomainClassLoader#getPackageNames()
150     */

151    public String JavaDoc[] getPackageNames()
152    {
153       // TODO Auto-generated method stub
154
return null;
155    }
156
157    /**
158     * Find and define the given java class
159     *
160     * @param name - the binary class name
161     * @return the defined Class object
162     * @throws ClassNotFoundException thrown if the class could not be found
163     * or defined
164     */

165    protected Class JavaDoc<?> findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc
166    {
167       String JavaDoc resName = name.replace('.', '/');
168       VirtualFile classFile = findResourceFile(resName+".class");
169       if( classFile == null )
170          throw new ClassNotFoundException JavaDoc(name);
171       try
172       {
173          byte[] tmp = new byte[128];
174          ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
175          InputStream JavaDoc is = classFile.openStream();
176          int length;
177          while ((length = is.read(tmp)) > 0)
178          {
179             baos.write(tmp, 0, length);
180          }
181          is.close();
182          tmp = baos.toByteArray();
183          ProtectionDomain JavaDoc pd = getProtectionDomain(classFile);
184          return super.defineClass(name, tmp, 0, tmp.length, pd);
185       }
186       catch (Exception JavaDoc e)
187       {
188          throw new ClassNotFoundException JavaDoc(name, e);
189       }
190    }
191
192    /**
193     * Search for the resource in the VFS contraining the search to the
194     * class loader paths.
195     * @param name - the resource name
196     * @return the resource URL if found, null otherwise
197     */

198    public URL JavaDoc findResource(String JavaDoc name)
199    {
200       URL JavaDoc res = null;
201       VirtualFile vf = findResourceFile(name);
202       if( vf != null )
203       {
204          try
205          {
206             res = vf.toURL();
207          }
208          catch(Exception JavaDoc e)
209          {
210             if( log.isTraceEnabled() )
211                log.trace("Failed to obtain vf URL: "+vf, e);
212          }
213       }
214       return res;
215    }
216
217    /**
218     * Search for the resource in the VFS contraining the search to the
219     * class loader paths.
220     * @param name - the resource name
221     * @return A possibly empty enumeration of the matching resources
222     */

223    public Enumeration JavaDoc<URL JavaDoc> findResources(String JavaDoc name) throws IOException JavaDoc
224    {
225       Vector JavaDoc<URL JavaDoc> resources = new Vector JavaDoc<URL JavaDoc>();
226       /*for(ClassPathVFS cp : classpath)
227       {
228          List<VirtualFile> matches = null;//cp.vfs.resolveFiles(name, cp.searchCtxs);
229          for(VirtualFile vf : matches)
230          {
231             URL resURL = vf.toURL();
232             resources.add(resURL);
233          }
234       }*/

235       return resources.elements();
236    }
237    public Enumeration JavaDoc<URL JavaDoc> findResourcesLocally(String JavaDoc name) throws IOException JavaDoc
238    {
239       return findResources(name);
240    }
241
242    public ClassLoadingDomain getDomain()
243    {
244       return null;
245    }
246    public void setDomain(ClassLoadingDomain domain)
247    {
248    }
249
250    public Class JavaDoc loadClassLocally(String JavaDoc name, boolean resolve)
251       throws ClassNotFoundException JavaDoc
252    {
253       return findClass(name);
254    }
255
256    public URL JavaDoc loadResourceLocally(String JavaDoc name)
257    {
258       return this.findResource(name);
259    }
260
261    /**
262     * Get the packages defined by the classloader
263     *
264     * @return the packages
265     */

266    public Package JavaDoc[] getPackages()
267    {
268       return super.getPackages();
269    }
270
271    /**
272     * Get a package defined by the classloader
273     *
274     * @param name the name of the package
275     * @return the package
276     */

277    public Package JavaDoc getPackage(String JavaDoc name)
278    {
279       return super.getPackage(name);
280    }
281
282    protected VirtualFile findResourceFile(String JavaDoc name)
283    {
284       VirtualFile vf = null;
285       try
286       {
287          outer:
288          for(ClassPathVFS cp : classpath)
289          {
290             for(String JavaDoc ctx : cp.searchCtxs)
291             {
292                String JavaDoc path = ctx + '/' + name;
293                vf = cp.vfs.findChild(path);
294                if( vf != null )
295                {
296                   break outer;
297                }
298             }
299          }
300       }
301       catch (IOException JavaDoc e)
302       {
303          if( log.isTraceEnabled() )
304             log.trace("Failed to find resource: "+name, e);
305       }
306       return vf;
307    }
308
309    /**
310     * Determine the protection domain. If we are a copy of the original
311     * deployment, use the original url as the codebase.
312     *
313     * @param classFile the virtual file for this class
314     * @return the protection domain
315     * @throws Exception for any error
316     * TODO certificates and principles?
317     */

318    protected ProtectionDomain JavaDoc getProtectionDomain(VirtualFile classFile) throws Exception JavaDoc
319    {
320       Certificate JavaDoc certs[] = null;
321       URL JavaDoc codesourceUrl = classFile.toURL();
322       CodeSource JavaDoc cs = new CodeSource JavaDoc(codesourceUrl, certs);
323       PermissionCollection JavaDoc permissions = SecurityActions.getPolicy().getPermissions(cs);
324       if (log.isTraceEnabled())
325          log.trace("getProtectionDomain, url=" + codesourceUrl +
326                    " codeSource=" + cs + " permissions=" + permissions);
327       return new ProtectionDomain JavaDoc(cs, permissions);
328    }
329
330    /**
331     * Iterate through the searchCtxs and look for wildcard expressions. Currently only '*.jar' indicating
332     * every jar in a directory is supported.
333     *
334     * @param searchCtxs - input array of vfs paths relative to vfs
335     * @param vfs - the vfs to resolve the searchCtxs against
336     * @return the contexts
337     * @throws IOException for any error
338     */

339    protected String JavaDoc[] resolveSearchCtxs(String JavaDoc[] searchCtxs, VFS vfs) throws IOException JavaDoc
340    {
341       ArrayList JavaDoc<String JavaDoc> tmp = new ArrayList JavaDoc<String JavaDoc>(searchCtxs.length);
342       for(String JavaDoc ctx : searchCtxs)
343       {
344          if( ctx.endsWith("*.jar") )
345          {
346             // Obtain the parent directory name
347
int slash = ctx.lastIndexOf('/');
348             String JavaDoc dir = "";
349             if( slash > 0 )
350                dir = ctx.substring(0, slash);
351             VirtualFile dirFile = vfs.findChild(dir);
352             List JavaDoc<VirtualFile> children = dirFile.getChildren();
353             StringBuilder JavaDoc sb = new StringBuilder JavaDoc(dir);
354             sb.append('/');
355             int dirLength = sb.length();
356             for(VirtualFile child : children)
357             {
358                String JavaDoc name = child.getName();
359                if( name.endsWith(".jar") )
360                {
361                   sb.append(name);
362                   String JavaDoc path = sb.toString();
363                   tmp.add(path);
364                   sb.setLength(dirLength);
365                }
366             }
367          }
368          else
369          {
370             tmp.add(ctx);
371          }
372       }
373       log.debug("Resolved searchCtxs to: "+tmp);
374       String JavaDoc[] newCtxs = new String JavaDoc[tmp.size()];
375       tmp.toArray(newCtxs);
376       return newCtxs;
377    }
378 }
379
Popular Tags