KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > virtual > spi > VFSContextFactoryLocator


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.spi;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.net.URI JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.security.AccessController JavaDoc;
31 import java.security.PrivilegedAction JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Arrays JavaDoc;
34 import java.util.Enumeration JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37 import java.util.concurrent.ConcurrentHashMap JavaDoc;
38
39 import org.jboss.logging.Logger;
40 import org.jboss.virtual.plugins.context.file.FileSystemContextFactory;
41 import org.jboss.virtual.plugins.context.jar.JarContextFactory;
42
43 /**
44  * A singleton factory for locating VFSContextFactory instances given VFS root URIs.
45  *
46  * @author Scott.Stark@jboss.org
47  * @author adrian@jboss.org
48  * @version $Revision: 45764 $
49  */

50 public class VFSContextFactoryLocator
51 {
52    /** The log */
53    private static final Logger log = Logger.getLogger(VFSContextFactoryLocator.class);
54    
55    /** The VSFactory mapped keyed by the VFS protocol string */
56    private static final Map JavaDoc<String JavaDoc, VFSContextFactory> factoryByProtocol = new ConcurrentHashMap JavaDoc<String JavaDoc, VFSContextFactory>();
57    
58    /** The system property that defines the default file factory */
59    public static final String JavaDoc DEFAULT_FACTORY_PROPERTY = VFSContextFactory.class.getName();
60    
61    /** The path used to load services from the classpath */
62    public static final String JavaDoc SERVICES_PATH = "META-INF/services/" + VFSContextFactory.class.getName();
63    
64    /** Has the default initialzation been performed */
65    private static boolean initialized;
66
67    /**
68     * Register a new VFSContextFactory
69     *
70     * @param factory the factory
71     * @throws IllegalArgumentException if the factory is null or the factory
72     * returns a null or no protocols
73     * @throws IllegalStateException if one of the protocols is already registered
74     */

75    public synchronized static void registerFactory(VFSContextFactory factory)
76    {
77       if (factory == null)
78          throw new IllegalArgumentException JavaDoc("Null VFSContextFactory");
79
80       String JavaDoc[] protocols = factory.getProtocols();
81       if (protocols == null || protocols.length == 0)
82          throw new IllegalArgumentException JavaDoc("VFSContextFactory trying to register null or no protocols: " + factory);
83       
84       for (String JavaDoc protocol : protocols)
85       {
86          if (protocol == null)
87             throw new IllegalArgumentException JavaDoc("VFSContextFactory try to register a null protocol: " + factory + " protocols=" + Arrays.asList(protocols));
88          VFSContextFactory other = factoryByProtocol.get(protocol);
89          if (other != null)
90             throw new IllegalStateException JavaDoc("VFSContextFactory: " + other + " already registered for protocol: " + protocol);
91       }
92
93       boolean trace = log.isTraceEnabled();
94       for (String JavaDoc protocol : protocols)
95       {
96          factoryByProtocol.put(protocol, factory);
97          if (trace)
98             log.trace("Registered " + factory + " for protocol: " + protocol);
99       }
100    }
101
102    /**
103     * Unregister a VFSContextFactory
104     *
105     * @param factory the factory
106     * @return false when not registered
107     * @throws IllegalArgumentException if the factory is null
108     */

109    public synchronized static boolean unregisterFactory(VFSContextFactory factory)
110    {
111       if (factory == null)
112          throw new IllegalArgumentException JavaDoc("Null VFSContextFactory");
113
114       ArrayList JavaDoc<String JavaDoc> protocols = new ArrayList JavaDoc<String JavaDoc>();
115       for (Map.Entry JavaDoc<String JavaDoc, VFSContextFactory> entry : factoryByProtocol.entrySet())
116       {
117          if (factory == entry.getValue())
118             protocols.add(entry.getKey());
119       }
120
121       boolean trace = log.isTraceEnabled();
122       for (String JavaDoc protocol : protocols)
123       {
124          factoryByProtocol.remove(protocol);
125          if (trace)
126             log.trace("Unregistered " + factory + " for protocol: " + protocol);
127       }
128       
129       return protocols.isEmpty() == false;
130    }
131
132    /**
133     * Return the VFSContextFactory for the VFS mount point specified by the rootURL.
134     *
135     * @param rootURL - the URL to a VFS root
136     * @return the VFSContextFactory capable of handling the rootURL. This will be null
137     * if there is no factory registered for the rootURL protocol.
138     * @throws IllegalArgumentException if the rootURL is null
139     */

140    public static VFSContextFactory getFactory(URL JavaDoc rootURL)
141    {
142       if (rootURL == null)
143          throw new IllegalArgumentException JavaDoc("Null rootURL");
144       
145       init();
146       String JavaDoc protocol = rootURL.getProtocol();
147       return factoryByProtocol.get(protocol);
148    }
149    /**
150     * Return the VFSContextFactory for the VFS mount point specified by the rootURI.
151     *
152     * @param rootURI - the URI to a VFS root
153     * @return the VFSContextFactory capable of handling the rootURI. This will be null
154     * if there is no factory registered for the rootURI scheme.
155     * @throws IllegalArgumentException if the rootURI is null
156     */

157    public static VFSContextFactory getFactory(URI JavaDoc rootURI)
158    {
159       if (rootURI == null)
160          throw new IllegalArgumentException JavaDoc("Null rootURI");
161       
162       init();
163       String JavaDoc scheme = rootURI.getScheme();
164       return factoryByProtocol.get(scheme);
165    }
166
167    /**
168     * Initialises the default VFSContextFactorys<p>
169     *
170     * <ol>
171     * <li>Look for META-INF/services/org.jboss.virtual.spi.VFSContextFactory
172     * <li>Look at the system property org.jboss.virtual.spi.VFSContextFactory for a comma
173     * seperated list of factories
174     * <li>Register default loaders when not done by the above mechanisms.
175     * </ol>
176     */

177    private static synchronized void init()
178    {
179       // Somebody beat us to it?
180
if (initialized)
181          return;
182       
183       // Try to locate from services files
184
ClassLoader JavaDoc loader = AccessController.doPrivileged(new GetContextClassLoader());
185       Enumeration JavaDoc<URL JavaDoc> urls = AccessController.doPrivileged(new EnumerateServices());
186       if (urls != null)
187       {
188          while (urls.hasMoreElements())
189          {
190             URL JavaDoc url = urls.nextElement();
191             
192             VFSContextFactory[] factories = loadFactories(url, loader);
193             for (VFSContextFactory factory : factories)
194             {
195                try
196                {
197                   registerFactory(factory);
198                }
199                catch (Exception JavaDoc e)
200                {
201                   log.warn("Error registering factory from " + url, e);
202                }
203             }
204          }
205       }
206
207       String JavaDoc defaultFactoryNames = AccessController.doPrivileged(new GetDefaultFactories());
208       if (defaultFactoryNames != null)
209       {
210          StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(defaultFactoryNames, ",");
211          while (tokenizer.hasMoreTokens())
212          {
213             String JavaDoc factoryName = tokenizer.nextToken();
214             VFSContextFactory factory = createVFSContextFactory(loader, factoryName, " from system property.");
215             if (factory != null)
216                registerFactory(factory);
217          }
218       }
219
220       // No file protocol, use the default
221
if (factoryByProtocol.containsKey("file") == false)
222          registerFactory(new FileSystemContextFactory());
223
224       // No jar protocol, use the default
225
if (factoryByProtocol.containsKey("jar") == false)
226          registerFactory(new JarContextFactory());
227
228       initialized = true;
229    }
230    
231    /**
232     * Load the VFSFactory classes found in the service file
233     *
234     * @param serviceURL the service url
235     * @param loader the class loader
236     * @return A possibly zero length array of the VFSFactory instances
237     * loaded from the serviceURL
238     */

239    private static VFSContextFactory[] loadFactories(URL JavaDoc serviceURL, ClassLoader JavaDoc loader)
240    {
241       ArrayList JavaDoc<VFSContextFactory> temp = new ArrayList JavaDoc<VFSContextFactory>();
242       try
243       {
244          InputStream JavaDoc is = serviceURL.openStream();
245          try
246          {
247             BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is));
248             String JavaDoc line;
249             while ( (line = br.readLine()) != null )
250             {
251                if (line.startsWith("#") == true)
252                   continue;
253                String JavaDoc[] classes = line.split("\\s+|#.*");
254                for (int n = 0; n < classes.length; n ++)
255                {
256                   String JavaDoc name = classes[n];
257                   if (name.length() == 0)
258                      continue;
259                   VFSContextFactory factory = createVFSContextFactory(loader, name, " defined in " + serviceURL);
260                   if (factory != null)
261                      temp.add(factory);
262                }
263             }
264          }
265          finally
266          {
267             is.close();
268          }
269       }
270       catch(Exception JavaDoc e)
271       {
272          log.warn("Error parsing " + serviceURL, e);
273       }
274
275       VFSContextFactory[] factories = new VFSContextFactory[temp.size()];
276       return temp.toArray(factories);
277    }
278    
279    /**
280     * Create a vfs context factory
281     *
282     * @param cl the classloader
283     * @param className the class name
284     * @return the vfs context factory
285     */

