View Javadoc

1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.jsieve;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.HashMap;
24  import java.util.Map;
25  import org.apache.commons.digester.Digester;
26  import org.apache.commons.logging.Log;
27  import org.xml.sax.SAXException;
28  /***
29   * <p>
30   * Singleton class <code>ConfigurationManager</code> parses the XML
31   * statements in the Sieve configuration file and translates them to Java
32   * objects.
33   * </p>
34   * 
35   * <p>
36   * The Sieve configuration file is named <code>sieveConfig.xml</code>. It is
37   * located by searching the classpath of the current ClassLoader.
38   * </p>
39   */
40  public class ConfigurationManager
41  {
42      /***
43       * The sole instance of the receiver.
44       */
45      static private ConfigurationManager fieldInstance;
46      /***
47       * The Digester used to process the Sieve configuration XML.
48       */
49      private Digester fieldDigester;
50      /***
51       * A Map of the Command names and their associated class names.
52       */
53      private Map fieldCommandMap;
54      /***
55       * A Map of the Test names and their associated class names.
56       */
57      private Map fieldTestMap;
58      /***
59       * A Map of the Comparator names and their associated class names.
60       */
61      private Map fieldComparatorMap;
62      /***
63       * Constructor for ConfigurationManager.
64       * 
65       * @throws SieveConfigurationException
66       */
67      private ConfigurationManager() throws SieveConfigurationException
68      {
69          super();
70          Log log = Logger.getLog();
71          try
72          {
73              parse();
74          } catch (SAXException e)
75          {
76              if (log.isErrorEnabled())
77                  log.error("Exception processing Configuration: ", e);
78              throw new SieveConfigurationException(e);
79          } catch (IOException e)
80          {
81              if (log.isErrorEnabled())
82                  log.error("Exception processing Configuration: ", e);
83              throw new SieveConfigurationException(e);
84          }
85      }
86      /***
87       * Returns the sole instance of the receiver, lazily initialised if
88       * required.
89       * 
90       * @return ConfigurationManager
91       */
92      static public synchronized ConfigurationManager getInstance()
93              throws SieveConfigurationException
94      {
95          ConfigurationManager instance = null;
96          if (null == (instance = getInstanceBasic()))
97          {
98              updateInstance();
99              return getInstance();
100         }
101         return instance;
102     }
103     /***
104      * Returns the sole instance of the receiver.
105      * 
106      * @return ConfigurationManager
107      */
108     static private ConfigurationManager getInstanceBasic()
109     {
110         return fieldInstance;
111     }
112     /***
113      * Returns a new instance of the receiver.
114      * 
115      * @return ConfigurationManager
116      */
117     static protected ConfigurationManager computeInstance()
118             throws SieveConfigurationException
119     {
120         return new ConfigurationManager();
121     }
122     /***
123      * Sets the instance.
124      * 
125      * @param instance The instance to set
126      */
127     static protected void setInstance(ConfigurationManager instance)
128     {
129         fieldInstance = instance;
130     }
131     /***
132      * Updates the instance.
133      */
134     static protected void updateInstance() throws SieveConfigurationException
135     {
136         setInstance(computeInstance());
137     }
138     /***
139      * Method getConfigName answers the name of the Sieve configuration file.
140      * 
141      * @return String
142      */
143     static protected String getConfigName()
144     {
145         return "sieveConfig.xml";
146     }
147     /***
148      * <p>
149      * Method getConfigStream answers an InputStream over the Sieve
150      * configuration file. It is located by searching the classpath of the
151      * current ClassLoader.
152      * </p><p>
153      * The context classloader is searched first. If a suitably named
154      * resource is found then this is returned. Otherwise, the classloader
155      * used to load this class is searched for the resource.
156      * </p>
157      * @return InputStream
158      * @throws IOException
159      */
160     static protected InputStream getConfigStream() throws IOException
161     {
162         InputStream stream = null;
163         final String configName = getConfigName();
164         // Context classloader is usually right in a JEE evironment
165         final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
166         if (contextClassLoader != null)
167         {
168             stream = contextClassLoader.getResourceAsStream(configName);
169         }
170         
171         // Sometimes context classloader will not be set conventionally
172         // So, try class classloader
173         if (null == stream)
174         {
175             stream = ConfigurationManager.class.getClassLoader()
176                 .getResourceAsStream(configName);
177         }
178 
179         if (null == stream)
180             throw new IOException("Resource \"" + configName
181                     + "\" not found");
182         return stream;
183     }
184     /***
185      * Method getCommandMap answers a Map of Command names and their associated
186      * class names, lazily initialized if required.
187      * 
188      * @return Map
189      */
190     public synchronized Map getCommandMap()
191     {
192         Map commandMap = null;
193         if (null == (commandMap = getCommandMapBasic()))
194         {
195             updateCommandMap();
196             return getCommandMap();
197         }
198         return commandMap;
199     }
200     /***
201      * Method getTestMap answers a Map of Test names and their associated class
202      * names, lazily initialized if required.
203      * 
204      * @return Map
205      */
206     public synchronized Map getTestMap()
207     {
208         Map testMap = null;
209         if (null == (testMap = getTestMapBasic()))
210         {
211             updateTestMap();
212             return getTestMap();
213         }
214         return testMap;
215     }
216     /***
217      * Method getComparatorMap answers a Map of Comparator names and their
218      * associated class names, lazily initialized if required.
219      * 
220      * @return Map
221      */
222     public synchronized Map getComparatorMap()
223     {
224         Map comparatorMap = null;
225         if (null == (comparatorMap = getComparatorMapBasic()))
226         {
227             updateComparatorMap();
228             return getComparatorMap();
229         }
230         return comparatorMap;
231     }
232     /***
233      * Method getCommandMapBasic answers a Map of Command names and their
234      * associated class names.
235      * 
236      * @return Map
237      */
238     private Map getCommandMapBasic()
239     {
240         return fieldCommandMap;
241     }
242     /***
243      * Method getTestMapBasic answers a Map of Test names and their associated
244      * class names.
245      * 
246      * @return Map
247      */
248     private Map getTestMapBasic()
249     {
250         return fieldTestMap;
251     }
252     /***
253      * Method getComparatorMapBasic answers a Map of Comparator names and their
254      * a ssociated class names.
255      * 
256      * @return Map
257      */
258     private Map getComparatorMapBasic()
259     {
260         return fieldComparatorMap;
261     }
262     /***
263      * Method computeCommandMap answers a new CommandMap.
264      * 
265      * @return Map
266      */
267     protected Map computeCommandMap()
268     {
269         return new HashMap();
270     }
271     /***
272      * Method computeTestMap answers a new TestMap.
273      * 
274      * @return Map
275      */
276     protected Map computeTestMap()
277     {
278         return new HashMap();
279     }
280     /***
281      * Method computeComparatorMap answers a new ComparatorMap.
282      * 
283      * @return Map
284      */
285     protected Map computeComparatorMap()
286     {
287         return new HashMap();
288     }
289     /***
290      * Method putCommandMapEntry adds an association between a Command name and
291      * an implementation class to the Command Map.
292      * 
293      * @param name
294      * @param className
295      */
296     public void putCommandMapEntry(String name, String className)
297     {
298         getCommandMap().put(name, className);
299     }
300     /***
301      * Method putTestMapEntry adds an association between a Test name and an
302      * implementation class to the Test Map.
303      * 
304      * @param name
305      * @param className
306      */
307     public void putTestMapEntry(String name, String className)
308     {
309         getTestMap().put(name, className);
310     }
311     /***
312      * Method putComparatorMapEntry adds an association between a Comparator
313      * name and an implementation class to the Comparator Map.
314      * 
315      * @param name
316      * @param className
317      */
318     public void putComparatorMapEntry(String name, String className)
319     {
320         getComparatorMap().put(name, className);
321     }
322     /***
323      * Returns the digester, lazily initialised if required.
324      * 
325      * @return Digester
326      */
327     protected synchronized Digester getDigester()
328     {
329         Digester digester = null;
330         if (null == (digester = getDigesterBasic()))
331         {
332             updateDigester();
333             return getDigester();
334         }
335         return digester;
336     }
337     /***
338      * Returns the digester.
339      * 
340      * @return Digester
341      */
342     private Digester getDigesterBasic()
343     {
344         return fieldDigester;
345     }
346     /***
347      * Method computeDigester answers a new digester intialised with the rules
348      * to parse the Sieve configuration file.
349      * 
350      * @return Digester
351      */
352     protected Digester computeDigester()
353     {
354         Digester digester = new Digester();
355         digester.push(this);
356         digester.setValidating(false);
357         // CommandMap rules
358         digester.addCallMethod("sieve/commandMap/entry", "putCommandMapEntry",
359                 2, new Class[]{String.class, String.class});
360         digester.addCallParam("sieve/commandMap/entry/name", 0);
361         digester.addCallParam("sieve/commandMap/entry/class", 1);
362         // TestMap rules
363         digester.addCallMethod("sieve/testMap/entry", "putTestMapEntry", 2,
364                 new Class[]{String.class, String.class});
365         digester.addCallParam("sieve/testMap/entry/name", 0);
366         digester.addCallParam("sieve/testMap/entry/class", 1);
367         // ComparatorMap rules
368         digester.addCallMethod("sieve/comparatorMap/entry",
369                 "putComparatorMapEntry", 2, new Class[]{String.class,
370                         String.class});
371         digester.addCallParam("sieve/comparatorMap/entry/name", 0);
372         digester.addCallParam("sieve/comparatorMap/entry/class", 1);
373         return digester;
374     }
375     /***
376      * Sets the digester.
377      * 
378      * @param digester The digester to set
379      */
380     protected void setDigester(Digester digester)
381     {
382         fieldDigester = digester;
383     }
384     /***
385      * Updates the digester.
386      */
387     protected void updateDigester()
388     {
389         setDigester(computeDigester());
390     }
391     /***
392      * Method parse uses the Digester to parse the XML statements in the Sieve
393      * configuration file into Java objects.
394      * 
395      * @return Object
396      * @throws SAXException
397      * @throws IOException
398      */
399     protected Object parse() throws SAXException, IOException
400     {
401         return getDigester().parse(getConfigStream());
402     }
403     /***
404      * Sets the commandMap.
405      * 
406      * @param commandMap The commandMap to set
407      */
408     protected void setCommandMap(Map commandMap)
409     {
410         fieldCommandMap = commandMap;
411     }
412     /***
413      * Sets the testMap.
414      * 
415      * @param testMap The testMap to set
416      */
417     protected void setTestMap(Map testMap)
418     {
419         fieldTestMap = testMap;
420     }
421     /***
422      * Sets the comparatorMap.
423      * 
424      * @param comparatorMap The comparatorMap to set
425      */
426     protected void setComparatorMap(Map comparatorMap)
427     {
428         fieldComparatorMap = comparatorMap;
429     }
430     /***
431      * Updates the commandMap.
432      */
433     protected void updateCommandMap()
434     {
435         setCommandMap(computeCommandMap());
436     }
437     /***
438      * Updates the testMap.
439      */
440     protected void updateTestMap()
441     {
442         setTestMap(computeTestMap());
443     }
444     /***
445      * Updates the comparatorMap.
446      */
447     protected void updateComparatorMap()
448     {
449         setComparatorMap(computeComparatorMap());
450     }
451 }