KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > startup > NbURLStreamHandlerFactory


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.core.startup;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.lang.reflect.Field JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLConnection JavaDoc;
28 import java.net.URLStreamHandler JavaDoc;
29 import java.net.URLStreamHandlerFactory JavaDoc;
30 import java.util.Collection JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.logging.Level JavaDoc;
33 import java.util.logging.Logger JavaDoc;
34 import org.openide.filesystems.FileUtil;
35 import org.openide.util.Lookup;
36 import org.openide.util.LookupEvent;
37 import org.openide.util.LookupListener;
38 import org.openide.util.NbBundle;
39
40 /**
41  * Proxying stream handler factory. Currently searches Lookup for registered
42  * factories and delegates to them. But #20838 suggests using JNDI instead,
43  * in which case registering them via Lookup would be deprecated.
44  * @author Jesse Glick
45  */

46 final class NbURLStreamHandlerFactory implements URLStreamHandlerFactory JavaDoc, LookupListener {
47     private static Logger JavaDoc LOG = Logger.getLogger(NbURLStreamHandlerFactory.class.getName());
48     
49     private Lookup.Result<URLStreamHandlerFactory JavaDoc> r = null;
50     private URLStreamHandlerFactory JavaDoc[] handlers = null;
51     private URLStreamHandlerFactory JavaDoc delegate;
52     
53     public NbURLStreamHandlerFactory() {}
54     
55     public URLStreamHandler JavaDoc createURLStreamHandler(String JavaDoc protocol) {
56         if (protocol.equals("jar") || protocol.equals("file") || // NOI18N
57
protocol.equals("http") || protocol.equals("resource")) { // NOI18N
58
// Well-known handlers in JRE. Do not try to initialize lookup, etc.
59
return null;
60         }
61         
62         if (protocol.equals("nbfs")) { // NOI18N
63
return FileUtil.nbfsURLStreamHandler();
64         }
65         
66         if (protocol.equals(NbResourceStreamHandler.PROTOCOL_SYSTEM_RESOURCE) ||
67                    protocol.equals(NbResourceStreamHandler.PROTOCOL_LOCALIZED_SYSTEM_RESOURCE)) {
68            return new NbResourceStreamHandler();
69         }
70         
71         URLStreamHandlerFactory JavaDoc d = delegate;
72         if (d != null) {
73             URLStreamHandler JavaDoc h = d.createURLStreamHandler(protocol);
74             if (h != null) {
75                 return h;
76             }
77         }
78         
79         URLStreamHandlerFactory JavaDoc[] _handlers;
80         synchronized (this) {
81             if (r == null) {
82                 r = Lookup.getDefault().lookupResult(URLStreamHandlerFactory JavaDoc.class);
83                 r.addLookupListener(this);
84                 resultChanged(null);
85             }
86             _handlers = handlers;
87         }
88         if (_handlers == null) {
89             // Too early during startup (#75422)
90
return null;
91         }
92         for (int i = 0; i < _handlers.length; i++) {
93             URLStreamHandler JavaDoc h = _handlers[i].createURLStreamHandler(protocol);
94             if (h != null) {
95                 return h;
96             }
97         }
98         return null;
99     }
100     
101     public void resultChanged(LookupEvent ev) {
102         Collection JavaDoc<? extends URLStreamHandlerFactory JavaDoc> c = r.allInstances();
103         synchronized (this) {
104             handlers = c.toArray(new URLStreamHandlerFactory JavaDoc[0]);
105         }
106     }
107
108     void registerUsingReflection(Error JavaDoc e) {
109         LOG.log(Level.CONFIG, "Problems registering URLStreamHandlerFactory, trying reflection", e); // NOI18N
110
try {
111             URLStreamHandlerFactory JavaDoc prev = null;
112             for (Field JavaDoc f : URL JavaDoc.class.getDeclaredFields()) {
113                 LOG.log(Level.FINEST, "Found field {0}", f);
114                 if (f.getType() == URLStreamHandlerFactory JavaDoc.class) {
115                     LOG.log(Level.FINEST, "Clearing field {0}");
116                     f.setAccessible(true);
117                     prev = (URLStreamHandlerFactory JavaDoc)f.get(null);
118                     LOG.log(Level.CONFIG, "Previous value was {0}", prev);
119                     f.set(null, null);
120                     LOG.config("Field is supposed to be empty");
121                     break;
122                 }
123             }
124             URL.setURLStreamHandlerFactory(this);
125             delegate = prev;
126         } catch (Throwable JavaDoc t) {
127             LOG.log(Level.SEVERE,
128                 "No way to register URLStreamHandlerFactory; NetBeans is unlikely to work",
129                 t
130             ); // NOI18N
131
}
132     }
133     
134     /** Stream handler for internal resource-based URLs.
135      * Copied with modifications from org.openide.execution - that version is now
136      * deprecated and handles only deprecated protocols.
137      * @author Jesse Glick
138      */

139     private static final class NbResourceStreamHandler extends URLStreamHandler JavaDoc {
140         
141         public NbResourceStreamHandler() {}
142         
143         public static final String JavaDoc PROTOCOL_SYSTEM_RESOURCE = "nbres"; // NOI18N
144
public static final String JavaDoc PROTOCOL_LOCALIZED_SYSTEM_RESOURCE = "nbresloc"; // NOI18N
145

146         public URLConnection JavaDoc openConnection(URL JavaDoc u) throws IOException JavaDoc {
147             if (u.getProtocol().equals(PROTOCOL_SYSTEM_RESOURCE)) {
148                 return new Connection JavaDoc(u, false);
149             } else if (u.getProtocol().equals(PROTOCOL_LOCALIZED_SYSTEM_RESOURCE)) {
150                 return new Connection JavaDoc(u, true);
151             } else {
152                 throw new IOException JavaDoc("Bad protocol: " + u.getProtocol()); // NOI18N
153
}
154         }
155         
156         private static class Connection extends URLConnection JavaDoc {
157             
158             private final boolean localized;
159             
160             // A real connection to delegate to. Non-null if successfully connected.
161
private URLConnection JavaDoc real;
162             
163             private IOException JavaDoc exception = null;
164             
165             public Connection(URL JavaDoc u, boolean localized) {
166                 super(u);
167                 this.localized = localized;
168             }
169             
170             /** Tries to get a URL from this resource from the proper classloader,
171              * localizing first if requested.
172              * Also opens the URL to make a connection; this connection, <code>real</code>,
173              * will be delegated to for all operations.
174              */

175             public synchronized void connect() throws IOException JavaDoc {
176                 if (exception != null) {
177                     // See tryToConnect().
178
IOException JavaDoc e = exception;
179                     exception = null;
180                     throw e;
181                 }
182                 if (! connected) {
183                     String JavaDoc resource = url.getPath();
184                     if (resource.length() > 0 && resource.charAt(0) == '/') resource = resource.substring(1); // NOI18N
185
ClassLoader JavaDoc loader = Lookup.getDefault().lookup(ClassLoader JavaDoc.class);
186                     URL JavaDoc target;
187                     URL JavaDoc t1 = loader.getResource(resource);
188                     if (localized) {
189                         // Find the suffix insertion point.
190
// XXX #29580: should have a shared API for this
191
int dotIndex = resource.lastIndexOf('.');
192                         if (dotIndex < resource.lastIndexOf('/')) {
193                             dotIndex = -1;
194                         }
195                         String JavaDoc base, ext;
196                         if (dotIndex != -1) {
197                             base = resource.substring(0, dotIndex);
198                             ext = resource.substring(dotIndex);
199                         } else {
200                             base = resource;
201                             ext = "";
202                         }
203                         target = null;
204                         Iterator JavaDoc<String JavaDoc> suffixes = NbBundle.getLocalizingSuffixes();
205                         while (suffixes.hasNext()) {
206                             String JavaDoc suffix = suffixes.next();
207                             target = "".equals(suffix)? t1: loader.getResource(base + suffix + ext);
208                             if (target != null) {
209                                 break;
210                             }
211                         }
212                     } else {
213                         target = t1;
214                     }
215                     if (target == null) {
216                         throw new IOException JavaDoc(NbBundle.getMessage(NbURLStreamHandlerFactory.class, "EXC_nbres_cannot_connect", url));
217                     }
218                     real = target.openConnection();
219                     real.connect();
220                     connected = true;
221                 }
222             }
223             
224             /** Try to connect; but if it does not work, oh well.
225              * Ideally this would be quite unnecessary.
226              * Unfortunately much code, inclduing the Swing editor kits,
227              * gets header fields and so on without ever calling connect().
228              * These methods cannot even throw exceptions so it is a mess.
229              * E.g. if you display a nbres: URL in the ICE browser, it is fine:
230              * it calls connect() according to the specification, then
231              * getContentType() produces text/html as expected.
232              * But using the SwingBrowser default implementation, it goes
233              * ahead and calls getContentType() immediately. So we have
234              * to try to connect and get the right content type then too.
235              * This complicated the timing of error reporting.
236              */

237             private void tryToConnect() {
238                 if (connected || exception != null) return;
239                 try {
240                     connect();
241                 } catch (IOException JavaDoc ioe) {
242                     exception = ioe;
243                 }
244             }
245             
246             public String JavaDoc getHeaderField(int n) {
247                 tryToConnect();
248                 if (connected)
249                     return real.getHeaderField(n);
250                 else
251                     return null;
252             }
253             
254             public String JavaDoc getHeaderFieldKey(int n) {
255                 tryToConnect();
256                 if (connected)
257                     return real.getHeaderFieldKey(n);
258                 else
259                     return null;
260             }
261             
262             public String JavaDoc getHeaderField(String JavaDoc key) {
263                 tryToConnect();
264                 if (connected) {
265                     return real.getHeaderField(key);
266                 }
267                 return null;
268             }
269             
270             public InputStream JavaDoc getInputStream() throws IOException JavaDoc {
271                 connect();
272                 return real.getInputStream();
273             }
274             
275             public OutputStream JavaDoc getOutputStream() throws IOException JavaDoc {
276                 connect();
277                 return real.getOutputStream();
278             }
279             
280             // Should not be required, but they are:
281

282             public String JavaDoc getContentType() {
283                 tryToConnect();
284                 if (connected)
285                     return real.getContentType();
286                 else
287                     return "application/octet-stream"; // NOI18N
288
}
289             
290             public int getContentLength() {
291                 tryToConnect();
292                 if (connected)
293                     return real.getContentLength();
294                 else
295                     return 0;
296             }
297             
298             // [PENDING] might be some more methods it would be useful to delegate, possibly
299

300         }
301         
302     }
303     
304 }
305
Popular Tags