1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
40
41
42 public final class PackageNamesLoader
43 extends AbstractLoader
44 {
45
46 private static final String DTD_PUBLIC_ID =
47 "-//Puppy Crawl//DTD Package Names 1.0//EN";
48
49
50 private static final String DTD_RESOURCE_NAME =
51 "com/puppycrawl/tools/checkstyle/packages_1_0.dtd";
52
53
54
55
56 private static final String CHECKSTYLE_PACKAGES =
57 "checkstyle_packages.xml";
58
59
60 private final FastStack<String> packageStack = FastStack.newInstance();
61
62
63 private final Set<String> packageNames = Sets.newLinkedHashSet();
64
65
66
67
68
69
70 private PackageNamesLoader()
71 throws ParserConfigurationException, SAXException
72 {
73 super(DTD_PUBLIC_ID, DTD_RESOURCE_NAME);
74 }
75
76
77
78
79
80
81 private Set<String> getPackageNames()
82 {
83 return packageNames;
84 }
85
86 @Override
87 public void startElement(String namespaceURI,
88 String localName,
89 String qName,
90 Attributes atts)
91 throws SAXException
92 {
93 if ("package".equals(qName)) {
94
95 final String name = atts.getValue("name");
96 if (name == null) {
97 throw new SAXException("missing package name");
98 }
99 packageStack.push(name);
100 }
101 }
102
103
104
105
106
107 private String getPackageName()
108 {
109 final StringBuilder buf = new StringBuilder();
110 for (String subPackage : packageStack) {
111 buf.append(subPackage);
112 if (!subPackage.endsWith(".")) {
113 buf.append(".");
114 }
115 }
116 return buf.toString();
117 }
118
119 @Override
120 public void endElement(String namespaceURI,
121 String localName,
122 String qName)
123 {
124 if ("package".equals(qName)) {
125
126 packageNames.add(getPackageName());
127 packageStack.pop();
128 }
129 }
130
131
132
133
134
135
136
137
138
139
140 public static Set<String> getPackageNames(ClassLoader classLoader)
141 throws CheckstyleException
142 {
143
144 Enumeration<URL> packageFiles = null;
145 try {
146 packageFiles = classLoader.getResources(CHECKSTYLE_PACKAGES);
147 }
148 catch (IOException e) {
149 throw new CheckstyleException(
150 "unable to get package file resources", e);
151 }
152
153
154
155 final PackageNamesLoader namesLoader = newPackageNamesLoader();
156
157 while (null != packageFiles && packageFiles.hasMoreElements()) {
158 final URL packageFile = packageFiles.nextElement();
159 InputStream stream = null;
160
161 try {
162 stream = new BufferedInputStream(packageFile.openStream());
163 final InputSource source = new InputSource(stream);
164 loadPackageNamesSource(source, "default package names",
165 namesLoader);
166 }
167 catch (IOException e) {
168 throw new CheckstyleException(
169 "unable to open " + packageFile, e);
170 }
171 finally {
172 Utils.closeQuietly(stream);
173 }
174 }
175 return namesLoader.getPackageNames();
176 }
177
178
179
180
181
182
183 private static PackageNamesLoader newPackageNamesLoader()
184 throws CheckstyleException
185 {
186 try {
187 return new PackageNamesLoader();
188 }
189 catch (final ParserConfigurationException e) {
190 throw new CheckstyleException(
191 "unable to create PackageNamesLoader ", e);
192 }
193 catch (final SAXException e) {
194 throw new CheckstyleException(
195 "unable to create PackageNamesLoader - "
196 + e.getMessage(), e);
197 }
198 }
199
200
201
202
203
204
205
206
207 private static void loadPackageNamesSource(
208 InputSource source, String sourceName,
209 PackageNamesLoader nameLoader)
210 throws CheckstyleException
211 {
212 try {
213 nameLoader.parseInputSource(source);
214 }
215 catch (final SAXException e) {
216 throw new CheckstyleException("unable to parse "
217 + sourceName + " - " + e.getMessage(), e);
218 }
219 catch (final IOException e) {
220 throw new CheckstyleException("unable to read " + sourceName, e);
221 }
222 }
223 }