View Javadoc

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   * The configuration class for Johnson! :)
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             // Parse document
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             // If no container factory was specified then fall back to the old behaviour by default
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             // now cache the ignore paths in our mapper
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 }