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_0.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 else if ("javaee_web_services_client_1_2.xsd".equals(systemId))
173 {
174 return new LSInputImpl(publicId, systemId, baseURI,
175 ClassUtils.getResourceAsStream(
176 "org/apache/myfaces/resource/javaee_web_services_client_1_2.xsd"));
177 }
178 }
179 if ("http://www.w3.org/XML/1998/namespace".equals(namespaceURI))
180 {
181 return new LSInputImpl(publicId, systemId, baseURI,
182 ClassUtils.getResourceAsStream("org/apache/myfaces/resource/xml.xsd"));
183 }
184 return null;
185 }
186
187 }
188
189 public static class ValidationErrorHandler implements ErrorHandler
190 {
191 public void fatalError(SAXParseException exception) throws SAXException
192 {
193 throw exception;
194 }
195
196 public void error(SAXParseException exception) throws SAXException
197 {
198 Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
199 log.log(Level.SEVERE, exception.getMessage(), exception);
200 }
201
202 public void warning(SAXParseException exception) throws SAXException
203 {
204 Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
205 log.log(Level.WARNING, exception.getMessage(), exception);
206 }
207 }
208
209 public static void validateFacesConfigFile(URL xmlFile,
210 ExternalContext externalContext, String version) throws SAXException, IOException
211 {
212 SchemaFactory schemaFactory = SchemaFactory
213 .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
214
215 Source schemaFile = getFacesConfigSchemaFileAsSource(externalContext, version);
216 if (schemaFile == null)
217 {
218 throw new IOException("Could not find schema file for validation.");
219 }
220
221 schemaFactory.setResourceResolver(JAVAEE_5_LS_RESOURCE_RESOLVER);
222 Schema schema = schemaFactory.newSchema(schemaFile);
223
224 Validator validator = schema.newValidator();
225 URLConnection conn = xmlFile.openConnection();
226 conn.setUseCaches(false);
227 InputStream is = conn.getInputStream();
228 Source source = new StreamSource(is);
229 validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
230 validator.validate(source);
231 }
232
233 private static Source getFacesConfigSchemaFileAsSource(ExternalContext externalContext, String version)
234 {
235 String xmlSchema = "1.2".equals(version)
236 ? FACES_CONFIG_SCHEMA_PATH_12
237 : ("2.0".equals(version) ? FACES_CONFIG_SCHEMA_PATH_20 : FACES_CONFIG_SCHEMA_PATH_21);
238
239 InputStream stream = ClassUtils.getResourceAsStream(xmlSchema);
240
241 if (stream == null)
242 {
243 stream = externalContext.getResourceAsStream(xmlSchema);
244 }
245
246 if (stream == null)
247 {
248 return null;
249 }
250
251 return new StreamSource(stream);
252 }
253
254 public static final String getFacesConfigVersion(URL url)
255 {
256 URLConnection conn = null;
257 InputStream input = null;
258 String result = "2.0";
259
260 try
261 {
262 SAXParserFactory factory = SAXParserFactory.newInstance();
263 SAXParser parser;
264 FacesConfigVersionCheckHandler handler = new FacesConfigVersionCheckHandler();
265
266
267
268
269 factory.setNamespaceAware(false);
270 factory.setFeature("http://xml.org/sax/features/validation", false);
271 factory.setValidating(false);
272
273 parser = factory.newSAXParser();
274
275 conn = url.openConnection();
276 conn.setUseCaches(false);
277 input = conn.getInputStream();
278
279 try
280 {
281 parser.parse(input, handler);
282 }
283
284 catch (SAXException e)
285 {
286
287 }
288
289 result = handler.isVersion21OrLater() ? "2.1" : (handler.isVersion20() ? "2.0" : (handler
290 .isVersion12() ? "1.2" : "1.1"));
291 }
292
293 catch (Throwable e)
294 {
295
296 }
297
298 finally
299 {
300 if (input != null)
301 {
302 try
303 {
304 input.close();
305 }
306
307 catch (Throwable e)
308 {
309 }
310 }
311 }
312
313 return result;
314 }
315
316 private static class FacesConfigVersionCheckHandler extends DefaultHandler
317 {
318 private boolean version12;
319 private boolean version20;
320 private boolean version21OrLater;
321
322 public boolean isVersion12()
323 {
324 return this.version12;
325 }
326
327 public boolean isVersion20()
328 {
329 return this.version20 || this.version21OrLater;
330 }
331
332 public boolean isVersion21OrLater()
333 {
334 return version21OrLater;
335 }
336
337 @Override
338 public void startElement(String uri, String localName, String name,
339 Attributes attributes) throws SAXException
340 {
341 if (name.equals("faces-config"))
342 {
343 int length = attributes.getLength();
344
345 for (int i = 0; i < length; i++)
346 {
347 String attrName = attributes.getLocalName(i);
348 attrName = (attrName != null) ? ((attrName.length() > 0) ? attrName
349 : attributes.getQName(i))
350 : attributes.getQName(i);
351 if (attrName.equals("version"))
352 {
353 if (attributes.getValue(i).equals("1.2"))
354 {
355 this.version12 = true;
356 this.version20 = false;
357 this.version21OrLater = false;
358 }
359 else if (attributes.getValue(i).equals("2.0"))
360 {
361 this.version21OrLater = false;
362 this.version20 = true;
363 this.version12 = false;
364 }
365 else
366 {
367 this.version21OrLater = true;
368 this.version20 = false;
369 this.version12 = false;
370 }
371 }
372 }
373 }
374 }
375 }
376
377 public static void validateFaceletTagLibFile(URL xmlFile, ExternalContext externalContext, String version)
378 throws SAXException, IOException, ParserConfigurationException
379 {
380 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
381
382 Source schemaFile = getFaceletSchemaFileAsSource(externalContext);
383 if (schemaFile == null)
384 {
385 throw new IOException("Could not find schema file for validation.");
386 }
387 schemaFactory.setResourceResolver(ConfigFilesXmlValidationUtils.JAVAEE_5_LS_RESOURCE_RESOLVER);
388 Schema schema = schemaFactory.newSchema(schemaFile);
389
390 Validator validator = schema.newValidator();
391 URLConnection conn = xmlFile.openConnection();
392 conn.setUseCaches(false);
393 InputStream is = conn.getInputStream();
394 Source source = new StreamSource(is);
395 validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
396 validator.validate(source);
397 }
398
399 private static Source getFaceletSchemaFileAsSource(ExternalContext externalContext)
400 {
401 InputStream stream = ClassUtils.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
402
403 if (stream == null)
404 {
405 stream = externalContext.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
406 }
407
408 if (stream == null)
409 {
410 return null;
411 }
412
413 return new StreamSource(stream);
414 }
415
416 public static final String getFaceletTagLibVersion(URL url)
417 {
418 if (isTaglibDocument20OrLater(url))
419 {
420 return "2.0";
421 }
422 else
423 {
424 return "1.0";
425 }
426 }
427
428 private static final boolean isTaglibDocument20OrLater (URL url)
429 {
430 URLConnection conn = null;
431 InputStream input = null;
432 boolean result = false;
433
434 try
435 {
436 SAXParserFactory factory = SAXParserFactory.newInstance();
437 SAXParser parser;
438 VersionCheckHandler handler = new VersionCheckHandler();
439
440
441
442
443 factory.setNamespaceAware(false);
444 factory.setFeature("http://xml.org/sax/features/validation", false);
445 factory.setValidating(false);
446
447 parser = factory.newSAXParser();
448
449 conn = url.openConnection();
450 conn.setUseCaches(false);
451 input = conn.getInputStream();
452
453 try
454 {
455 parser.parse (input, handler);
456 }
457
458 catch (SAXException e)
459 {
460
461 }
462
463 result = handler.isVersion20OrLater();
464 }
465
466 catch (Throwable e)
467 {
468
469 }
470
471 finally
472 {
473 if (input != null)
474 {
475 try
476 {
477 input.close();
478 }
479
480 catch (Throwable e)
481 {
482 }
483 }
484 }
485
486 return result;
487 }
488
489
490
491
492
493
494
495 private static class VersionCheckHandler extends DefaultHandler
496 {
497 private boolean version20OrLater;
498
499 public boolean isVersion20OrLater ()
500 {
501 return this.version20OrLater;
502 }
503
504 @Override
505 public void startElement (String uri, String localName, String name, Attributes attributes) throws SAXException
506 {
507 if (name.equals ("facelet-taglib"))
508 {
509 int length = attributes.getLength();
510
511 for (int i = 0; i < length; i++)
512 {
513 String attrName = attributes.getLocalName(i);
514 attrName = (attrName != null)
515 ? ( (attrName.length() > 0) ? attrName : attributes.getQName(i))
516 : attributes.getQName(i);
517 if (attrName.equals ("version"))
518 {
519
520
521
522 this.version20OrLater = true;
523 }
524 }
525
526
527
528
529
530
531 }
532 }
533 }
534 }