View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.apt;
21  
22  import com.sun.mirror.apt.AnnotationProcessorEnvironment;
23  import com.sun.mirror.apt.Filer;
24  import com.sun.mirror.declaration.InterfaceDeclaration;
25  import com.sun.mirror.declaration.PackageDeclaration;
26  import org.apache.commons.io.IOUtils;
27  import org.apache.myfaces.tobago.apt.annotation.Tag;
28  import org.apache.myfaces.tobago.apt.annotation.Taglib;
29  import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
30  import org.codehaus.modello.plugin.java.javasource.JClass;
31  import org.codehaus.modello.plugin.java.javasource.JCompUnit;
32  import org.codehaus.modello.plugin.java.javasource.JConstructor;
33  import org.codehaus.modello.plugin.java.javasource.JField;
34  import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
35  import org.w3c.dom.Document;
36  import org.w3c.dom.Element;
37  
38  import javax.faces.component.UIComponent;
39  import javax.xml.parsers.DocumentBuilder;
40  import javax.xml.parsers.DocumentBuilderFactory;
41  import javax.xml.parsers.ParserConfigurationException;
42  import javax.xml.transform.OutputKeys;
43  import javax.xml.transform.Transformer;
44  import javax.xml.transform.TransformerException;
45  import javax.xml.transform.TransformerFactory;
46  import javax.xml.transform.dom.DOMSource;
47  import javax.xml.transform.stream.StreamResult;
48  import java.io.File;
49  import java.io.IOException;
50  import java.io.Writer;
51  import java.lang.reflect.Field;
52  import java.util.HashSet;
53  import java.util.Set;
54  
55  /*
56   * Date: 30.03.2006
57   * Time: 19:26:18
58   */
59  public class FaceletAnnotationVisitor extends AbstractAnnotationVisitor {
60  
61    public FaceletAnnotationVisitor(AnnotationProcessorEnvironment env) {
62      super(env);
63    }
64  
65    public void process() throws Exception {
66  
67      for (PackageDeclaration packageDeclaration : getCollectedPackageDeclarations()) {
68        Taglib taglibAnnotation = packageDeclaration.getAnnotation(Taglib.class);
69  
70        Set<String> tagSet = new HashSet<String>();
71        String packageName = "org.apache.myfaces.tobago.facelets";
72  
73        JClass libraryClass = new JClass("TobagoTagLibrary");
74        libraryClass.setPackageName(packageName);
75  
76        JCompUnit unit = new JCompUnit(libraryClass);
77        libraryClass.setSuperClass("AbstractTobagoTagLibrary");
78  
79        JField nameSpace = new JField(new JClass("String"), "NAMESPACE");
80        nameSpace.getModifiers().setFinal(true);
81        nameSpace.getModifiers().setStatic(true);
82        nameSpace.getModifiers().makePublic();
83        nameSpace.setInitString("\""+taglibAnnotation.uri()+"\"");
84        libraryClass.addField(nameSpace);
85  
86        JField instance = new JField(libraryClass, "INSTANCE");
87        instance.getModifiers().setFinal(true);
88        instance.getModifiers().setStatic(true);
89        instance.getModifiers().makePublic();
90        instance.setInitString("new "+libraryClass.getName(true) +"()");
91        libraryClass.addField(instance);
92        JConstructor constructor = libraryClass.createConstructor();
93        constructor.getSourceCode().add("super(NAMESPACE);");
94  
95        for (InterfaceDeclaration decl : getCollectedInterfaceDeclarations()) {
96          if (decl.getPackage().equals(packageDeclaration)) {
97            appendComponent(constructor, decl, tagSet);
98          }
99        }
100       Document document = createDocument(libraryClass);
101 
102       writeFaceletTaglibConfig(taglibAnnotation, document, packageDeclaration);
103       writeFaceletTaglibHandler(unit, libraryClass);
104     }
105   }
106 
107   private void writeFaceletTaglibConfig(Taglib taglibAnnotation, Document document,
108       PackageDeclaration packageDeclaration) throws IOException, TransformerException {
109     Writer faceletsConfigWriter = null;
110     try {
111       getEnv().getMessager().printNotice("Create facelets taglib config");
112       String fileName =
113           taglibAnnotation.fileName().substring(0, taglibAnnotation.fileName().length()-3) + "taglib.xml";
114 
115       faceletsConfigWriter =
116           getEnv().getFiler().createTextFile(Filer.Location.SOURCE_TREE, "", new File(fileName), null);
117       TransformerFactory transFactory = TransformerFactory.newInstance();
118       transFactory.setAttribute("indent-number", 2);
119       Transformer transformer = transFactory.newTransformer();
120       transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
121           "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN");
122       transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
123           "http://java.sun.com/dtd/facelet-taglib_1_0.dtd");
124       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
125       transformer.transform(new DOMSource(document),
126           new StreamResult(faceletsConfigWriter));
127       getEnv().getMessager().printNotice("Write to file " + packageDeclaration.getQualifiedName() + " " + fileName);
128     } finally{
129       IOUtils.closeQuietly(faceletsConfigWriter);
130     }
131   }
132 
133   private void writeFaceletTaglibHandler(JCompUnit unit, JClass clazz) throws IOException {
134     JSourceWriter sourceWriter = null;
135     try {
136       Writer writer = getEnv().getFiler().createTextFile(Filer.Location.SOURCE_TREE,
137           unit.getPackageName(),
138           new File(clazz.getLocalName()+".java"), null);
139       sourceWriter = new JSourceWriter(writer);
140       unit.print(sourceWriter);
141     } finally{
142       IOUtils.closeQuietly(sourceWriter);
143     }
144   }
145 
146   private Document createDocument(JClass libraryClass) throws ParserConfigurationException {
147     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
148     dbf.setValidating(false);
149     DocumentBuilder parser = dbf.newDocumentBuilder();
150     Document document = parser.newDocument();
151 
152     Element taglib = document.createElement("facelet-taglib");
153     addLeafTextElement(libraryClass.getName(), "library-class", taglib, document);
154 
155     document.appendChild(taglib);
156     return document;
157   }
158 
159   protected void appendComponent(JConstructor constructor, InterfaceDeclaration decl, Set<String> tagSet) {
160 
161     Tag annotationTag = decl.getAnnotation(Tag.class);
162     if (annotationTag != null) {
163       createTag(constructor, decl, annotationTag);
164 
165     }
166   }
167 
168   protected void createTag(JConstructor constructor, InterfaceDeclaration decl, Tag annotationTag) {
169     UIComponentTag componentTag = decl.getAnnotation(UIComponentTag.class);
170     if (componentTag == null) {
171       return;
172     }
173     try {
174       ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
175       Thread.currentThread().setContextClassLoader(UIComponent.class.getClassLoader());
176       Class uiComponentClass = Class.forName(componentTag.uiComponent());
177 
178       StringBuilder addComponent = new StringBuilder("addTobagoComponent(\"");
179       addComponent.append(annotationTag.name());
180 
181       Field componentField = uiComponentClass.getField("COMPONENT_TYPE");
182       String componentType = (String) componentField.get(null);
183       Thread.currentThread().setContextClassLoader(currentClassLoader);
184 
185       addComponent.append("\", \"");
186       addComponent.append(componentType);
187       addComponent.append("\", ");
188       String rendererType = componentTag.rendererType();
189       if (rendererType != null && rendererType.length() > 0) {
190         addComponent.append("\"");
191         addComponent.append(rendererType);
192         addComponent.append("\", ");
193       } else {
194         addComponent.append("null,");
195       }
196       addComponent.append("TobagoComponentHandler.class);");
197       constructor.getSourceCode().add("");
198       constructor.getSourceCode().add(addComponent.toString());
199 
200     } catch (Exception e) {
201       e.printStackTrace();
202     }
203   }
204 }