View Javadoc

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