1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import java.io.BufferedInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.net.URL;
26  import java.util.ArrayDeque;
27  import java.util.Collections;
28  import java.util.Deque;
29  import java.util.Enumeration;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.LinkedHashSet;
33  import java.util.Map;
34  import java.util.Set;
35  
36  import javax.xml.parsers.ParserConfigurationException;
37  
38  import org.xml.sax.Attributes;
39  import org.xml.sax.InputSource;
40  import org.xml.sax.SAXException;
41  
42  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
43  
44  
45  
46  
47  public final class PackageNamesLoader
48      extends XmlLoader {
49  
50      
51      private static final String DTD_PUBLIC_ID =
52          "-//Puppy Crawl//DTD Package Names 1.0//EN";
53  
54      
55      private static final String DTD_PUBLIC_CS_ID =
56          "-//Checkstyle//DTD Package Names Configuration 1.0//EN";
57  
58      
59      private static final String DTD_RESOURCE_NAME =
60          "com/puppycrawl/tools/checkstyle/packages_1_0.dtd";
61  
62      
63  
64  
65  
66      private static final String CHECKSTYLE_PACKAGES =
67          "checkstyle_packages.xml";
68  
69      
70      private static final String PACKAGE_ELEMENT_NAME = "package";
71  
72      
73      private final Deque<String> packageStack = new ArrayDeque<>();
74  
75      
76      private final Set<String> packageNames = new LinkedHashSet<>();
77  
78      
79  
80  
81  
82  
83  
84      private PackageNamesLoader()
85              throws ParserConfigurationException, SAXException {
86          super(createIdToResourceNameMap());
87      }
88  
89      @Override
90      public void startElement(String uri,
91                               String localName,
92                               String qName,
93                               Attributes attributes) {
94          if (PACKAGE_ELEMENT_NAME.equals(qName)) {
95              
96              final String name = attributes.getValue("name");
97              packageStack.push(name);
98          }
99      }
100 
101     
102 
103 
104 
105 
106     private String getPackageName() {
107         final StringBuilder buf = new StringBuilder(256);
108         final Iterator<String> iterator = packageStack.descendingIterator();
109         while (iterator.hasNext()) {
110             final String subPackage = iterator.next();
111             buf.append(subPackage);
112             if (!subPackage.endsWith(".") && iterator.hasNext()) {
113                 buf.append('.');
114             }
115         }
116         return buf.toString();
117     }
118 
119     @Override
120     public void endElement(String uri,
121                            String localName,
122                            String qName) {
123         if (PACKAGE_ELEMENT_NAME.equals(qName)) {
124             packageNames.add(getPackageName());
125             packageStack.pop();
126         }
127     }
128 
129     
130 
131 
132 
133 
134 
135 
136 
137 
138 
139     public static Set<String> getPackageNames(ClassLoader classLoader)
140             throws CheckstyleException {
141         final Set<String> result;
142         try {
143             
144             
145             final PackageNamesLoader namesLoader = new PackageNamesLoader();
146 
147             final Enumeration<URL> packageFiles = classLoader.getResources(CHECKSTYLE_PACKAGES);
148 
149             while (packageFiles.hasMoreElements()) {
150                 processFile(packageFiles.nextElement(), namesLoader);
151             }
152 
153             result = namesLoader.packageNames;
154         }
155         catch (IOException exc) {
156             throw new CheckstyleException("unable to get package file resources", exc);
157         }
158         catch (ParserConfigurationException | SAXException exc) {
159             throw new CheckstyleException("unable to open one of package files", exc);
160         }
161 
162         return Collections.unmodifiableSet(result);
163     }
164 
165     
166 
167 
168 
169 
170 
171 
172 
173     private static void processFile(URL packageFile, PackageNamesLoader namesLoader)
174             throws SAXException, CheckstyleException {
175         try (InputStream stream = new BufferedInputStream(packageFile.openStream())) {
176             final InputSource source = new InputSource(stream);
177             namesLoader.parseInputSource(source);
178         }
179         catch (IOException exc) {
180             throw new CheckstyleException("unable to open " + packageFile, exc);
181         }
182     }
183 
184     
185 
186 
187 
188 
189     private static Map<String, String> createIdToResourceNameMap() {
190         final Map<String, String> map = new HashMap<>();
191         map.put(DTD_PUBLIC_ID, DTD_RESOURCE_NAME);
192         map.put(DTD_PUBLIC_CS_ID, DTD_RESOURCE_NAME);
193         return map;
194     }
195 
196 }