1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.commons.resourcehandler.config;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URL;
24 import java.net.URLConnection;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.faces.FacesException;
29 import javax.faces.context.ExternalContext;
30 import javax.faces.context.FacesContext;
31 import javax.xml.parsers.ParserConfigurationException;
32 import javax.xml.parsers.SAXParser;
33 import javax.xml.parsers.SAXParserFactory;
34
35 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
36 import org.apache.myfaces.commons.resourcehandler.config.element.Library;
37 import org.apache.myfaces.commons.resourcehandler.config.element.MyFacesResourcesConfig;
38 import org.apache.myfaces.commons.util.ClassUtils;
39 import org.apache.myfaces.commons.util.WebConfigParamUtils;
40 import org.xml.sax.Attributes;
41 import org.xml.sax.InputSource;
42 import org.xml.sax.Locator;
43 import org.xml.sax.SAXException;
44 import org.xml.sax.SAXParseException;
45 import org.xml.sax.XMLReader;
46 import org.xml.sax.helpers.DefaultHandler;
47
48
49
50
51
52
53
54 public class MyFacesResourceHandlerConfigParser
55 {
56
57
58
59
60
61 @JSFWebConfigParam
62 public static final String INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER = "org.apache.myfaces.commons.EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER";
63 public static final String INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER_DEFAULT = DefaultMyFacesResourceHandlerUrlProvider.class.getName();
64
65 public MyFacesResourcesConfig parse(FacesContext facesContext)
66 {
67 String resourceHandlerUrlProviderClassName = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
68 INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER, INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER_DEFAULT);
69
70 MyFacesResourceHandlerUrlProvider urlProvider = (MyFacesResourceHandlerUrlProvider) ClassUtils.newInstance(resourceHandlerUrlProviderClassName);
71
72 List<URL> configUrls = new ArrayList<URL>();
73
74 try
75 {
76 configUrls.addAll(urlProvider.getMetaInfConfigurationResources(facesContext.getExternalContext()));
77 }
78 catch(IOException e)
79 {
80 throw new FacesException("Cannot get META-INF/myfaces-resources-config.xml urls", e);
81 }
82
83 try
84 {
85 URL webInfConfig = urlProvider.getWebInfConfigurationResource(facesContext.getExternalContext());
86 if (webInfConfig != null)
87 {
88 configUrls.add(webInfConfig);
89 }
90 }
91 catch(IOException e)
92 {
93 throw new FacesException(e);
94 }
95
96 List<MyFacesResourcesConfig> configList = new ArrayList<MyFacesResourcesConfig>();
97
98 for (URL url : configUrls)
99 {
100 try
101 {
102 MyFacesResourcesConfig mrc = parseFile(url);
103 if (mrc != null)
104 {
105 configList.add(mrc);
106 }
107 }
108 catch (IOException e) {
109 throw new FacesException("Cannot parse file "+url);
110 }
111 }
112
113 MyFacesResourcesConfig finalConfig = new MyFacesResourcesConfig();
114 for (MyFacesResourcesConfig cfg : configList)
115 {
116 finalConfig.merge(cfg);
117 }
118 return finalConfig;
119 }
120
121 private MyFacesResourcesConfig parseFile(URL configFileUrl) throws IOException
122 {
123 InputStream is = null;
124 URLConnection conn = null;
125 try
126 {
127 ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
128 boolean schemaValidating = false;
129
130
131 LibraryHandler handler = new LibraryHandler(configFileUrl);
132 SAXParser parser = createSAXParser(handler, externalContext, schemaValidating);
133 conn = configFileUrl.openConnection();
134 conn.setUseCaches(false);
135 is = conn.getInputStream();
136 parser.parse(is, handler);
137 return handler.getMyFacesResourcesConfig();
138 }
139 catch (SAXException e)
140 {
141 IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
142 ioe.initCause(e);
143 throw ioe;
144 }
145 catch (ParserConfigurationException e)
146 {
147 IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
148 ioe.initCause(e);
149 throw ioe;
150 }
151 finally
152 {
153 if (is != null)
154 is.close();
155 }
156 }
157
158 private static final SAXParser createSAXParser(LibraryHandler handler, ExternalContext externalContext, boolean schemaValidating) throws SAXException,
159 ParserConfigurationException
160 {
161 SAXParserFactory factory = SAXParserFactory.newInstance();
162
163
164 factory.setNamespaceAware(true);
165 factory.setFeature("http://xml.org/sax/features/validation", false);
166 factory.setValidating(false);
167
168 SAXParser parser = factory.newSAXParser();
169 XMLReader reader = parser.getXMLReader();
170 reader.setErrorHandler(handler);
171 reader.setEntityResolver(handler);
172 return parser;
173 }
174
175 private static class LibraryHandler extends DefaultHandler
176 {
177 private final URL source;
178
179 private final StringBuffer buffer;
180
181 private Locator locator;
182
183 private MyFacesResourcesConfig config;
184
185 private String libraryName;
186
187 private String redirectName;
188
189 private String requestPath;
190
191 public LibraryHandler(URL source)
192 {
193 this.source = source;
194 this.buffer = new StringBuffer(64);
195 this.config = null;
196 }
197
198 public MyFacesResourcesConfig getMyFacesResourcesConfig()
199 {
200 return this.config;
201 }
202
203 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
204 {
205 this.buffer.setLength(0);
206 if ("myfaces-resources-config".equals(qName))
207 {
208 this.config = new MyFacesResourcesConfig();
209 }
210 else if ("library".equals(qName))
211 {
212 this.libraryName = null;
213 this.redirectName = null;
214 this.requestPath = null;
215 }
216 }
217
218 public void endElement(String uri, String localName, String qName) throws SAXException
219 {
220 try
221 {
222 if (this.config == null)
223 {
224 return;
225 }
226
227 if ("library".equals(localName))
228 {
229 Library l = new Library();
230 l.setName(libraryName);
231 l.setRedirectName(redirectName);
232 l.setRequestPath(requestPath);
233 config.addLibrary(l);
234 }
235 else if ("library-name".equals(localName))
236 {
237 libraryName = captureBuffer();
238 }
239 else if ("redirect-name".equals(localName))
240 {
241 redirectName = captureBuffer();
242 }
243 else if ("request-path".equals(localName))
244 {
245 requestPath = captureBuffer();
246 }
247 }
248 catch (Exception e)
249 {
250 SAXException saxe = new SAXException("Error Handling [" + this.source + "@"
251 + this.locator.getLineNumber() + "," + this.locator.getColumnNumber() + "] <" + qName + ">");
252 saxe.initCause(e);
253 throw saxe;
254 }
255 }
256
257 public void characters(char[] ch, int start, int length) throws SAXException
258 {
259 this.buffer.append(ch, start, length);
260 }
261
262 private String captureBuffer() throws Exception
263 {
264 String s = this.buffer.toString().trim();
265 if (s.length() == 0)
266 {
267 throw new Exception("Value Cannot be Empty");
268 }
269 this.buffer.setLength(0);
270 return s;
271 }
272
273 public InputSource resolveEntity(String publicId, String systemId) throws SAXException
274 {
275 return null;
276 }
277
278 public void error(SAXParseException e) throws SAXException
279 {
280 SAXException saxe = new SAXException("Error Handling [" + this.source + "@" + e.getLineNumber() + ","
281 + e.getColumnNumber() + "]");
282 saxe.initCause(e);
283 throw saxe;
284 }
285
286 public void setDocumentLocator(Locator locator)
287 {
288 this.locator = locator;
289 }
290
291 public void fatalError(SAXParseException e) throws SAXException
292 {
293 throw e;
294 }
295
296 public void warning(SAXParseException e) throws SAXException
297 {
298 throw e;
299 }
300 }
301
302 }