001: ////////////////////////////////////////////////////////////////////////////////
002: // checkstyle: Checks Java source code for adherence to a set of rules.
003: // Copyright (C) 2001-2007 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: ////////////////////////////////////////////////////////////////////////////////
019: package com.puppycrawl.tools.checkstyle;
020:
021: import com.puppycrawl.tools.checkstyle.api.AbstractLoader;
022: import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
023: import java.io.FileInputStream;
024: import java.io.FileNotFoundException;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.util.Iterator;
028: import java.util.Stack;
029: import javax.xml.parsers.ParserConfigurationException;
030: import org.xml.sax.Attributes;
031: import org.xml.sax.InputSource;
032: import org.xml.sax.SAXException;
033:
034: /**
035: * Loads a list of package names from a package name XML file.
036: * @author Rick Giles
037: * @version 4-Dec-2002
038: */
039: public final class PackageNamesLoader extends AbstractLoader {
040: /** the public ID for the configuration dtd */
041: private static final String DTD_PUBLIC_ID = "-//Puppy Crawl//DTD Package Names 1.0//EN";
042:
043: /** the resource for the configuration dtd */
044: private static final String DTD_RESOURCE_NAME = "com/puppycrawl/tools/checkstyle/packages_1_0.dtd";
045:
046: /** Name of default checkstyle package names resource file.
047: * The file must be in the classpath.
048: */
049: private static final String DEFAULT_PACKAGES = "com/puppycrawl/tools/checkstyle/checkstyle_packages.xml";
050:
051: /**
052: * the factory to return in getModuleFactory(),
053: * configured during parsing
054: */
055: private final PackageObjectFactory mModuleFactory = new PackageObjectFactory();
056:
057: /** The loaded package names */
058: private final Stack mPackageStack = new Stack();
059:
060: /**
061: * Creates a new <code>PackageNamesLoader</code> instance.
062: * @throws ParserConfigurationException if an error occurs
063: * @throws SAXException if an error occurs
064: */
065: private PackageNamesLoader() throws ParserConfigurationException,
066: SAXException {
067: super (DTD_PUBLIC_ID, DTD_RESOURCE_NAME);
068: }
069:
070: /** {@inheritDoc} */
071: public void startElement(String aNamespaceURI, String aLocalName,
072: String aQName, Attributes aAtts) throws SAXException {
073: if (aQName.equals("package")) {
074: //push package name
075: final String name = aAtts.getValue("name");
076: if (name == null) {
077: throw new SAXException("missing package name");
078: }
079: mPackageStack.push(name);
080: }
081: }
082:
083: /**
084: * Creates a full package name from the package names on the stack.
085: * @return the full name of the current package.
086: */
087: private String getPackageName() {
088: final StringBuffer buf = new StringBuffer();
089: final Iterator it = mPackageStack.iterator();
090: while (it.hasNext()) {
091: final String subPackage = (String) it.next();
092: buf.append(subPackage);
093: if (!subPackage.endsWith(".")) {
094: buf.append(".");
095: }
096: }
097: return buf.toString();
098: }
099:
100: /**
101: * Returns the module factory that has just been configured.
102: * @return the module factory, never null
103: */
104: private ModuleFactory getModuleFactory() {
105: return mModuleFactory;
106: }
107:
108: /** {@inheritDoc} */
109: public void endElement(String aNamespaceURI, String aLocalName,
110: String aQName) {
111: if (aQName.equals("package")) {
112: mModuleFactory.addPackage(getPackageName());
113: mPackageStack.pop();
114: }
115: }
116:
117: /**
118: * Returns the default list of package names.
119: * @param aClassLoader the class loader that gets the
120: * default package names.
121: * @return the default list of package names.
122: * @throws CheckstyleException if an error occurs.
123: */
124: public static ModuleFactory loadModuleFactory(
125: ClassLoader aClassLoader) throws CheckstyleException {
126:
127: final InputStream stream = aClassLoader
128: .getResourceAsStream(DEFAULT_PACKAGES);
129: final InputSource source = new InputSource(stream);
130: return loadModuleFactory(source, "default package names");
131: }
132:
133: /**
134: * Returns the package names in a specified file.
135: * @param aFilename name of the package file.
136: * @return the list of package names stored in the
137: * package file.
138: * @throws CheckstyleException if an error occurs.
139: */
140: public static ModuleFactory loadModuleFactory(String aFilename)
141: throws CheckstyleException {
142: FileInputStream fis = null;
143: try {
144: fis = new FileInputStream(aFilename);
145: } catch (final FileNotFoundException e) {
146: throw new CheckstyleException(
147: "unable to find " + aFilename, e);
148: }
149: final InputSource source = new InputSource(fis);
150: return loadModuleFactory(source, aFilename);
151: }
152:
153: /**
154: * Returns the list of package names in a specified source.
155: * @param aSource the source for the list.
156: * @param aSourceName the name of the source.
157: * @return the list ofpackage names stored in aSource.
158: * @throws CheckstyleException if an error occurs.
159: */
160: private static ModuleFactory loadModuleFactory(InputSource aSource,
161: String aSourceName) throws CheckstyleException {
162: try {
163: final PackageNamesLoader nameLoader = new PackageNamesLoader();
164: nameLoader.parseInputSource(aSource);
165: return nameLoader.getModuleFactory();
166: } catch (final FileNotFoundException e) {
167: throw new CheckstyleException("unable to find "
168: + aSourceName, e);
169: } catch (final ParserConfigurationException e) {
170: throw new CheckstyleException("unable to parse "
171: + aSourceName, e);
172: } catch (final SAXException e) {
173: throw new CheckstyleException("unable to parse "
174: + aSourceName + " - " + e.getMessage(), e);
175: } catch (final IOException e) {
176: throw new CheckstyleException("unable to read "
177: + aSourceName, e);
178: }
179: }
180: }
|