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 }