Coverage Report - com.puppycrawl.tools.checkstyle.PackageNamesLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
PackageNamesLoader
74%
38/51
78%
11/14
3.625
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 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;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.Utils;
 22  
 
 23  
 import com.google.common.collect.Sets;
 24  
 import com.puppycrawl.tools.checkstyle.api.AbstractLoader;
 25  
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
 26  
 import com.puppycrawl.tools.checkstyle.api.FastStack;
 27  
 import java.io.BufferedInputStream;
 28  
 import java.io.IOException;
 29  
 import java.io.InputStream;
 30  
 import java.net.URL;
 31  
 import java.util.Enumeration;
 32  
 import java.util.Set;
 33  
 import javax.xml.parsers.ParserConfigurationException;
 34  
 import org.xml.sax.Attributes;
 35  
 import org.xml.sax.InputSource;
 36  
 import org.xml.sax.SAXException;
 37  
 
 38  
 /**
 39  
  * Loads a list of package names from a package name XML file.
 40  
  * @author Rick Giles
 41  
  * @version 4-Dec-2002
 42  
  */
 43  
 public final class PackageNamesLoader
 44  
     extends AbstractLoader
 45  
 {
 46  
     /** the public ID for the configuration dtd */
 47  
     private static final String DTD_PUBLIC_ID =
 48  
         "-//Puppy Crawl//DTD Package Names 1.0//EN";
 49  
 
 50  
     /** the resource for the configuration dtd */
 51  
     private static final String DTD_RESOURCE_NAME =
 52  
         "com/puppycrawl/tools/checkstyle/packages_1_0.dtd";
 53  
 
 54  
     /** Name of default checkstyle package names resource file.
 55  
      * The file must be in the classpath.
 56  
      */
 57  
     private static final String CHECKSTYLE_PACKAGES =
 58  
         "checkstyle_packages.xml";
 59  
 
 60  
     /** The temporary stack of package name parts */
 61  594
     private final FastStack<String> mPackageStack = FastStack.newInstance();
 62  
 
 63  
     /** The fully qualified package names. */
 64  594
     private final Set<String> mPackageNames = Sets.newLinkedHashSet();
 65  
 
 66  
     /**
 67  
      * Creates a new <code>PackageNamesLoader</code> instance.
 68  
      * @throws ParserConfigurationException if an error occurs
 69  
      * @throws SAXException if an error occurs
 70  
      */
 71  
     private PackageNamesLoader()
 72  
         throws ParserConfigurationException, SAXException
 73  
     {
 74  594
         super(DTD_PUBLIC_ID, DTD_RESOURCE_NAME);
 75  594
     }
 76  
 
 77  
     /**
 78  
      * Returns the set of fully qualified package names this
 79  
      * this loader processed.
 80  
      * @return the set of package names
 81  
      */
 82  
     private Set<String> getPackageNames()
 83  
     {
 84  594
         return mPackageNames;
 85  
     }
 86  
 
 87  
     @Override
 88  
     public void startElement(String aNamespaceURI,
 89  
                              String aLocalName,
 90  
                              String aQName,
 91  
                              Attributes aAtts)
 92  
         throws SAXException
 93  
     {
 94  11286
         if ("package".equals(aQName)) {
 95  
             //push package name
 96  10692
             final String name = aAtts.getValue("name");
 97  10692
             if (name == null) {
 98  0
                 throw new SAXException("missing package name");
 99  
             }
 100  10692
             mPackageStack.push(name);
 101  
         }
 102  11286
     }
 103  
 
 104  
     /**
 105  
      * Creates a full package name from the package names on the stack.
 106  
      * @return the full name of the current package.
 107  
      */
 108  
     private String getPackageName()
 109  
     {
 110  10692
         final StringBuffer buf = new StringBuffer();
 111  10692
         for (String subPackage : mPackageStack) {
 112  29700
             buf.append(subPackage);
 113  29700
             if (!subPackage.endsWith(".")) {
 114  29700
                 buf.append(".");
 115  
             }
 116  
         }
 117  10692
         return buf.toString();
 118  
     }
 119  
 
 120  
     @Override
 121  
     public void endElement(String aNamespaceURI,
 122  
                            String aLocalName,
 123  
                            String aQName)
 124  
     {
 125  11286
         if ("package".equals(aQName)) {
 126  
 
 127  10692
             mPackageNames.add(getPackageName());
 128  10692
             mPackageStack.pop();
 129  
         }
 130  11286
     }
 131  
 
 132  
     /**
 133  
      * Returns the set of package names, compiled from all
 134  
      * checkstyle_packages.xml files found on the given classloaders
 135  
      * classpath.
 136  
      * @param aClassLoader the class loader for loading the
 137  
      *          checkstyle_packages.xml files.
 138  
      * @return the set of package names.
 139  
      * @throws CheckstyleException if an error occurs.
 140  
      */
 141  
     public static Set<String> getPackageNames(ClassLoader aClassLoader)
 142  
         throws CheckstyleException
 143  
     {
 144  
 
 145  594
         Enumeration<URL> packageFiles = null;
 146  
         try {
 147  594
             packageFiles = aClassLoader.getResources(CHECKSTYLE_PACKAGES);
 148  
         }
 149  0
         catch (IOException e) {
 150  0
             throw new CheckstyleException(
 151  
                     "unable to get package file resources", e);
 152  594
         }
 153  
 
 154  
         //create the loader outside the loop to prevent PackageObjectFactory
 155  
         //being created anew for each file
 156  594
         final PackageNamesLoader namesLoader = newPackageNamesLoader();
 157  
 
 158  1188
         while ((null != packageFiles) && packageFiles.hasMoreElements()) {
 159  594
             final URL aPackageFile = packageFiles.nextElement();
 160  594
             InputStream stream = null;
 161  
 
 162  
             try {
 163  594
                 stream = new BufferedInputStream(aPackageFile.openStream());
 164  594
                 final InputSource source = new InputSource(stream);
 165  594
                 loadPackageNamesSource(source, "default package names",
 166  
                     namesLoader);
 167  
             }
 168  0
             catch (IOException e) {
 169  0
                 throw new CheckstyleException(
 170  
                         "unable to open " + aPackageFile, e);
 171  
             }
 172  
             finally {
 173  594
                 Utils.closeQuietly(stream);
 174  594
             }
 175  594
         }
 176  594
         return namesLoader.getPackageNames();
 177  
     }
 178  
 
 179  
     /**
 180  
      * Creates a PackageNamesLoader instance.
 181  
      * @return the PackageNamesLoader
 182  
      * @throws CheckstyleException if the creation failed
 183  
      */
 184  
     private static PackageNamesLoader newPackageNamesLoader()
 185  
         throws CheckstyleException
 186  
     {
 187  
         try {
 188  594
             return new PackageNamesLoader();
 189  
         }
 190  0
         catch (final ParserConfigurationException e) {
 191  0
             throw new CheckstyleException(
 192  
                     "unable to create PackageNamesLoader ", e);
 193  
         }
 194  0
         catch (final SAXException e) {
 195  0
             throw new CheckstyleException(
 196  
                     "unable to create PackageNamesLoader - "
 197  
                     + e.getMessage(), e);
 198  
         }
 199  
     }
 200  
 
 201  
     /**
 202  
      * Returns the list of package names in a specified source.
 203  
      * @param aSource the source for the list.
 204  
      * @param aSourceName the name of the source.
 205  
      * @param aNameLoader the PackageNamesLoader instance
 206  
      * @throws CheckstyleException if an error occurs.
 207  
      */
 208  
     private static void loadPackageNamesSource(
 209  
             InputSource aSource, String aSourceName,
 210  
             PackageNamesLoader aNameLoader)
 211  
         throws CheckstyleException
 212  
     {
 213  
         try {
 214  594
             aNameLoader.parseInputSource(aSource);
 215  
         }
 216  0
         catch (final SAXException e) {
 217  0
             throw new CheckstyleException("unable to parse "
 218  
                     + aSourceName + " - " + e.getMessage(), e);
 219  
         }
 220  0
         catch (final IOException e) {
 221  0
             throw new CheckstyleException("unable to read " + aSourceName, e);
 222  594
         }
 223  594
     }
 224  
 }