001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.api; 020 021import com.google.common.collect.Maps; 022import java.io.IOException; 023import java.io.InputStream; 024import java.util.HashMap; 025import java.util.Map; 026import javax.xml.parsers.ParserConfigurationException; 027import javax.xml.parsers.SAXParserFactory; 028import org.xml.sax.InputSource; 029import org.xml.sax.SAXException; 030import org.xml.sax.SAXParseException; 031import org.xml.sax.XMLReader; 032import org.xml.sax.helpers.DefaultHandler; 033 034/** 035 * Contains the common implementation of a loader, for loading a configuration 036 * from an XML file. 037 * <p> 038 * The error handling policy can be described as being austere, dead set, 039 * disciplinary, dour, draconian, exacting, firm, forbidding, grim, hard, hard- 040 * boiled, harsh, harsh, in line, iron-fisted, no-nonsense, oppressive, 041 * persnickety, picky, prudish, punctilious, puritanical, rigid, rigorous, 042 * scrupulous, set, severe, square, stern, stickler, straight, strait-laced, 043 * stringent, stuffy, stuffy, tough, unpermissive, unsparing and uptight. 044 * </p> 045 * 046 * @author Oliver Burn 047 */ 048public abstract class AbstractLoader 049 extends DefaultHandler 050{ 051 /** maps public id to resolve to esource name for the DTD */ 052 private final Map<String, String> publicIdToResourceNameMap; 053 /** parser to read XML files **/ 054 private final XMLReader parser; 055 056 /** 057 * Creates a new instance. 058 * @param publicId the public ID for the DTD to resolve 059 * @param dtdResourceName the resource for the DTD 060 * @throws SAXException if an error occurs 061 * @throws ParserConfigurationException if an error occurs 062 */ 063 protected AbstractLoader(String publicId, String dtdResourceName) 064 throws SAXException, ParserConfigurationException 065 { 066 this(new HashMap<String, String>(1)); 067 publicIdToResourceNameMap.put(publicId, dtdResourceName); 068 } 069 070 /** 071 * Creates a new instance. 072 * @param publicIdToResourceNameMap maps public IDs to DTD resource names 073 * @throws SAXException if an error occurs 074 * @throws ParserConfigurationException if an error occurs 075 */ 076 protected AbstractLoader(Map<String, String> publicIdToResourceNameMap) 077 throws SAXException, ParserConfigurationException 078 { 079 this.publicIdToResourceNameMap = 080 Maps.newHashMap(publicIdToResourceNameMap); 081 final SAXParserFactory factory = SAXParserFactory.newInstance(); 082 factory.setValidating(true); 083 factory.setNamespaceAware(true); 084 parser = factory.newSAXParser().getXMLReader(); 085 parser.setContentHandler(this); 086 parser.setEntityResolver(this); 087 parser.setErrorHandler(this); 088 } 089 090 /** 091 * Parses the specified input source. 092 * @param inputSource the input source to parse. 093 * @throws IOException if an error occurs 094 * @throws SAXException in an error occurs 095 */ 096 public void parseInputSource(InputSource inputSource) 097 throws IOException, SAXException 098 { 099 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}