KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > system > url > GeronimoURLFactory


1 /**
2  *
3  * Copyright 2004 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.geronimo.system.url;
19
20 import java.lang.reflect.Field JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.net.URLStreamHandler JavaDoc;
23 import java.security.AccessController JavaDoc;
24 import java.security.PrivilegedAction JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import org.apache.geronimo.gbean.GBeanInfo;
33 import org.apache.geronimo.gbean.GBeanInfoBuilder;
34 import org.apache.geronimo.gbean.GBeanLifecycle;
35
36 /**
37  * This service replaces the URLStreamHandlerFactory used in URL, which gives Geronimo
38  * complete control over the URLs creted in the server. This allows us to replace the
39  * broken implementation of the "file" protocol.
40  *
41  * @version $Rev: 151106 $ $Date: 2005-02-02 18:49:54 -0800 (Wed, 02 Feb 2005) $
42  */

43 public class GeronimoURLFactory implements GBeanLifecycle {
44     private static final URLStreamHandlerFactory factory = new URLStreamHandlerFactory();
45     private static boolean installed = false;
46
47     public void doStart() throws Exception JavaDoc {
48         // verify that our factory is installed... if our factory can not be
49
// installed the gbean will fail
50
install();
51     }
52
53     public void doStop() throws Exception JavaDoc {
54     }
55
56     public void doFail() {
57     }
58
59     /**
60      * Assigns the handler to the specified protocol.
61      *
62      * @param protocol the prototcol name
63      * @param handler the url handler for the protocol
64      * @throws IllegalStateException if a handler is alreayd assigned to the protocol
65      */

66     public void registerHandler(String JavaDoc protocol, URLStreamHandler JavaDoc handler) {
67         factory.registerHandler(protocol, handler);
68     }
69
70     /**
71      * Gets the handler registered for the specified protocol
72      *
73      * @param protocol the protocol name
74      * @return the registered handler or null if no handler is registerd for the protocol
75      */

76     public URLStreamHandler JavaDoc getRegisteredHandler(String JavaDoc protocol) {
77         return factory.getRegisteredHandler(protocol);
78     }
79
80     /**
81      * Gets a map of all registered handlers keyed by protocol name.
82      *
83      * @return a map from protocol name to handler
84      */

85     public Map JavaDoc getRegisteredHandlers() {
86         return factory.getRegisteredHandlers();
87     }
88
89     /**
90      * Is our factory installed?
91      *
92      * @return true if our factory is installed; false otherwise
93      */

94     public static boolean isInstalled() {
95         return installed;
96     }
97
98     /**
99      * Installs the factory into URL using the setURLStreamHandlerFactory method.
100      * This will fail is some other code already installed a factory.
101      * <p/>
102      * This should be called from your main method to assure the factory is installed
103      * before another code has a chance to take the slot.
104      *
105      * @throws Error if the application has already set a factory
106      * @throws SecurityException if a security manager exists and its checkSetFactory method doesn't allow the operation
107      */

108     public static void install() throws Error JavaDoc, SecurityException JavaDoc {
109         if (!installed) {
110             URL.setURLStreamHandlerFactory(factory);
111             installed = true;
112         }
113     }
114
115     /**
116      * Installs the factory into directly URL's private and package protected fields using
117      * Field.setAccessable(true). This is the "naughty" way of installing a factory but works
118      * on most platforms. If the platform is not using Sun's implementation of URL, this code is
119      * likely to not work, but all known platforms use Sun's URL code.
120      * <p/>
121      * You should not use this method unless you absolutely have to.
122      *
123      * @throws Error if the application has already set a factory
124      * @throws SecurityException if a security manager exists and its checkSetFactory method doesn't allow the operation
125      */

126     public static void forceInstall() throws Error JavaDoc, SecurityException JavaDoc {
127         if (!installed) {
128             // This way is "naughty" but works great
129
Throwable JavaDoc t = (Throwable JavaDoc) AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
130                 public Object JavaDoc run() {
131                     try {
132                         // get a reference to the URL stream handler lock... we need to
133
// synchronize on this field to be safe
134
Field JavaDoc streamHandlerLockField = URL JavaDoc.class.getDeclaredField("streamHandlerLock");
135                         streamHandlerLockField.setAccessible(true);
136                         Object JavaDoc streamHandlerLock = streamHandlerLockField.get(null);
137
138                         synchronized (streamHandlerLock) {
139                             // get a reference to the factory field and change the permissions
140
// to make it accessable (factory is a package protected field)
141
Field JavaDoc factoryField = URL JavaDoc.class.getDeclaredField("factory");
142                             factoryField.setAccessible(true);
143
144                             // get a reference to the handlers field and change the permissions
145
// to make it accessable (handlers is a package protected field)
146
Field JavaDoc handlersField = URL JavaDoc.class.getDeclaredField("handlers");
147                             handlersField.setAccessible(true);
148
149                             // the the handlers map first
150
Map JavaDoc handlers = (Map JavaDoc) handlersField.get(null);
151
152                             // set the factory field to our factory
153
factoryField.set(null, factory);
154
155                             // clear the handlers
156
handlers.clear();
157                         }
158                     } catch (Throwable JavaDoc e) {
159                         return e;
160                     }
161                     return null;
162                 }
163             });
164
165             if (t != null) {
166                 if (t instanceof SecurityException JavaDoc) {
167                     throw (SecurityException JavaDoc) t;
168                 } else if (t instanceof Error JavaDoc) {
169                     throw (Error JavaDoc) t;
170                 }
171                 throw new Error JavaDoc("Unknown error while force installing URL factory", t);
172             }
173             installed = true;
174         }
175     }
176
177     private static class URLStreamHandlerFactory implements java.net.URLStreamHandlerFactory JavaDoc {
178         private final Map JavaDoc handlers = new HashMap JavaDoc();
179         private final List JavaDoc handlerPackages = new LinkedList JavaDoc();
180
181         private URLStreamHandlerFactory() {
182             // add the packages listed in the standard system property
183
String JavaDoc systemPackages = System.getProperty("java.protocol.handler.pkgs");
184             if (systemPackages != null) {
185                 StringTokenizer JavaDoc stok = new StringTokenizer JavaDoc(systemPackages, "|");
186                 while (stok.hasMoreTokens()) {
187                     handlerPackages.add(stok.nextToken().trim());
188                 }
189             }
190             // always add the sun handlers
191
handlerPackages.add("sun.net.www.protocol");
192
193             // register our well known protocol handlers
194
// URL permanently caches our handlers so we may want to register a wrapper
195
// around the true handler to enable changing the implementation at runtime
196
handlers.put("file", new org.apache.geronimo.system.url.file.Handler());
197             handlers.put("resource", new org.apache.geronimo.system.url.resource.Handler());
198         }
199
200         public URLStreamHandler JavaDoc createURLStreamHandler(String JavaDoc protocol) {
201             if (protocol == null) {
202                 throw new IllegalArgumentException JavaDoc("protocol is null");
203             }
204             protocol = protocol.trim();
205
206             URLStreamHandler JavaDoc handler;
207
208             // first check the registered handlers
209
synchronized (this) {
210                 handler = (URLStreamHandler JavaDoc) handlers.get(protocol);
211             }
212             if (handler != null) {
213                 return handler;
214             }
215
216             // try to get the stream handler from the registered package list
217
Class JavaDoc type = findProtocolHandler(protocol);
218             if (type == null) {
219                 throw new IllegalArgumentException JavaDoc("unknown protocol: " + protocol);
220             }
221
222             try {
223                 return (URLStreamHandler JavaDoc) type.newInstance();
224             } catch (Exception JavaDoc e) {
225                 throw new IllegalArgumentException JavaDoc("Error constructing protocol handler:" +
226                         "protocol " + protocol +
227                         " messgae=" + e.getMessage());
228             }
229         }
230
231         private synchronized void registerHandler(String JavaDoc protocol, URLStreamHandler JavaDoc handler) {
232             assert protocol != null: "protocol is null";
233             assert handler != null: "handler is null";
234             if (handlers.containsKey(protocol)) {
235                 throw new IllegalStateException JavaDoc("Protocol already has a registered handler: " + protocol);
236             }
237             handlers.put(protocol, handler);
238         }
239
240         private synchronized URLStreamHandler JavaDoc getRegisteredHandler(String JavaDoc protocol) {
241             return (URLStreamHandler JavaDoc) handlers.get(protocol);
242         }
243
244         private synchronized Map JavaDoc getRegisteredHandlers() {
245             return new HashMap JavaDoc(handlers);
246         }
247
248         /**
249          * Searches each registered package for specified protocol handler. The class name
250          * is packageName + "." + protocolName + ".Handler"
251          *
252          * @param protocol the desired protocol handler
253          * @return the protocol handler or null if none is found
254          */

255         private Class JavaDoc findProtocolHandler(final String JavaDoc protocol) {
256             ClassLoader JavaDoc classLoader = Thread.currentThread().getContextClassLoader();
257             if (classLoader == null) {
258                 classLoader = ClassLoader.getSystemClassLoader();
259             }
260             for (Iterator JavaDoc iterator = handlerPackages.iterator(); iterator.hasNext();) {
261                 String JavaDoc pkg = (String JavaDoc) iterator.next();
262                 String JavaDoc classname = pkg + "." + protocol + ".Handler";
263
264                 try {
265                     return classLoader.loadClass(classname);
266                 } catch (Throwable JavaDoc e) {
267                     // ignore
268
}
269             }
270             return null;
271         }
272     }
273
274     public static final GBeanInfo GBEAN_INFO;
275
276     static {
277         GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(GeronimoURLFactory.class);
278         infoFactory.addOperation("registerHandler", new Class JavaDoc[]{String JavaDoc.class, URLStreamHandler JavaDoc.class});
279         infoFactory.addOperation("getRegisteredHandler", new Class JavaDoc[]{String JavaDoc.class});
280         infoFactory.addOperation("getRegisteredHandlers", new Class JavaDoc[]{});
281         GBEAN_INFO = infoFactory.getBeanInfo();
282     }
283
284     public static GBeanInfo getGBeanInfo() {
285         return GBEAN_INFO;
286     }
287 }
288
Popular Tags