1 package net.sourceforge.pmd;
2
3 import net.sourceforge.pmd.util.ResourceLoader;
4 import org.xml.sax.Attributes;
5 import org.xml.sax.InputSource;
6 import org.xml.sax.SAXException;
7 import org.xml.sax.helpers.DefaultHandler;
8
9 import javax.xml.parsers.SAXParser;
10 import javax.xml.parsers.SAXParserFactory;
11 import java.io.InputStream;
12 import java.util.Enumeration;
13 import java.util.Iterator;
14 import java.util.Properties;
15 import java.util.Stack;
16 import java.util.StringTokenizer;
17
18 /***
19 * Loads the PMD <b>project.xml</b> file and stores the contents in a Properties object.
20 * The property keys are the case-insensitive path starting below the root <project> down
21 * to the element. For example:
22 * <ul>
23 * <li>currentVersion</li>
24 * <li>organization/name</li>
25 * <li>versions/version/name</li>
26 * </ul>
27 * When an element has repeated values, e.g., developer names, one property is created and
28 * the values are separated by <b>&vs;</b>. The <i>vs</i> stands for <i>value separator</i>.
29 * For example:
30 * <ul>
31 * <li>Tom Copeland&vs;David Dixon-Peugh&vs;David Craine</li>
32 * <li>tom@infoether.com&vs;ddp@apache.org&vs;dave@infoether.com</li>
33 * </ul>
34 * When there is a collection of repeating values, an empty space will reserve the position
35 * of a missing value. This is so that the collection can be parsed on position.
36 *
37 * @author Donald A. Leckie
38 * @since September 10, 2002
39 * @version $Revision: 1.12 $, $Date: 2003/04/08 16:02:10 $
40 */
41 public class ProjectFile {
42
43 private static Properties PROPERTIES;
44 private static Exception PARSE_EXCEPTION;
45 private static final String VALUE_SEPARATOR = "&vs;";
46
47 /***
48 *****************************************************************************
49 *
50 * @param key
51 *
52 * @return
53 */
54 public static final String getProperty(String key) {
55 key = (key == null) ? "" : key.trim().toLowerCase();
56
57 if (PROPERTIES == null) {
58 (new ProjectFile()).loadProperties();
59 }
60
61 String value = PROPERTIES.getProperty(key);
62
63 return (value == null) ? "" : value;
64 }
65
66 /***
67 *****************************************************************************
68 *
69 * @return
70 */
71 public static final Enumeration getPropertyKeys() {
72 return PROPERTIES.propertyNames();
73 }
74
75 /***
76 *****************************************************************************
77 *
78 * @return
79 */
80 public static final int getPropertyCount() {
81 int count = 0;
82 Enumeration keys = PROPERTIES.propertyNames();
83
84 while (keys.hasMoreElements()) {
85 keys.nextElement();
86 count++;
87 }
88
89 return count;
90 }
91
92 /***
93 *****************************************************************************
94 *
95 * @return
96 */
97 public static final String[] toArray(String propertyValue) {
98 String[] values = new String[0];
99
100 if (propertyValue != null) {
101 StringTokenizer parser;
102 int valueCount;
103 int index;
104
105 parser = new StringTokenizer(propertyValue, VALUE_SEPARATOR);
106 valueCount = parser.countTokens();
107 values = new String[valueCount];
108 index = 0;
109
110 while (parser.hasMoreTokens()) {
111 values[index] = parser.nextToken();
112 index++;
113 }
114 }
115
116 return values;
117 }
118
119 /***
120 *****************************************************************************
121 *
122 * @return
123 */
124 public static final Exception getException() {
125 return PARSE_EXCEPTION;
126 }
127
128 /***
129 *****************************************************************************
130 *
131 */
132 private void loadProperties() {
133 InputStream inputStream;
134 InputSource inputSource;
135
136 PROPERTIES = new Properties();
137
138 try {
139 inputStream = ResourceLoader.loadResourceAsStream("project.xml");
140 inputSource = new InputSource(inputStream);
141 MainContentHandler mainContentHandler;
142 SAXParserFactory factory = SAXParserFactory.newInstance();
143 factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
144 factory.setFeature("http://xml.org/sax/features/namespaces", false);
145
146 SAXParser parser = factory.newSAXParser();
147
148 mainContentHandler = new MainContentHandler();
149
150 parser.parse(inputSource, mainContentHandler);
151 } catch (Exception exception) {
152 PARSE_EXCEPTION = exception;
153 }
154 }
155
156 /***
157 *****************************************************************************
158 *****************************************************************************
159 *****************************************************************************
160 */
161 private class MainContentHandler extends DefaultHandler {
162
163 private StringBuffer m_buffer = new StringBuffer(100);
164 private Stack m_nameStack = new Stack();
165 private final String PROJECT = "project";
166
167 /***
168 *************************************************************************
169 */
170 private MainContentHandler() {
171 super();
172 }
173
174 /***
175 *************************************************************************
176 *
177 * @param namespace
178 * @param localName
179 * @param qualifiedName
180 * @param attributes
181 *
182 * @throws SAXException
183 */
184 public void startElement(String namespace, String localName, String qualifiedName, Attributes attributes) throws SAXException {
185 if (qualifiedName.equalsIgnoreCase(PROJECT) == false) {
186 m_nameStack.push(qualifiedName);
187 }
188 }
189
190 /***
191 *************************************************************************
192 *
193 * @param chars
194 * @param beginIndex
195 * @param length
196 *
197 * @throws PMDException
198 */
199 public void characters(char[] chars, int beginIndex, int length) {
200 m_buffer.append(chars, beginIndex, length);
201 }
202
203 /***
204 *************************************************************************
205 *
206 * @param namespace
207 * @param localName
208 * @param qualifiedName
209 *
210 * @throws SAXException
211 */
212 public void endElement(String namespace, String localName, String qualifiedName) throws SAXException {
213 String value = m_buffer.toString().replace('\n', ' ').trim();
214 String key = buildKey();
215 String existingValue = PROPERTIES.getProperty(key);
216
217 if (existingValue != null) {
218 value = existingValue + VALUE_SEPARATOR + value;
219 }
220
221 PROPERTIES.setProperty(key, value);
222 m_buffer.setLength(0);
223 m_nameStack.pop();
224 }
225
226 /***
227 *************************************************************************
228 *
229 * @return
230 */
231 private String buildKey() {
232 StringBuffer name = new StringBuffer(100);
233 Iterator iterator = m_nameStack.iterator();
234
235 while (iterator.hasNext()) {
236 name.append(iterator.next());
237 name.append('/');
238 }
239
240 if (name.length() > 0) {
241 name.setLength(name.length() - 1);
242 }
243
244 return name.toString().toLowerCase();
245 }
246 }
247 }
This page was automatically generated by Maven