KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > tax > parser > TreeStreamSource


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.modules.xml.tax.parser;
21
22 import java.io.IOException JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.text.MessageFormat JavaDoc;
25 import org.netbeans.api.xml.services.UserCatalog;
26 import org.netbeans.tax.io.TreeBuilder;
27 import org.netbeans.tax.io.TreeInputSource;
28 import org.netbeans.tax.io.TreeStreamBuilderErrorHandler;
29 import org.openide.ErrorManager;
30 import org.openide.awt.StatusDisplayer;
31 import org.xml.sax.EntityResolver JavaDoc;
32 import org.xml.sax.InputSource JavaDoc;
33 import org.xml.sax.SAXException JavaDoc;
34
35 /**
36  * Creates DOM-like structure called Tree.
37  * <p>
38  * The result structure consists from two layers:
39  * declaration-layer-object <- instance-layer-object.getDecl() i.e.
40  * similar to Class and Object.
41  * <p>
42  * It is believed that this representation is more suitable
43  * than pure DOM for development tool purposes. It may become
44  * void as DOM3 introduces events, node identity, clones, merging etc.
45  *
46  * @author Petr Kuzel
47  * @author Libor Kramolis
48  * @version 2.0 delegation to implementations
49  */

50 public class TreeStreamSource implements TreeInputSource {
51
52     private static final String JavaDoc BUILDER_IMPL = "org.netbeans.tax.io.XNIBuilder"; // NOI18N
53

54     
55     /** */
56     private InputSource inputSource;
57     /** */
58     private Class JavaDoc buildClass;
59     /** */
60     private ErrorHolder errorHolder;
61         
62     //
63
// init
64
//
65

66     /** */
67     public TreeStreamSource (Class JavaDoc buildClass, InputSource inputSource, URL JavaDoc url) {
68     this.buildClass = buildClass;
69     this.inputSource = inputSource;
70         this.errorHolder = new ErrorHolder();
71     }
72
73
74     //
75
// from TreeInputSource
76
//
77

78     /**
79      */

80     public TreeBuilder getBuilder () {
81         return getImplementation();
82     }
83     
84     
85     //
86
// itself
87
//
88

89     /**
90      * Build new TreeDTD from given InputSource.
91      */

92 /* public synchronized TreeDTD buildDTDTree (InputSource in) throws IOException{
93         TreeBuilderInterface builder = getImplementation (in, getSystemEntityResolver(), errorHolder);
94         if (builder == null)
95             return null;
96         
97         return builder.buildDTDTree (in, getSystemEntityResolver(), errorHolder);
98     }*/

99     
100
101     /**
102      * Create new TreeDocument from given input source.
103      */

104 /* public synchronized TreeDocument buildXMLTree (InputSource in) throws IOException {
105         TreeBuilderInterface builder = getImplementation();
106         if (builder == null)
107             return null;
108         builder.setSource (in);
109         builder.
110         return builder.buildXMLTree(in, getSystemEntityResolver(), errorHolder);
111     }*/

112     
113     /**
114      * Get isolated implementation of tree builder
115      */

116     private TreeBuilder getImplementation () {
117     
118         ClassLoader JavaDoc loader;
119
120         if (Boolean.getBoolean("netbeans.tax.use_private_xni_impl")) { // NOI18N
121
loader = ParserLoader.getInstance();
122         if (loader == null) {
123             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug("Can not get loader."); // NOI18N
124

125             return null;
126         }
127         } else {
128             loader = TreeBuilder.class.getClassLoader(); // we need TAX module classloader which sees Xerces 2.4.0 library
129
}
130         
131         Class JavaDoc impl_c = null;
132         try {
133             impl_c = loader.loadClass(BUILDER_IMPL);
134         } catch (ClassNotFoundException JavaDoc ex) {
135             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("!!! TreeStreamSource.getImplementation", ex);
136
137             return null;
138         }
139         
140         try {
141             java.lang.reflect.Constructor JavaDoc impl_const = impl_c.getConstructor (new Class JavaDoc[] { Class JavaDoc.class, InputSource.class, EntityResolver JavaDoc.class, TreeStreamBuilderErrorHandler.class });
142             return (TreeBuilder) impl_const.newInstance (new Object JavaDoc[] { buildClass, inputSource, getSystemEntityResolver(), errorHolder });
143 // return (TreeBuilder) impl_c.newInstance();
144
} catch (java.lang.reflect.InvocationTargetException JavaDoc ex) {
145         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (ex);
146
147         return null;
148         } catch (NoSuchMethodException JavaDoc ex) {
149         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (ex);
150             
151             return null;
152         } catch (InstantiationException JavaDoc ex) {
153         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (ex);
154             
155             return null;
156         } catch (IllegalAccessException JavaDoc ex) {
157         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (ex);
158             
159             return null;
160         }
161     
162     }
163     
164     /**
165      * Return a user's catalog based resolver or null
166      */

167     private EntityResolver JavaDoc getSystemEntityResolver() {
168
169         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("TreeStreamSource.getSystemEntityResolver:");
170
171         UserCatalog catalog = UserCatalog.getDefault();
172
173         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (" UserCatalog.getDefault() = " + catalog);
174
175         EntityResolver JavaDoc resolver = (catalog == null ? null : catalog.getEntityResolver());
176
177         if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug (" EntityResolver = " + resolver);
178                 
179         if (resolver == null) return null;
180         
181         // wrap it to timeouted resolver
182
resolver = new EntityResolverWrapper (resolver);
183         
184         return resolver;
185     }
186
187     // ~~~~~~~~~~~~~~~~~~~~~ ERROR REPORTING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188

189     
190     //
191
// class ErrorHolder
192
//
193

194     /**
195      *
196      */

197     private class ErrorHolder implements TreeStreamBuilderErrorHandler {
198           
199         public void message (int type, org.xml.sax.SAXParseException JavaDoc e) {
200             
201             if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("Builder ex", e); // NOI18N
202

203         }
204         
205     } // end: class ErrorHolder
206

207
208     //
209
// RESOLVERS
210
//
211

212     /**
213      * class EmptyEntityResolver.
214      */

215     static class EmptyEntityResolver implements EntityResolver JavaDoc {
216
217         public InputSource resolveEntity (String JavaDoc publicId, String JavaDoc systemId) throws SAXException JavaDoc, IOException JavaDoc {
218             return null;
219         }
220
221     } // end: class EmptyEntityResolver
222

223     
224     /**
225      * Timeout-ed resolver wrapping another one giving it
226      * limited time to perform resolution.
227      *
228      * //??? It timeoutes just the resolution process, another timeouted
229      * thing should be sockets actually used to download data, but how can
230      * I get to socket to setSoTimeout()? See http://www.logicamente.com/sockets.html
231      * how Borland JDK Http[Timeout]Handler is patched.
232      */

233     static class EntityResolverWrapper implements EntityResolver JavaDoc {
234         /** */
235         private final EntityResolver JavaDoc res;
236
237         public EntityResolverWrapper(EntityResolver JavaDoc er) {
238             if (er == null) throw new NullPointerException JavaDoc();
239             res = er;
240         }
241
242         /*
243          * It will block at maximum for timeout period. Then it throws IOException
244          * indication that resolution timeouted.
245          */

246         public InputSource resolveEntity (final String JavaDoc publicId, final String JavaDoc systemId) throws SAXException JavaDoc, IOException JavaDoc {
247
248             // parse catalogs explicitly eliminating timeout on first resolution
249
// we use such IDs that there is not reason for I/O i.e. block (#19779)
250
// [jglick] It is illegal to pass null for systemId! breaks e.g. contrib/docbook
251
res.resolveEntity(null, "urn:nowhere"); // NOI18N
252

253             final ErrorManager emgr = ErrorManager.getDefault();
254             final InputSource MARK = new InputSource("mark"); // NOI18N
255

256             try {
257
258                 final InputSource result[] = new InputSource[] {MARK};
259                 final SAXException JavaDoc sex[] = new SAXException JavaDoc[1];
260                 final IOException JavaDoc ioex[] = new IOException JavaDoc[1];
261
262                 // asynchronous thread body uses above fileds to comunicate
263
// its result
264

265                 Runnable JavaDoc task = new Runnable JavaDoc() {
266                     
267                     public void run() {
268                         
269                         InputSource is = MARK;
270                         try {
271                             is = res.resolveEntity(publicId, systemId);
272                         } catch (IOException JavaDoc _ioex) {
273                             ioex[0] = _ioex;
274                         } catch (SAXException JavaDoc _sex) {
275                             sex[0] = _sex;
276                         } finally {
277                             synchronized (EntityResolverWrapper.this) {
278                                 if (is != MARK) result[0] = is;
279                                 EntityResolverWrapper.this.notify();
280                             }
281                         }
282                     }
283                 };
284                 
285                 // use private thread per request
286
// because there is no guarantee that it ever finishes
287

288                 Thread JavaDoc thread = new Thread JavaDoc(task, "Timeouted EntityResolver"); // NOI18N
289
thread.setDaemon(true);
290                 thread.start();
291
292                 // according to passed time change status line
293

294                 synchronized (this) { //TRY IT
295
if (result[0] == MARK) {
296                         wait(300);
297                     }
298                 }
299
300                 if (result[0] == MARK) {
301                     
302                     StatusDisplayer.getDefault().setStatusText (Util.THIS.getString("MSG_resolving"));
303                     
304                     synchronized (this) { //TRY IT 2
305
int timeout = Integer.getInteger("netbeans.xml.resolver.timeout", 5000).intValue(); //??? expose to settings? // NOI18N
306
if (result[0] == MARK) {
307                             wait(timeout); // get notified by "Timeouted EntityResolver" thread
308
}
309                     }
310                 }
311
312                 if (result[0] != MARK) {
313                     return result[0];
314                 } else if (sex[0] != null) {
315                     throw sex[0];
316                 } else if (ioex[0] != null) {
317                     throw ioex[0];
318                 } else {
319                     
320                     // perform timeout procedure
321

322                     thread.interrupt();
323                     thread.setPriority(Thread.MIN_PRIORITY);
324                     thread.setName("Zombie"); // NOI18N
325

326                     final IOException JavaDoc CANNOT_CONNECT =
327                         new IOException JavaDoc("Resolution timeout \"" + systemId + "\" (" + publicId + ")"); // NOI18N
328
String JavaDoc pattern = Util.THIS.getString("MSG_cannot_connect");
329                     Object JavaDoc[] params = new String JavaDoc[] {publicId, systemId};
330                     String JavaDoc annotation = MessageFormat.format(pattern, params);
331                     emgr.annotate(CANNOT_CONNECT, annotation);
332                     
333                     throw CANNOT_CONNECT;
334                 }
335                 
336             } catch (InterruptedException JavaDoc iex) {
337                 
338                 // throw IOException annotated by InterruptedException reason
339

340                 final IOException JavaDoc INTERRUPTED =
341                     new IOException JavaDoc("Resolution interrupted \"" + systemId + "\" (" + publicId + ")"); // NOI18N
342

343                 String JavaDoc pattern = Util.THIS.getString("MSG_interrupted");
344                 Object JavaDoc[] params = new String JavaDoc[] {publicId, systemId};
345                 String JavaDoc annotation = MessageFormat.format(pattern, params);
346                 emgr.annotate(INTERRUPTED, annotation);
347
348                 throw INTERRUPTED;
349                 
350             } finally {
351                 StatusDisplayer.getDefault().setStatusText(""); // NOI18N
352
}
353
354         }
355         
356         public String JavaDoc toString() {
357             return super.toString() + Util.THIS.getString ("PROP_wrapping") + res.toString();
358         }
359         
360     } // end: class EntityResolverWrapper
361

362 }
363
Popular Tags