1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.tomcat.util.descriptor.tld;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.security.AccessController;
22
23 import org.apache.juli.logging.Log;
24 import org.apache.juli.logging.LogFactory;
25 import org.apache.tomcat.util.descriptor.Constants;
26 import org.apache.tomcat.util.descriptor.DigesterFactory;
27 import org.apache.tomcat.util.descriptor.XmlErrorHandler;
28 import org.apache.tomcat.util.digester.Digester;
29 import org.apache.tomcat.util.digester.RuleSet;
30 import org.apache.tomcat.util.security.PrivilegedGetTccl;
31 import org.apache.tomcat.util.security.PrivilegedSetTccl;
32 import org.xml.sax.InputSource;
33 import org.xml.sax.SAXException;
34
35 /**
36  * Parses a Tag Library Descriptor.
37  */

38 public class TldParser {
39     private final Log log = LogFactory.getLog(TldParser.class); // must not be static
40     private final Digester digester;
41
42     public TldParser(boolean namespaceAware, boolean validation,
43             boolean blockExternal) {
44         this(namespaceAware, validation, new TldRuleSet(), blockExternal);
45     }
46
47     public TldParser(boolean namespaceAware, boolean validation, RuleSet ruleSet,
48             boolean blockExternal) {
49         digester = DigesterFactory.newDigester(
50                 validation, namespaceAware, ruleSet, blockExternal);
51     }
52
53     public TaglibXml parse(TldResourcePath path) throws IOException, SAXException {
54         ClassLoader original;
55         if (Constants.IS_SECURITY_ENABLED) {
56             PrivilegedGetTccl pa = new PrivilegedGetTccl();
57             original = AccessController.doPrivileged(pa);
58         } else {
59             original = Thread.currentThread().getContextClassLoader();
60         }
61         try (InputStream is = path.openStream()) {
62             if (Constants.IS_SECURITY_ENABLED) {
63                 PrivilegedSetTccl pa = new PrivilegedSetTccl(TldParser.class.getClassLoader());
64                 AccessController.doPrivileged(pa);
65             } else {
66                 Thread.currentThread().setContextClassLoader(TldParser.class.getClassLoader());
67             }
68             XmlErrorHandler handler = new XmlErrorHandler();
69             digester.setErrorHandler(handler);
70
71             TaglibXml taglibXml = new TaglibXml();
72             digester.push(taglibXml);
73
74             InputSource source = new InputSource(path.toExternalForm());
75             source.setByteStream(is);
76             digester.parse(source);
77             if (!handler.getWarnings().isEmpty() || !handler.getErrors().isEmpty()) {
78                 handler.logFindings(log, source.getSystemId());
79                 if (!handler.getErrors().isEmpty()) {
80                     // throw the first to indicate there was an error during processing
81                     throw handler.getErrors().iterator().next();
82                 }
83             }
84             return taglibXml;
85         } finally {
86             digester.reset();
87             if (Constants.IS_SECURITY_ENABLED) {
88                 PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
89                 AccessController.doPrivileged(pa);
90             } else {
91                 Thread.currentThread().setContextClassLoader(original);
92             }
93         }
94     }
95
96     public void setClassLoader(ClassLoader classLoader) {
97         digester.setClassLoader(classLoader);
98     }
99 }
100