1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.config;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.Reader;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import javax.faces.context.ExternalContext;
30 import javax.xml.XMLConstants;
31 import javax.xml.parsers.ParserConfigurationException;
32 import javax.xml.parsers.SAXParser;
33 import javax.xml.parsers.SAXParserFactory;
34 import javax.xml.transform.Source;
35 import javax.xml.transform.stream.StreamSource;
36 import javax.xml.validation.Schema;
37 import javax.xml.validation.SchemaFactory;
38 import javax.xml.validation.Validator;
39
40 import org.apache.myfaces.shared.util.ClassUtils;
41 import org.w3c.dom.ls.LSInput;
42 import org.w3c.dom.ls.LSResourceResolver;
43 import org.xml.sax.Attributes;
44 import org.xml.sax.ErrorHandler;
45 import org.xml.sax.SAXException;
46 import org.xml.sax.SAXParseException;
47 import org.xml.sax.helpers.DefaultHandler;
48
49 public class ConfigFilesXmlValidationUtils
50 {
51 public final static LSResourceResolver JAVAEE_5_LS_RESOURCE_RESOLVER = new ValidatorLSResourceResolver();
52 public final static ErrorHandler VALIDATION_ERROR_HANDLER = new ValidationErrorHandler();
53
54 private final static String FACES_CONFIG_SCHEMA_PATH_12 = "org/apache/myfaces/resource/web-facesconfig_1_2.xsd";
55 private final static String FACES_CONFIG_SCHEMA_PATH_20 = "org/apache/myfaces/resource/web-facesconfig_2_0.xsd";
56 private final static String FACES_TAGLIB_SCHEMA_PATH = "org/apache/myfaces/resource/web-facelettaglibrary_2_0.xsd";
57
58 public static class LSInputImpl implements LSInput
59 {
60 private final String _publicId;
61 private final String _systemId;
62 private final String _baseURI;
63 private final InputStream _input;
64
65 public LSInputImpl(String publicId,
66 String systemId, String baseURI, InputStream input)
67 {
68 super();
69 _publicId = publicId;
70 _systemId = systemId;
71 _baseURI = baseURI;
72 _input = input;
73 }
74
75 public String getBaseURI()
76 {
77 return _baseURI;
78 }
79
80 public InputStream getByteStream()
81 {
82 return _input;
83 }
84
85 public boolean getCertifiedText()
86 {
87 return false;
88 }
89
90 public Reader getCharacterStream()
91 {
92 return null;
93 }
94
95 public String getEncoding()
96 {
97 return null;
98 }
99
100 public String getPublicId()
101 {
102 return _publicId;
103 }
104
105 public String getStringData()
106 {
107 return null;
108 }
109
110 public String getSystemId()
111 {
112 return _systemId;
113 }
114
115 public void setBaseURI(String baseURI)
116 {
117 }
118
119 public void setByteStream(InputStream byteStream)
120 {
121 }
122
123 public void setCertifiedText(boolean certifiedText)
124 {
125 }
126
127 public void setCharacterStream(Reader characterStream)
128 {
129 }
130
131 public void setEncoding(String encoding)
132 {
133 }
134
135 public void setPublicId(String publicId)
136 {
137 }
138
139 public void setStringData(String stringData)
140 {
141 }
142
143 public void setSystemId(String systemId)
144 {
145 }
146 }
147
148 public static class ValidatorLSResourceResolver implements LSResourceResolver
149 {
150
151 public LSInput resolveResource(String type, String namespaceURI,
152 String publicId, String systemId, String baseURI)
153 {
154 if ("http://www.w3.org/TR/REC-xml".equals(type) && "datatypes.dtd".equals(systemId))
155 {
156 return new LSInputImpl(publicId, systemId, baseURI, ClassUtils.getResourceAsStream("org/apache/myfaces/resource/datatypes.dtd"));
157 }
158 if ("-//W3C//DTD XMLSCHEMA 200102//EN".equals(publicId) && "XMLSchema.dtd".equals(systemId))
159 {
160 return new LSInputImpl(publicId, systemId, baseURI, ClassUtils.getResourceAsStream("org/apache/myfaces/resource/XMLSchema.dtd"));
161 }
162 if ("http://java.sun.com/xml/ns/javaee".equals(namespaceURI))
163 {
164 if ("javaee_5.xsd".equals(systemId))
165 {
166 return new LSInputImpl(publicId, systemId, baseURI, ClassUtils.getResourceAsStream("org/apache/myfaces/resource/javaee_5.xsd"));
167 }
168 else if ("javaee_web_services_client_1_2.xsd".equals(systemId))
169 {
170 return new LSInputImpl(publicId, systemId, baseURI, ClassUtils.getResourceAsStream("org/apache/myfaces/resource/javaee_web_services_client_1_2.xsd"));
171 }
172 }
173 if ("http://www.w3.org/XML/1998/namespace".equals(namespaceURI))
174 {
175 return new LSInputImpl(publicId, systemId, baseURI, ClassUtils.getResourceAsStream("org/apache/myfaces/resource/xml.xsd"));
176 }
177 return null;
178 }
179
180 }
181
182 public static class ValidationErrorHandler implements ErrorHandler
183 {
184 public void fatalError(SAXParseException exception) throws SAXException
185 {
186 throw exception;
187 }
188
189 public void error(SAXParseException exception) throws SAXException
190 {
191 Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
192 log.log(Level.SEVERE, exception.getMessage(), exception);
193 }
194
195 public void warning(SAXParseException exception) throws SAXException
196 {
197 Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
198 log.log(Level.WARNING, exception.getMessage(), exception);
199 }
200 }
201
202 public static void validateFacesConfigFile(URL xmlFile,
203 ExternalContext externalContext, String version) throws SAXException, IOException
204 {
205 SchemaFactory schemaFactory = SchemaFactory
206 .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
207
208 Source schemaFile = getFacesConfigSchemaFileAsSource(externalContext, version);
209 if (schemaFile == null)
210 {
211 throw new IOException("Could not find schema file for validation.");
212 }
213
214 schemaFactory.setResourceResolver(JAVAEE_5_LS_RESOURCE_RESOLVER);
215 Schema schema = schemaFactory.newSchema(schemaFile);
216
217 Validator validator = schema.newValidator();
218 URLConnection conn = xmlFile.openConnection();
219 conn.setUseCaches(false);
220 InputStream is = conn.getInputStream();
221 Source source = new StreamSource(is);
222 validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
223 validator.validate(source);
224 }
225
226 private static Source getFacesConfigSchemaFileAsSource(ExternalContext externalContext, String version)
227 {
228 String xmlSchema = "1.2".equals(version) ? FACES_CONFIG_SCHEMA_PATH_12 : FACES_CONFIG_SCHEMA_PATH_20;
229
230 InputStream stream = ClassUtils.getResourceAsStream(xmlSchema);
231
232 if (stream == null)
233 {
234 stream = externalContext.getResourceAsStream(xmlSchema);
235 }
236
237 if (stream == null) {
238 return null;
239 }
240
241 return new StreamSource(stream);
242 }
243
244 public static final String getFacesConfigVersion(URL url)
245 {
246 URLConnection conn = null;
247 InputStream input = null;
248 String result = "2.0";
249
250 try
251 {
252 SAXParserFactory factory = SAXParserFactory.newInstance();
253 SAXParser parser;
254 FacesConfigVersionCheckHandler handler = new FacesConfigVersionCheckHandler();
255
256
257
258
259 factory.setNamespaceAware(false);
260 factory.setFeature("http://xml.org/sax/features/validation", false);
261 factory.setValidating(false);
262
263 parser = factory.newSAXParser();
264
265 conn = url.openConnection();
266 conn.setUseCaches(false);
267 input = conn.getInputStream();
268
269 try
270 {
271 parser.parse(input, handler);
272 }
273
274 catch (SAXException e)
275 {
276
277 }
278
279 result = handler.isVersion20OrLater() ? "2.0" : (handler
280 .isVersion12() ? "1.2" : "1.1");
281 }
282
283 catch (Throwable e)
284 {
285
286 }
287
288 finally
289 {
290 if (input != null)
291 {
292 try
293 {
294 input.close();
295 }
296
297 catch (Throwable e)
298 {
299 }
300 }
301 }
302
303 return result;
304 }
305
306 private static class FacesConfigVersionCheckHandler extends DefaultHandler
307 {
308 private boolean version12;
309 private boolean version20OrLater;
310
311 public boolean isVersion12()
312 {
313 return this.version12;
314 }
315
316 public boolean isVersion20OrLater()
317 {
318 return this.version20OrLater;
319 }
320
321 @Override
322 public void startElement(String uri, String localName, String name,
323 Attributes attributes) throws SAXException
324 {
325 if (name.equals("faces-config"))
326 {
327 int length = attributes.getLength();
328
329 for (int i = 0; i < length; i++)
330 {
331 String attrName = attributes.getLocalName(i);
332 attrName = (attrName != null) ? ((attrName.length() > 0) ? attrName
333 : attributes.getQName(i))
334 : attributes.getQName(i);
335 if (attrName.equals("version"))
336 {
337 if (attributes.getValue(i).equals("1.2"))
338 {
339 this.version12 = true;
340 this.version20OrLater = false;
341 }
342 else
343 {
344 this.version20OrLater = true;
345 this.version12 = false;
346 }
347 }
348 }
349 }
350 }
351 }
352
353 public static void validateFaceletTagLibFile(URL xmlFile, ExternalContext externalContext, String version)
354 throws SAXException, IOException, ParserConfigurationException
355 {
356 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
357
358 Source schemaFile = getFaceletSchemaFileAsSource(externalContext);
359 if (schemaFile == null)
360 {
361 throw new IOException("Could not find schema file for validation.");
362 }
363 schemaFactory.setResourceResolver(ConfigFilesXmlValidationUtils.JAVAEE_5_LS_RESOURCE_RESOLVER);
364 Schema schema = schemaFactory.newSchema(schemaFile);
365
366 Validator validator = schema.newValidator();
367 URLConnection conn = xmlFile.openConnection();
368 conn.setUseCaches(false);
369 InputStream is = conn.getInputStream();
370 Source source = new StreamSource(is);
371 validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
372 validator.validate(source);
373 }
374
375 private static Source getFaceletSchemaFileAsSource(ExternalContext externalContext)
376 {
377 InputStream stream = ClassUtils.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
378
379 if (stream == null)
380 {
381 stream = externalContext.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
382 }
383
384 if (stream == null) {
385 return null;
386 }
387
388 return new StreamSource(stream);
389 }
390
391 public static final String getFaceletTagLibVersion(URL url)
392 {
393 if (isTaglibDocument20OrLater(url))
394 {
395 return "2.0";
396 }
397 else
398 {
399 return "1.0";
400 }
401 }
402
403 private static final boolean isTaglibDocument20OrLater (URL url)
404 {
405 URLConnection conn = null;
406 InputStream input = null;
407 boolean result = false;
408
409 try
410 {
411 SAXParserFactory factory = SAXParserFactory.newInstance();
412 SAXParser parser;
413 VersionCheckHandler handler = new VersionCheckHandler();
414
415
416
417
418 factory.setNamespaceAware(false);
419 factory.setFeature("http://xml.org/sax/features/validation", false);
420 factory.setValidating(false);
421
422 parser = factory.newSAXParser();
423
424 conn = url.openConnection();
425 conn.setUseCaches(false);
426 input = conn.getInputStream();
427
428 try
429 {
430 parser.parse (input, handler);
431 }
432
433 catch (SAXException e)
434 {
435
436 }
437
438 result = handler.isVersion20OrLater();
439 }
440
441 catch (Throwable e)
442 {
443
444 }
445
446 finally
447 {
448 if (input != null)
449 {
450 try
451 {
452 input.close();
453 }
454
455 catch (Throwable e)
456 {
457 }
458 }
459 }
460
461 return result;
462 }
463
464
465
466
467
468
469
470 private static class VersionCheckHandler extends DefaultHandler
471 {
472 private boolean version20OrLater;
473
474 public boolean isVersion20OrLater ()
475 {
476 return this.version20OrLater;
477 }
478
479 @Override
480 public void startElement (String uri, String localName, String name, Attributes attributes) throws SAXException
481 {
482 if (name.equals ("facelet-taglib"))
483 {
484 int length = attributes.getLength();
485
486 for (int i = 0; i < length; i++)
487 {
488 String attrName = attributes.getLocalName(i);
489 attrName = (attrName != null) ? ( (attrName.length() > 0) ? attrName : attributes.getQName(i)) : attributes.getQName(i);
490 if (attrName.equals ("version"))
491 {
492
493
494
495 this.version20OrLater = true;
496 }
497 }
498
499
500
501
502
503
504 }
505 }
506 }
507 }