1 package com.atlassian.johnson.config;
2
3 import com.atlassian.johnson.event.*;
4 import com.atlassian.johnson.setup.ContainerFactory;
5 import com.atlassian.johnson.setup.DefaultContainerFactory;
6 import com.atlassian.johnson.setup.SetupConfig;
7 import com.atlassian.johnson.Initable;
8 import com.atlassian.seraph.util.PathMapper;
9 import com.opensymphony.util.ClassLoaderUtil;
10 import org.apache.log4j.Category;
11 import org.w3c.dom.Element;
12 import org.w3c.dom.Node;
13 import org.w3c.dom.NodeList;
14 import org.w3c.dom.Text;
15
16 import javax.xml.parsers.DocumentBuilderFactory;
17 import java.net.URL;
18 import java.util.*;
19
20
21
22
23 public class JohnsonConfig
24 {
25 private static final Category log = Category.getInstance(JohnsonConfig.class);
26 private static JohnsonConfig instance;
27
28 private static final String DEFAULT_CONFIGURATION_FILE = "johnson-config.xml";
29
30 private String configurationFile;
31 private SetupConfig setupConfig;
32 private ContainerFactory containerFactory;
33 private List eventChecks;
34 private List requestEventChecks;
35 private List applicationEventChecks;
36 private Map eventChecksById;
37 private Map params;
38 private String setupPath;
39 private String errorPath;
40 private PathMapper ignoreMapper;
41 private Map eventLevels;
42 private Map eventTypes;
43 private List ignorePaths;
44
45 synchronized public static JohnsonConfig getInstance()
46 {
47 if (instance == null)
48 {
49 try
50 {
51 instance = new JohnsonConfig(DEFAULT_CONFIGURATION_FILE);
52 }
53 catch (ConfigurationException e)
54 {
55 log.error("Could not configure JohnsonConfig instance: " + e, e);
56 }
57 }
58
59 return instance;
60 }
61
62 public JohnsonConfig(String configurationFile) throws ConfigurationException
63 {
64 this.configurationFile = configurationFile;
65 init();
66 }
67
68 public List getEventChecks()
69 {
70 return eventChecks;
71 }
72
73 public List getRequestEventChecks()
74 {
75 return requestEventChecks;
76 }
77
78 public List getApplicationEventChecks()
79 {
80 return applicationEventChecks;
81 }
82
83 public EventCheck getEventCheck(int id)
84 {
85 return (EventCheck) eventChecksById.get(id);
86 }
87
88 public Map getParams()
89 {
90 return params;
91 }
92
93 public SetupConfig getSetupConfig()
94 {
95 return setupConfig;
96 }
97
98 public ContainerFactory getContainerFactory()
99 {
100 return containerFactory;
101 }
102
103 public String getSetupPath()
104 {
105 return setupPath;
106 }
107
108 public String getErrorPath()
109 {
110 return errorPath;
111 }
112
113 public List getIgnorePaths()
114 {
115 return ignorePaths;
116 }
117
118 public boolean isIgnoredPath(String uri)
119 {
120 return ignoreMapper.get(uri) != null;
121 }
122
123 public EventLevel getEventLevel(String level)
124 {
125 return (EventLevel) eventLevels.get(level);
126 }
127
128 public EventType getEventType(String type)
129 {
130 return (EventType) eventTypes.get(type);
131 }
132
133 private void init() throws ConfigurationException
134 {
135 try
136 {
137 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
138 URL fileUrl = ClassLoaderUtil.getResource(configurationFile, this.getClass());
139
140 if (fileUrl == null)
141 throw new IllegalArgumentException("No such XML file:" + configurationFile);
142
143
144 org.w3c.dom.Document doc = factory.newDocumentBuilder().parse(fileUrl.toString());
145 Element rootEl = doc.getDocumentElement();
146
147 setupConfig = (SetupConfig) configureClass(rootEl, "setupconfig");
148 containerFactory = (ContainerFactory) configureClass(rootEl, "container-factory");
149
150 if (containerFactory == null)
151 {
152 containerFactory = new DefaultContainerFactory();
153 }
154 configureEventChecks(rootEl);
155 eventLevels = configureEventConstants(rootEl, "eventlevels", "eventlevel");
156 eventTypes = configureEventConstants(rootEl, "eventtypes", "eventtype");
157 params = configureParameters(rootEl);
158 setupPath = (String) configurePaths(rootEl, "setup").get(0);
159 errorPath = (String) configurePaths(rootEl, "error").get(0);
160 ignorePaths = configurePaths(rootEl, "ignore");
161
162
163 ignoreMapper = new PathMapper();
164 for (Iterator iterator = ignorePaths.iterator(); iterator.hasNext();)
165 {
166 String path = (String) iterator.next();
167 ignoreMapper.put(path, path);
168 }
169
170 }
171 catch (Exception e)
172 {
173 e.printStackTrace();
174 throw new ConfigurationException("Exception configuring: " + e);
175 }
176 }
177
178 private Map configureEventConstants(Element rootEl, String tagname, String childname)
179 {
180 NodeList nl = rootEl.getElementsByTagName(tagname);
181
182 if (nl != null && nl.getLength() > 0)
183 {
184 Element element = (Element) nl.item(0);
185 NodeList children = element.getElementsByTagName(childname);
186 Map result = new HashMap(children.getLength());
187
188 for (int i = 0; i < children.getLength(); i++)
189 {
190 Element child = (Element) children.item(i);
191 String key = child.getAttribute("key");
192 String description = getContainedText(child, "description");
193
194 if (childname.equals("eventlevel"))
195 {
196 result.put(key, new EventLevel(key, description));
197 }
198 else if (childname.equals("eventtype"))
199 {
200 result.put(key, new EventType(key, description));
201 }
202 }
203
204 return result;
205 }
206
207 return Collections.EMPTY_MAP;
208 }
209
210 private List configurePaths(Element rootEl, String tagname)
211 {
212 NodeList nl = rootEl.getElementsByTagName(tagname);
213
214 if (nl != null && nl.getLength() > 0)
215 {
216 Element element = (Element) nl.item(0);
217 NodeList children = element.getElementsByTagName("path");
218 List result = new ArrayList(children.getLength());
219
220 for (int i = 0; i < children.getLength(); i++)
221 {
222 Element child = (Element) children.item(i);
223 result.add(((Text) child.getFirstChild()).getData().trim());
224 }
225
226 return result;
227 }
228
229 return Collections.EMPTY_LIST;
230 }
231
232 private Map configureParameters(Element rootEl)
233 {
234 NodeList nl = rootEl.getElementsByTagName("parameters");
235
236 if (nl.getLength() > 0)
237 {
238 Element parametersEl = (Element) nl.item(0);
239 return getInitParameters(parametersEl);
240 }
241
242 return Collections.EMPTY_MAP;
243 }
244
245 private Initable configureClass(Element rootEl, String tagname) throws ConfigurationException
246 {
247 try
248 {
249 NodeList elementList = rootEl.getElementsByTagName(tagname);
250
251 for (int i = 0; i < elementList.getLength(); i++)
252 {
253 Element authEl = (Element) elementList.item(i);
254 String clazz = authEl.getAttribute("class");
255
256 Initable initable = (Initable) ClassLoaderUtil.loadClass(clazz, this.getClass()).newInstance();
257 Map params = getInitParameters(authEl);
258 initable.init(params);
259 return initable;
260 }
261 }
262 catch (Exception e)
263 {
264 throw new ConfigurationException("Could not create: " + tagname + ": ", e);
265 }
266
267 return null;
268 }
269
270
271 private void configureEventChecks(Element rootEl) throws ConfigurationException
272 {
273 NodeList nl = rootEl.getElementsByTagName("eventchecks");
274
275 if (nl != null && nl.getLength() > 0)
276 {
277 eventChecks = new LinkedList();
278 requestEventChecks = new LinkedList();
279 applicationEventChecks = new LinkedList();
280 eventChecksById = new HashMap();
281
282 Element eventChecksEl = (Element) nl.item(0);
283 NodeList eventCheckList = eventChecksEl.getElementsByTagName("eventcheck");
284
285 for (int i = 0; i < eventCheckList.getLength(); i++)
286 {
287 Element eventCheckEl = (Element) eventCheckList.item(i);
288 String eventCheckClazz = eventCheckEl.getAttribute("class");
289
290 if (eventCheckClazz == null || "".equals(eventCheckClazz))
291
292 throw new ConfigurationException("eventcheck element with bad class attribute");
293
294 Object o = null;
295 try
296 {
297 log.debug("Adding eventcheck of class: " + eventCheckClazz);
298 o = ClassLoaderUtil.loadClass(eventCheckClazz, this.getClass()).newInstance();
299 }
300 catch (Exception e)
301 {
302 log.error(e);
303 throw new ConfigurationException("Could not create eventcheck: " + eventCheckClazz + ". Exception: " + e);
304 }
305
306 EventCheck eventCheck = null;
307 if (o instanceof EventCheck)
308 {
309 eventCheck = (EventCheck) o;
310 eventChecks.add(eventCheck);
311 }
312 else
313 {
314 throw new ConfigurationException("Eventcheck " + eventCheckClazz + " does not implement EventCheck interface.");
315 }
316
317 Map params = getInitParameters(eventCheckEl);
318 eventCheck.init(params);
319
320 if (eventCheck instanceof RequestEventCheck)
321 {
322 requestEventChecks.add(eventCheck);
323 }
324
325 if (eventCheck instanceof ApplicationEventCheck)
326 {
327 applicationEventChecks.add(eventCheck);
328 }
329
330 String eventCheckId = eventCheckEl.getAttribute("id");
331 if (eventCheckId != null && !"".equals(eventCheckId))
332 {
333 try
334 {
335 Integer id = Integer.valueOf(eventCheckId);
336 if (!eventChecksById.containsKey(id))
337 {
338 eventChecksById.put(id, eventCheck);
339 }
340 else
341 {
342 throw new ConfigurationException("Duplicate eventcheck id '" + id + "'.");
343 }
344 }
345 catch (NumberFormatException e)
346 {
347 throw new ConfigurationException("Eventcheck id must be an integer.", e);
348 }
349 }
350 }
351 }
352 else
353 {
354 eventChecks = Collections.EMPTY_LIST;
355 requestEventChecks = Collections.EMPTY_LIST;
356 applicationEventChecks = Collections.EMPTY_LIST;
357 eventChecksById = Collections.EMPTY_MAP;
358 }
359 }
360
361 private Map getInitParameters(Element el)
362 {
363 Map params = new HashMap();
364
365 NodeList nl = el.getElementsByTagName("init-param");
366
367 for (int i = 0; i < nl.getLength(); i++)
368 {
369 Node initParam = nl.item(i);
370 String paramName = getContainedText(initParam, "param-name");
371 String paramValue = getContainedText(initParam, "param-value");
372 params.put(paramName, paramValue);
373 }
374
375 return params;
376 }
377
378 public static void setInstance(JohnsonConfig johnsonConfig)
379 {
380 instance = johnsonConfig;
381 }
382
383 private String getContainedText(Node parent, String childTagName)
384 {
385 try
386 {
387 Node tag = ((Element) parent).getElementsByTagName(childTagName).item(0);
388 return ((Text) tag.getFirstChild()).getData();
389 }
390 catch (Exception e)
391 {
392 return null;
393 }
394 }
395 }