visualweb.jsfsupport/src/org/netbeans/modules/visualweb/jsfsupport/container/JsfTagSupport.java
2 * To change this template, choose Tools | Templates | Licenses | Default License
3 * and open the template in the editor.
5 package org.netbeans.modules.visualweb.jsfsupport.container;
7 import java.io.ByteArrayInputStream;
8 import java.io.IOException;
10 import java.util.ArrayList;
11 import java.util.Enumeration;
12 import java.util.HashMap;
13 import java.util.List;
15 import java.util.zip.ZipEntry;
16 import java.util.zip.ZipFile;
17 import javax.faces.webapp.UIComponentTagBase;
18 import javax.xml.parsers.DocumentBuilder;
19 import javax.xml.parsers.DocumentBuilderFactory;
20 import javax.xml.parsers.ParserConfigurationException;
21 import org.openide.filesystems.FileObject;
22 import org.openide.filesystems.FileUtil;
23 import org.openide.filesystems.URLMapper;
24 import org.openide.util.Exceptions;
25 import org.openide.util.NbBundle;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NodeList;
30 import org.xml.sax.EntityResolver;
31 import org.xml.sax.InputSource;
32 import org.xml.sax.SAXException;
35 * A Support class to find the JSF component corresponding to the JSP tag and TagLib URI
36 * @author Winston Prakash
38 public class JsfTagSupport {
40 private Map<String, TagInfo> tagInfoMap = new HashMap<String, TagInfo>();
41 private Map<String, ComponentInfo> componentInfoMap = new HashMap<String, ComponentInfo>();
42 // Static map of Taglib URI and taglib and faces-config locations in a jar
43 private static Map<String, TagLibFacesConfigInfo> statictTaglibFacesConfigLocationMap = new HashMap<String, TagLibFacesConfigInfo>();
44 // Cache of Taglib URI and JSF tag support
45 private static Map<String, JsfTagSupport> cachedTagLibraryInfoMap = new HashMap<String, JsfTagSupport>();
46 private static Object lock = new Object();
49 * This method should be called only once when the designtime JSF container is initialzed,
50 * passing the project classloader. The classpath (jars) of the classloader is scanned for
51 * TLD files and faces config files. Their locations are cached for later use
54 public static synchronized void initialize(ClassLoader classLoader) {
56 Enumeration<URL> urls = classLoader.getResources("META-INF/faces-config.xml");
57 while (urls.hasMoreElements()) {
58 addTaglibFacesConfigMapEntry(urls.nextElement());
61 // Bug Fix 124610 - Unfortunately the JSF RI component informations are not kept
62 // in the standard location (META-INF/faces-config.xml)
63 URL facesConfigUrl = classLoader.getResource("com/sun/faces/jsf-ri-runtime.xml");
64 URL tagLibUrl = new URL(facesConfigUrl.toString().split("!")[0] + "!/META-INF/html_basic.tld");
65 String taglibUri = "http://java.sun.com/jsf/html";
66 TagLibFacesConfigInfo tagLibFacesConfigInfo = new TagLibFacesConfigInfo(taglibUri);
67 tagLibFacesConfigInfo.addTagLibUrl(tagLibUrl);
68 tagLibFacesConfigInfo.addFacesConfigUrl(facesConfigUrl);
69 statictTaglibFacesConfigLocationMap.put(taglibUri, tagLibFacesConfigInfo);
71 tagLibUrl = new URL(facesConfigUrl.toString().split("!")[0] + "!/META-INF/jsf_core.tld");
72 taglibUri = "http://java.sun.com/jsf/core";
73 tagLibFacesConfigInfo = new TagLibFacesConfigInfo(taglibUri);
74 tagLibFacesConfigInfo.addTagLibUrl(tagLibUrl);
75 tagLibFacesConfigInfo.addFacesConfigUrl(facesConfigUrl);
76 statictTaglibFacesConfigLocationMap.put(taglibUri, tagLibFacesConfigInfo);
77 } catch (Exception ex) {
78 Exceptions.printStackTrace(ex);
82 private static void addTaglibFacesConfigMapEntry(URL facesConfigUrl) throws IOException, ParserConfigurationException, SAXException {
83 FileObject facesConfigFileObject = URLMapper.findFileObject(facesConfigUrl);
84 String zipFilePath = FileUtil.toFile(FileUtil.getArchiveFile(facesConfigFileObject)).getAbsolutePath();
85 ZipFile in = new ZipFile(zipFilePath);
86 Enumeration<? extends ZipEntry> entries = in.entries();
87 while (entries.hasMoreElements()) {
88 ZipEntry entry = entries.nextElement();
89 if (entry.getName().endsWith(".tld")) {
90 URL tagLibUrl = new URL(facesConfigUrl.toString().split("!")[0] + "!/" + entry.getName());
91 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
92 factory.setValidating(false);
93 DocumentBuilder documentBuilder = factory.newDocumentBuilder();
94 documentBuilder.setEntityResolver(new EmptyEntityResolver());
95 Document tagLibdocument = documentBuilder.parse(tagLibUrl.openStream());
96 NodeList tagNodes = tagLibdocument.getElementsByTagName("uri");
97 // Scan the TLD file to find the taglib URI
98 String taglibUri = tagNodes.item(0).getTextContent().trim();
100 TagLibFacesConfigInfo tagLibFacesConfigInfo = new TagLibFacesConfigInfo(taglibUri);
101 tagLibFacesConfigInfo.addTagLibUrl(tagLibUrl);
102 tagLibFacesConfigInfo.addFacesConfigUrl(facesConfigUrl);
104 statictTaglibFacesConfigLocationMap.put(taglibUri, tagLibFacesConfigInfo);
110 *Factory Method to get TagLibrarySupport for a particular taglibUri and ClassLoader
112 public static JsfTagSupport getInstance(
113 String taglibUri) throws JsfTagSupportException, SAXException, ParserConfigurationException, IOException {
114 synchronized (lock) {
115 if (!cachedTagLibraryInfoMap.containsKey(taglibUri)) {
116 cachedTagLibraryInfoMap.put(taglibUri, new JsfTagSupport(taglibUri));
120 return cachedTagLibraryInfoMap.get(taglibUri);
123 public Object getTagHandler(
124 ClassLoader classLoader, String tagName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
125 TagInfo tagInfo = tagInfoMap.get(tagName);
126 return classLoader.loadClass(tagInfo.getTagClass()).newInstance();
129 public Object getComponent(
130 ClassLoader classLoader, String tagName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
131 UIComponentTagBase componentTag = (UIComponentTagBase) getTagHandler(classLoader, tagName);
132 String componentType = componentTag.getComponentType();
133 ComponentInfo componentInfo = componentInfoMap.get(componentType);
134 String componentClass = componentInfo.getComponentClass();
135 return classLoader.loadClass(componentClass).newInstance();
138 public String getComponentClass(
139 ClassLoader classLoader, String tagName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
140 if(tagName.equals("view") || tagName.equals("subview") || tagName.equals("verbatim")) {
143 UIComponentTagBase componentTag = (UIComponentTagBase) getTagHandler(classLoader, tagName);
144 String componentType = componentTag.getComponentType();
145 ComponentInfo componentInfo = componentInfoMap.get(componentType);
146 return componentInfo.getComponentClass();
149 private JsfTagSupport(String taglibUri) throws JsfTagSupportException, SAXException, ParserConfigurationException, IOException {
150 TagLibFacesConfigInfo tagLibFacesConfigInfo = statictTaglibFacesConfigLocationMap.get(taglibUri);
152 if (tagLibFacesConfigInfo != null) {
153 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
154 factory.setValidating(false);
155 List<URL> tagLibUrlList = tagLibFacesConfigInfo.getTagLibUrls();
156 for (URL tagLibUrl : tagLibUrlList) {
157 // Create the builder and parse XML data from input stream
158 DocumentBuilder documentBuilder = factory.newDocumentBuilder();
159 documentBuilder.setEntityResolver(new EmptyEntityResolver());
160 Document tagLibdocument = documentBuilder.parse(tagLibUrl.openStream());
161 parseTagLibary(tagLibdocument);
164 List<URL> facesConfigUrlList = tagLibFacesConfigInfo.getFacesConfigUrls();
165 for (URL facesConfigUrl : facesConfigUrlList) {
166 // Create the builder and parse XML data from input stream
167 DocumentBuilder documentBuilder = factory.newDocumentBuilder();
168 documentBuilder.setEntityResolver(new EmptyEntityResolver());
169 Document facesConfigdocument = documentBuilder.parse(facesConfigUrl.openStream());
170 parseFacesConfig(facesConfigdocument);
173 throw new JsfTagSupportException(NbBundle.getMessage(JsfTagSupport.class, "UNRECOGNIZED_TAGLIB") + taglibUri);
177 private Map<String, ComponentInfo> parseFacesConfig(Document facesConfigdocument) {
178 NodeList componentNodes = facesConfigdocument.getElementsByTagName("component");
180 componentNodes.getLength(); i++) {
181 ComponentInfo componentInfo = new ComponentInfo(componentNodes.item(i));
182 componentInfoMap.put(componentInfo.getComponentType(), componentInfo);
185 return componentInfoMap;
188 private void parseTagLibary(Document tagLibdocument) {
189 NodeList tagNodes = tagLibdocument.getElementsByTagName("tag");
191 tagNodes.getLength(); i++) {
192 TagInfo tagInfo = new TagInfo(tagNodes.item(i));
193 tagInfoMap.put(tagInfo.getName(), tagInfo);
197 private static class TagLibFacesConfigInfo {
199 private String taglibUri;
200 private List<URL> tagLibUrls = new ArrayList<URL>(3);
201 private List<URL> facesConfigUrls = new ArrayList<URL>(3);
203 TagLibFacesConfigInfo(String taglibUri) {
204 this.taglibUri = taglibUri;
207 public void addTagLibUrl(URL taglib) {
208 tagLibUrls.add(taglib);
211 public List<URL> getTagLibUrls() {
215 public void addFacesConfigUrl(URL facesConfig) {
216 facesConfigUrls.add(facesConfig);
219 public List<URL> getFacesConfigUrls() {
220 return facesConfigUrls;
224 private static class TagInfo {
226 private String tagName;
227 private String tagClass;
229 TagInfo(Node tagNode) {
230 Node nameNode = ((Element) tagNode).getElementsByTagName("name").item(0);
231 tagName = nameNode.getTextContent().trim();
232 Node tagClassNode = ((Element) tagNode).getElementsByTagName("tag-class").item(0);
233 tagClass = tagClassNode.getTextContent().trim();
236 public String getName() {
240 public String getTagClass() {
245 private static class ComponentInfo {
247 private String componentType;
248 private String componentClass;
250 ComponentInfo(Node componentNode) {
251 Node componentTypeNode = ((Element) componentNode).getElementsByTagName("component-type").item(0);
252 componentType = componentTypeNode.getTextContent().trim();
253 Node componentClassNode = ((Element) componentNode).getElementsByTagName("component-class").item(0);
254 componentClass = componentClassNode.getTextContent().trim();
257 public String getComponentType() {
258 return componentType;
261 public String getComponentClass() {
262 return componentClass;
266 private static class EmptyEntityResolver implements EntityResolver {
267 public InputSource resolveEntity(String pubid, String sysid) {
268 return new InputSource(new ByteArrayInputStream(new byte[0]));