Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sun/facelets/compiler/TagLibraryConfig.java


1   /**
2    * Licensed under the Common Development and Distribution License,
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    * 
6    *   http://www.sun.com/cddl/
7    *   
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
11   * implied. See the License for the specific language governing
12   * permissions and limitations under the License.
13   */
14  
15  package com.sun.facelets.compiler;
16  
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.lang.reflect.Method;
20  import java.net.URL;
21  import java.util.logging.Level;
22  import java.util.logging.Logger;
23  
24  import javax.xml.parsers.ParserConfigurationException;
25  import javax.xml.parsers.SAXParser;
26  import javax.xml.parsers.SAXParserFactory;
27  
28  import org.xml.sax.Attributes;
29  import org.xml.sax.InputSource;
30  import org.xml.sax.Locator;
31  import org.xml.sax.SAXException;
32  import org.xml.sax.SAXParseException;
33  import org.xml.sax.XMLReader;
34  import org.xml.sax.helpers.DefaultHandler;
35  
36  import com.sun.facelets.tag.AbstractTagLibrary;
37  import com.sun.facelets.tag.TagHandler;
38  import com.sun.facelets.tag.TagLibrary;
39  import com.sun.facelets.util.ParameterCheck;
40  import com.sun.facelets.util.Classpath;
41  
42  /**
43   * Handles creating a {@link com.sun.facelets.tag.TagLibrary TagLibrary} from a
44   * {@link java.net.URL URL} source.
45   * 
46   * @author Jacob Hookom
47   * @version $Id: TagLibraryConfig.java,v 1.9 2006/05/03 05:18:10 jhook Exp $
48   */
49  public final class TagLibraryConfig {
50  
51      private final static String SUFFIX = ".taglib.xml";
52  
53      protected final static Logger log = Logger.getLogger("facelets.compiler");
54  
55      private static class TagLibraryImpl extends AbstractTagLibrary {
56          public TagLibraryImpl(String namespace) {
57              super(namespace);
58          }
59  
60          public void putConverter(String name, String id) {
61              ParameterCheck.notNull("name", name);
62              ParameterCheck.notNull("id", id);
63              this.addConverter(name, id);
64          }
65  
66          public void putConverter(String name, String id, Class handlerClass) {
67              ParameterCheck.notNull("name", name);
68              ParameterCheck.notNull("id", id);
69              ParameterCheck.notNull("handlerClass", handlerClass);
70              this.addConverter(name, id, handlerClass);
71          }
72  
73  
74          public void putValidator(String name, String id) {
75              ParameterCheck.notNull("name", name);
76              ParameterCheck.notNull("id", id);
77              this.addValidator(name, id);
78          }
79  
80          public void putValidator(String name, String id, Class handlerClass) {
81              ParameterCheck.notNull("name", name);
82              ParameterCheck.notNull("id", id);
83              ParameterCheck.notNull("handlerClass", handlerClass);
84              this.addValidator(name, id, handlerClass);
85          }
86  
87          public void putTagHandler(String name, Class type) {
88              ParameterCheck.notNull("name", name);
89              ParameterCheck.notNull("type", type);
90              this.addTagHandler(name, type);
91          }
92  
93          public void putComponent(String name, String componentType,
94                  String rendererType) {
95              ParameterCheck.notNull("name", name);
96              ParameterCheck.notNull("componentType", componentType);
97              this.addComponent(name, componentType, rendererType);
98          }
99  
100         public void putComponent(String name, String componentType,
101                 String rendererType, Class handlerClass) {
102             ParameterCheck.notNull("name", name);
103             ParameterCheck.notNull("componentType", componentType);
104             ParameterCheck.notNull("handlerClass", handlerClass);
105             this.addComponent(name, componentType, rendererType, handlerClass);
106         }
107 
108 
109         public void putUserTag(String name, URL source) {
110             ParameterCheck.notNull("name", name);
111             ParameterCheck.notNull("source", source);
112             this.addUserTag(name, source);
113         }
114         
115         public void putFunction(String name, Method method) {
116             ParameterCheck.notNull("name", name);
117             ParameterCheck.notNull("method", method);
118             this.addFunction(name, method);
119         }
120     }
121 
122     private static class LibraryHandler extends DefaultHandler {
123         private final String file;
124 
125         private final URL source;
126 
127         private TagLibrary library;
128 
129         private final StringBuffer buffer;
130 
131         private Locator locator;
132 
133         private String tagName;
134 
135         private String componentClassName;
136 
137         private String componentType;
138 
139         private String rendererType;
140         
141         private String functionName;
142         
143         private Class handlerClass;
144 
145         private Class functionClass;
146         
147         private String functionSignature;
148 
149         public LibraryHandler(URL source) {
150             this.file = source.getFile();
151             this.source = source;
152             this.buffer = new StringBuffer(64);
153         }
154 
155         public TagLibrary getLibrary() {
156             return this.library;
157         }
158 
159         public void endElement(String uri, String localName, String qName)
160                 throws SAXException {
161             try {
162                 if ("facelet-taglib".equals(qName)) {
163                   ; // Nothing to do
164                 }
165                 else if ("library-class".equals(qName)) {
166                     this.processLibraryClass();
167                 }
168                 else if ("namespace".equals(qName)) {
169                     this.library = new TagLibraryImpl(this.captureBuffer());
170                 }
171                 else if ("component-type".equals(qName)) {
172                     this.componentType = this.captureBuffer();
173                 }
174                 else if ("renderer-type".equals(qName)) {
175                     this.rendererType = this.captureBuffer();
176                 }
177                 else if ("tag-name".equals(qName)) {
178                     this.tagName = this.captureBuffer();
179                 }
180                 else if ("function-name".equals(qName)) {
181                     this.functionName = this.captureBuffer();
182                 }
183                 else if ("function-class".equals(qName)) {
184                     String className = this.captureBuffer();
185                     this.functionClass = this.createClass(Object.class, className);
186                 }
187                 else
188                 {
189                     // Make sure there we've seen a namespace element
190                     // before trying any of the following elements to avoid
191                     // obscure NPEs
192                     if (this.library == null) {
193                         throw new IllegalStateException("No <namespace> element");
194                     }
195                     
196                     TagLibraryImpl impl = (TagLibraryImpl) this.library;
197                     
198                     if ("tag".equals(qName)) {
199                         if (this.handlerClass != null) {
200                             impl.putTagHandler(this.tagName, this.handlerClass);
201                         }
202                     }
203                     else if ("handler-class".equals(qName)) {
204                         String cName = this.captureBuffer();
205                         this.handlerClass = this.createClass(
206                                                   TagHandler.class, cName);
207                     }
208                     else if ("component".equals(qName)) {
209                         if (this.handlerClass != null) {
210                             impl.putComponent(this.tagName,
211                                               this.componentType,
212                                               this.rendererType,
213                                               this.handlerClass);
214                             this.handlerClass = null;
215                         }
216                         else {
217                             impl.putComponent(this.tagName,
218                                               this.componentType,
219                                               this.rendererType);
220                         }
221                     }
222                     else if ("converter-id".equals(qName)) {
223                         if (this.handlerClass != null) {
224                             impl.putConverter(this.tagName,
225                                               this.captureBuffer(),
226                                               handlerClass);
227                             this.handlerClass = null;
228                         }
229                         else {
230                             impl.putConverter(this.tagName,
231                                               this.captureBuffer());
232                         }
233                     }
234                     else if ("validator-id".equals(qName)) {
235                         if (this.handlerClass != null) {
236                             impl.putValidator(this.tagName,
237                                               this.captureBuffer(),
238                                               handlerClass);
239                             this.handlerClass = null;
240                         }
241                         else {
242                             impl.putValidator(this.tagName,
243                                               this.captureBuffer());
244                         }
245                     }
246                     else  if ("source".equals(qName)) {
247                         String path = this.captureBuffer();
248                         URL url = new URL(this.source, path);
249                         impl.putUserTag(this.tagName, url);
250                     }
251                     else if ("function-signature".equals(qName)) {
252                         this.functionSignature = this.captureBuffer();
253                         Method m = this.createMethod(this.functionClass, this.functionSignature);
254                         impl.putFunction(this.functionName, m);
255                     }
256                 }
257             } catch (Exception e) {
258                 SAXException saxe =
259                    new SAXException("Error Handling [" + this.source + "@"
260                         + this.locator.getLineNumber() + ","
261                         + this.locator.getColumnNumber() + "] <" + qName
262                                     + ">");
263                 saxe.initCause(e);
264                 throw saxe;
265             }
266         }
267 
268         private String captureBuffer() throws Exception {
269             String s = this.buffer.toString().trim();
270             if (s.length() == 0) {
271                 throw new Exception("Value Cannot be Empty");
272             }
273             this.buffer.setLength(0);
274             return s;
275         }
276 
277         private static Class createClass(Class type, String name) throws Exception {
278             Class factory = ReflectionUtil.forName(name);
279             if (!type.isAssignableFrom(factory)) {
280                 throw new Exception(name + " must be an instance of "
281                         + type.getName());
282             }
283             return factory;
284         }
285         
286         private static Method createMethod(Class type, String s) throws Exception {
287             Method m = null;
288             int pos = s.indexOf(' ');
289             if (pos == -1) {
290                 throw new Exception("Must Provide Return Type: "+s);
291             } else {
292                 String rt = s.substring(0, pos).trim();
293                 int pos2 = s.indexOf('(', pos+1);
294                 if (pos2 == -1) {
295                     throw new Exception("Must provide a method name, followed by '(': "+s);
296                 } else {
297                     String mn = s.substring(pos+1, pos2).trim();
298                     pos = s.indexOf(')', pos2 + 1);
299                     if (pos == -1) {
300                         throw new Exception("Must close parentheses, ')' missing: "+s);
301                     } else {
302                         String[] ps = s.substring(pos2 + 1, pos).trim().split(",");
303                         Class[] pc;
304                         if (ps.length == 1 && "".equals(ps[0])) {
305                             pc = new Class[0];
306                         } else {
307                             pc = new Class[ps.length];
308                             for (int i = 0; i < pc.length; i ++) {
309                                 pc[i] = ReflectionUtil.forName(ps[i].trim());
310                             }
311                         }
312                         try {
313                             return type.getMethod(mn, pc);
314                         } catch (NoSuchMethodException e) {
315                             throw new Exception("No Function Found on type: "+type.getName()+" with signature: "+s);
316                         }
317                         
318                     }
319                             
320                 }
321             }
322         }
323 
324         private void processLibraryClass() throws Exception {
325             String name = this.captureBuffer();
326             Class type = this.createClass(TagLibrary.class, name);
327             this.library = (TagLibrary) type.newInstance();
328         }
329 
330         public InputSource resolveEntity(String publicId, String systemId)
331                 throws SAXException {
332             if ("-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
333                     .equals(publicId)) {
334                 URL url = Thread.currentThread().getContextClassLoader()
335                         .getResource("facelet-taglib_1_0.dtd");
336                 return new InputSource(url.toExternalForm());
337             }
338             return null;
339         }
340 
341         public void characters(char[] ch, int start, int length)
342                 throws SAXException {
343             this.buffer.append(ch, start, length);
344         }
345 
346         public void startElement(String uri, String localName, String qName,
347                 Attributes attributes) throws SAXException {
348             this.buffer.setLength(0);
349             if ("tag".equals(qName)) {
350                 this.componentClassName = null;
351                 this.handlerClass = null;
352                 this.componentType = null;
353                 this.rendererType = null;
354                 this.tagName = null;
355             } else if ("function".equals(qName)) {
356                 this.functionName = null;
357                 this.functionClass = null;
358                 this.functionSignature = null;
359             }
360         }
361 
362         public void error(SAXParseException e) throws SAXException {
363             SAXException saxe = 
364                 new SAXException("Error Handling [" + this.source + "@"
365                       + e.getLineNumber() + "," + e.getColumnNumber() + "]");
366             saxe.initCause(e);
367             throw saxe;
368         }
369 
370         public void setDocumentLocator(Locator locator) {
371             this.locator = locator;
372         }
373 
374         public void fatalError(SAXParseException e) throws SAXException {
375             throw e;
376         }
377 
378         public void warning(SAXParseException e) throws SAXException {
379             throw e;
380         }
381     }
382 
383     public TagLibraryConfig() {
384         super();
385     }
386 
387     public static TagLibrary create(URL url) throws IOException {
388         InputStream is = null;
389         TagLibrary t = null;
390         try {
391             is = url.openStream();
392             LibraryHandler handler = new LibraryHandler(url);
393             SAXParser parser = createSAXParser(handler);
394             parser.parse(is, handler);
395             t = handler.getLibrary();
396         } catch (SAXException e) {
397           IOException ioe =
398             new IOException("Error parsing [" + url + "]: ");
399           ioe.initCause(e);
400           throw ioe;
401         } catch (ParserConfigurationException e) {
402           IOException ioe =
403             new IOException("Error parsing [" + url + "]: ");
404           ioe.initCause(e);
405           throw ioe;
406         } finally {
407             if (is != null)
408                 is.close();
409         }
410         return t;
411     }
412 
413     public void loadImplicit(Compiler compiler) throws IOException {
414         ClassLoader cl = Thread.currentThread().getContextClassLoader();
415         URL[] urls = Classpath.search(cl, "META-INF/", SUFFIX);
416         for (int i = 0; i < urls.length; i++) {
417             try {
418                 compiler.addTagLibrary(create(urls[i]));
419                 log.info("Added Library from: " + urls[i]);
420             } catch (Exception e) {
421                 log.log(Level.SEVERE, "Error Loading Library: " + urls[i], e);
422             }
423         }
424     }
425 
426     private static final SAXParser createSAXParser(LibraryHandler handler)
427             throws SAXException, ParserConfigurationException {
428         SAXParserFactory factory = SAXParserFactory.newInstance();
429         factory.setNamespaceAware(false);
430         factory.setFeature("http://xml.org/sax/features/validation", true);
431         factory.setValidating(true);
432         SAXParser parser = factory.newSAXParser();
433         XMLReader reader = parser.getXMLReader();
434         reader.setErrorHandler(handler);
435         reader.setEntityResolver(handler);
436         return parser;
437     }
438 
439 }