286    private static VFSContextFactory createVFSContextFactory(ClassLoader JavaDoc cl, String JavaDoc className, String JavaDoc context)
287    {
288       try
289       {
290          Class JavaDoc factoryClass = cl.loadClass(className);
291          return (VFSContextFactory) factoryClass.newInstance();
292       }
293       catch (Exception JavaDoc e)
294       {
295          log.warn("Error creating VFSContextFactory " + className + " " + context, e);
296          return null;
297       }
298    }
299    
300    /**
301     * Get the context classloader
302     */

303    private static class GetContextClassLoader implements PrivilegedAction JavaDoc<ClassLoader JavaDoc>
304    {
305       public ClassLoader JavaDoc run()
306       {
307          return Thread.currentThread().getContextClassLoader();
308       }
309    }
310    
311    /**
312     * Get the default file factory class name
313     */

314    private static class GetDefaultFactories implements PrivilegedAction JavaDoc<String JavaDoc>
315    {
316       public String JavaDoc run()
317       {
318          return System.getProperty(DEFAULT_FACTORY_PROPERTY);
319       }
320    }
321    
322    /**
323     * Enumerates the services
324     */

325    private static class EnumerateServices implements PrivilegedAction JavaDoc<Enumeration JavaDoc<URL JavaDoc>>
326    {
327       public Enumeration JavaDoc<URL JavaDoc> run()
328       {
329          ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
330          try
331          {
332             return cl.getResources(SERVICES_PATH);
333          }
334          catch (IOException JavaDoc e)
335          {
336             log.warn("Error retrieving " + SERVICES_PATH, e);
337             return null;
338          }
339       }
340    }
341 }
342
Popular Tags