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
165 final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
166 if (contextClassLoader != null)
167 {
168 stream = contextClassLoader.getResourceAsStream(configName);
169 }
170
171
172
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
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
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
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 }