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