KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > net > protocol > URLStreamHandlerFactory


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.net.protocol;
23
24 import java.net.URL JavaDoc;
25 import java.net.URLStreamHandler JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import org.jboss.logging.Logger;
33
34 /**
35  * A factory for loading URL protocol handlers. This is based
36  * on Sun's URL mechanism, in that <tt>Handler</tt> classes will be
37  * searched for in the packages specified by the java.protocol.handler.pkgs
38  * property are searched for classes matching the protocol + ".Handler"
39  * classname. The default JBoss package "org.jboss.net.protocol" is searched
40  * even if not specified in the java.protocol.handler.pkgs property.
41  *
42  * <p>This factory is installed by the default server implementaion
43  * to ensure that protocol handlers not in the system classpath are
44  * located. The thread context class is used first followed by the
45  * Class.forName method.
46  * </p>
47  *
48  * <p>Use {@link preload} to force the URL handler map to load the
49  * handlers for each protocol listed in {@link #PROTOCOLS}.
50  *
51  * @version <tt>$Revision: 1958 $</tt>
52  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
53  * @author Scott.Stark@jboss.org
54  */

55 public class URLStreamHandlerFactory
56    implements java.net.URLStreamHandlerFactory JavaDoc
57 {
58    /** Class logger. */
59    private static final Logger log = Logger.getLogger(URLStreamHandlerFactory.class);
60    
61    /** The package prefix where JBoss protocol handlers live. */
62    public static final String JavaDoc PACKAGE_PREFIX = "org.jboss.net.protocol";
63    /** A map of protocol names to handlers. Since there can only be one
64     URLStreamHandlerFactory installed, this is a static map that may be
65     cleared.
66     */

67    private static Map JavaDoc handlerMap = Collections.synchronizedMap(new HashMap JavaDoc());
68
69    /** This thread local is used to prevent recursion in the
70     * createURLStreamHandler method. Resolving the protocol handler
71     * class can end up creating a new URL which can loop back into
72     * this factory with a stack like:
73     * <pre>
74       URLStreamHandlerFactory that use the TCL. See bug#669043
75       createURLStreamHandler():146, URLStreamHandlerFactory.java
76       getURLStreamHandler():1057, URL.java
77       <init>():405, URL.java
78       <init>():329, URL.java
79       <init>():321, URL.java
80       <init>():540, URLClassPath.java
81       run():319, URLClassPath.java
82       doPrivileged():-1, AccessController.java
83       getLoader():308, URLClassPath.java
84       getLoader():285, URLClassPath.java
85       findResource():136, URLClassPath.java
86       run():351, URLClassLoader.java
87       doPrivileged():-1, AccessController.java
88       findResource():348, URLClassLoader.java
89       getResource():780, ClassLoader.java
90       getResourceLocally():250, UnifiedClassLoader.java
91       getResourceFromClassLoader():333, UnifiedLoaderRepository3.java
92       getResource():243, UnifiedLoaderRepository3.java
93       getResource():228, UnifiedClassLoader3.java
94      </pre>
95     So we detect recursion based on the protocol value matches the current
96     createURLStreamHandlerProtocol setting.
97    */

98    private static ThreadLocal JavaDoc createURLStreamHandlerProtocol = new ThreadLocal JavaDoc();
99
100    /** The current packages prefixes determined from the java.protocol.handler.pkgs
101     property + the org.jboss.net.protocol default package.
102     */

103    private String JavaDoc[] handlerPkgs = {PACKAGE_PREFIX};
104    /** The last java.protocol.handler.pkgs value. Used to determine if the
105     java.protocol.handler.pkgs property has changed since handlerPkgs was
106     last built.
107     */

108    private String JavaDoc lastHandlerPkgs = PACKAGE_PREFIX;
109
110    /** A list of JBoss specific protocols for preloading. */
111    public static final String JavaDoc PROTOCOLS[] = {
112       "resource",
113       "file"
114    };
115
116    /**
117     * Preload the JBoss specific protocol handlers, so that URL knows about
118     * them even if the handler factory is changed.
119     */

120    public static void preload()
121    {
122       for (int i = 0; i < PROTOCOLS.length; i ++)
123       {
124          try
125          {
126             URL JavaDoc url = new URL JavaDoc(PROTOCOLS[i], "", -1, "");
127             log.trace("Loaded protocol: " + PROTOCOLS[i]);
128          }
129          catch (Exception JavaDoc e)
130          {
131             log.warn("Failed to load protocol: " + PROTOCOLS[i], e);
132          }
133       }
134    }
135
136    /** Clear the current protocol to handler map. The map will be rebuilt
137     as protocol handlers are requested.
138     */

139    public static void clear()
140    {
141       handlerMap.clear();
142    }
143
144    /** Search the handlerPkgs for URLStreamHandler classes matching the
145     * pkg + protocol + ".Handler" naming convention.
146     *
147     * @see #checkHandlerPkgs()
148     * @param protocol The protocol to create a stream handler for
149     * @return The protocol handler or null if not found
150     */

151    public URLStreamHandler JavaDoc createURLStreamHandler(final String JavaDoc protocol)
152    {
153       // Check the handler map
154
URLStreamHandler JavaDoc handler = (URLStreamHandler JavaDoc) handlerMap.get(protocol);
155       if( handler != null )
156          return handler;
157
158       // Validate that createURLStreamHandler is not recursing
159
String JavaDoc prevProtocol = (String JavaDoc) createURLStreamHandlerProtocol.get();
160       if( prevProtocol != null && prevProtocol.equals(protocol) )
161          return null;
162       createURLStreamHandlerProtocol.set(protocol);
163
164       // See if the handler pkgs definition has changed
165
checkHandlerPkgs();
166
167       // Search the handlerPkgs for a matching protocol handler
168
ClassLoader JavaDoc ctxLoader = Thread.currentThread().getContextClassLoader();
169       for(int p = 0; p < handlerPkgs.length; p ++)
170       {
171          try
172          {
173             // Form the standard protocol handler class name
174
String JavaDoc classname = handlerPkgs[p] + "." + protocol + ".Handler";
175             Class JavaDoc type = null;
176
177             try
178             {
179                type = ctxLoader.loadClass(classname);
180             }
181             catch(ClassNotFoundException JavaDoc e)
182             {
183                // Try our class loader
184
type = Class.forName(classname);
185             }
186
187             if( type != null )
188             {
189                handler = (URLStreamHandler JavaDoc) type.newInstance();
190                handlerMap.put(protocol, handler);
191                log.trace("Found protocol:"+protocol+" handler:"+handler);
192             }
193          }
194          catch (Throwable JavaDoc ignore)
195          {
196          }
197       }
198
199       createURLStreamHandlerProtocol.set(null);
200       return handler;
201    }
202
203    /** See if the java.protocol.handler.pkgs system property has changed
204     and if it has, parse it to update the handlerPkgs array.
205     */

206    private synchronized void checkHandlerPkgs()
207    {
208       String JavaDoc handlerPkgsProp = System.getProperty("java.protocol.handler.pkgs");
209       if( handlerPkgsProp != null && handlerPkgsProp.equals(lastHandlerPkgs) == false )
210       {
211          // Update the handlerPkgs[] from the handlerPkgsProp
212
StringTokenizer JavaDoc tokeninzer = new StringTokenizer JavaDoc(handlerPkgsProp, "|");
213          ArrayList JavaDoc tmp = new ArrayList JavaDoc();
214          while( tokeninzer.hasMoreTokens() )
215          {
216             String JavaDoc pkg = tokeninzer.nextToken().intern();
217             if( tmp.contains(pkg) == false )
218                tmp.add(pkg);
219          }
220          // Include the JBoss default protocol handler pkg
221
if( tmp.contains(PACKAGE_PREFIX) == false )
222             tmp.add(PACKAGE_PREFIX);
223          handlerPkgs = new String JavaDoc[tmp.size()];
224          tmp.toArray(handlerPkgs);
225          lastHandlerPkgs = handlerPkgsProp;
226       }
227    }
228
229 }
230
Popular Tags