View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2015 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  package com.puppycrawl.tools.checkstyle.api;
20  
21  import com.google.common.collect.Maps;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.HashMap;
25  import java.util.Map;
26  import javax.xml.parsers.ParserConfigurationException;
27  import javax.xml.parsers.SAXParserFactory;
28  import org.xml.sax.InputSource;
29  import org.xml.sax.SAXException;
30  import org.xml.sax.SAXParseException;
31  import org.xml.sax.XMLReader;
32  import org.xml.sax.helpers.DefaultHandler;
33  
34  /**
35   * Contains the common implementation of a loader, for loading a configuration
36   * from an XML file.
37   * <p>
38   * The error handling policy can be described as being austere, dead set,
39   * disciplinary, dour, draconian, exacting, firm, forbidding, grim, hard, hard-
40   * boiled, harsh, harsh, in line, iron-fisted, no-nonsense, oppressive,
41   * persnickety, picky, prudish, punctilious, puritanical, rigid, rigorous,
42   * scrupulous, set, severe, square, stern, stickler, straight, strait-laced,
43   * stringent, stuffy, stuffy, tough, unpermissive, unsparing and uptight.
44   * </p>
45   *
46   * @author Oliver Burn
47   */
48  public abstract class AbstractLoader
49      extends DefaultHandler
50  {
51      /** maps public id to resolve to esource name for the DTD */
52      private final Map<String, String> publicIdToResourceNameMap;
53      /** parser to read XML files **/
54      private final XMLReader parser;
55  
56      /**
57       * Creates a new instance.
58       * @param publicId the public ID for the DTD to resolve
59       * @param dtdResourceName the resource for the DTD
60       * @throws SAXException if an error occurs
61       * @throws ParserConfigurationException if an error occurs
62       */
63      protected AbstractLoader(String publicId, String dtdResourceName)
64          throws SAXException, ParserConfigurationException
65      {
66          this(new HashMap<String, String>(1));
67          publicIdToResourceNameMap.put(publicId, dtdResourceName);
68      }
69  
70      /**
71       * Creates a new instance.
72       * @param publicIdToResourceNameMap maps public IDs to DTD resource names
73       * @throws SAXException if an error occurs
74       * @throws ParserConfigurationException if an error occurs
75       */
76      protected AbstractLoader(Map<String, String> publicIdToResourceNameMap)
77          throws SAXException, ParserConfigurationException
78      {
79          this.publicIdToResourceNameMap =
80              Maps.newHashMap(publicIdToResourceNameMap);
81          final SAXParserFactory factory = SAXParserFactory.newInstance();
82          factory.setValidating(true);
83          factory.setNamespaceAware(true);
84          parser = factory.newSAXParser().getXMLReader();
85          parser.setContentHandler(this);
86          parser.setEntityResolver(this);
87          parser.setErrorHandler(this);
88      }
89  
90      /**
91       * Parses the specified input source.
92       * @param inputSource the input source to parse.
93       * @throws IOException if an error occurs
94       * @throws SAXException in an error occurs
95       */
96      public void parseInputSource(InputSource inputSource)
97          throws IOException, SAXException
98      {
99          parser.parse(inputSource);
100     }
101 
102     @Override
103     public InputSource resolveEntity(String publicId, String systemId)
104         throws SAXException, IOException
105     {
106         if (publicIdToResourceNameMap.keySet().contains(publicId)) {
107             final String dtdResourceName =
108                     publicIdToResourceNameMap.get(publicId);
109             final ClassLoader loader =
110                 this.getClass().getClassLoader();
111             final InputStream dtdIS =
112                 loader.getResourceAsStream(dtdResourceName);
113             if (dtdIS == null) {
114                 throw new SAXException(
115                     "Unable to load internal dtd " + dtdResourceName);
116             }
117             return new InputSource(dtdIS);
118         }
119         return super.resolveEntity(publicId, systemId);
120     }
121 
122     @Override
123     public void warning(SAXParseException ex) throws SAXException
124     {
125         throw ex;
126     }
127 
128     @Override
129     public void error(SAXParseException ex) throws SAXException
130     {
131         throw ex;
132     }
133 
134     @Override
135     public void fatalError(SAXParseException ex) throws SAXException
136     {
137         throw ex;
138     }
139 }