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