blob: a4031eb9a79929d9778700e5e8623e06904a9a61 [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.jsieve;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* <p>
* <code>ConfigurationManager</code> parses the XML statements
* in the Sieve configuration file and translates them to Java objects.
* </p>
* <p>
* The Sieve configuration is read from 3 properties files
* </p>
* <ul>
* <li><code>org/apache/jsieve/commandsmap.properties</code></li>
* <li><code>org/apache/jsieve/testsmap.properties</code></li>
* <li><code>org/apache/jsieve/comparatorsmap.properties</code></li>
* </ul>
* <p>They are located by searching the classpath of the current ClassLoader.
* </p>
* <h4>Thread Safety</h4>
* <p>
* Each configuration manager instance may be safely accessed by concurrent threads.
* </p>
* <p>
* The managers constructed by
* </p>
* <ul>
* <li>{@link #getCommandManager()}</li>
* <li>{@link #getComparatorManager()}</li>
* <li>{@link #getTestManager()}</li>
* </ul>
* <p>
* and the {@link SieveFactory} built by
* </p>
* <ul>
* <li>{@link #build()}</li>
* </ul>
* <p>
* may be safely shared by multiple threads.
* </p>
*/
public class ConfigurationManager {
private static final int DEFAULT_INITIAL_CONCURRENCY_LEVEL = 8;
private static final String COMMANDSMAP_PROPERTIES = "org/apache/jsieve/commandsmap.properties";
private static final String TESTSMAP_PROPERTIES = "org/apache/jsieve/testsmap.properties";
private static final String COMPARATORSMAP_PROPERTIES = "org/apache/jsieve/comparatorsmap.properties";
/**
* A Map of the Command names and their associated class names.
*/
private ConcurrentMap<String, String> fieldCommandMap;
/**
* A Map of the Test names and their associated class names.
*/
private ConcurrentMap<String, String> fieldTestMap;
/**
* A Map of the Comparator names and their associated class names.
*/
private ConcurrentMap<String, String> fieldComparatorMap;
/**
* The initial size for the {@link ConcurrentHashMap} concurrency level.
*/
private int initialConcurrencyLevel = DEFAULT_INITIAL_CONCURRENCY_LEVEL;
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationManager.class);
/**
* Constructor for ConfigurationManager.
*
* @throws SieveConfigurationException
*/
public ConfigurationManager() throws SieveConfigurationException {
super();
try {
parse();
} catch (SAXException e) {
LOGGER.error("Exception processing Configuration: ", e);
throw new SieveConfigurationException(e);
} catch (IOException e) {
LOGGER.error("Exception processing Configuration: ", e);
throw new SieveConfigurationException(e);
}
}
/**
* Gets the current initial size for the {@link ConcurrentHashMap} concurrency level.
*
* @return number of concurrent threads estimated for initial sizing
*/
public int getInitialConcurrencyLevel() {
return initialConcurrencyLevel;
}
/**
* Sets the current initial size for the {@link ConcurrentHashMap} concurrency level.
*
* @param initialConcurrencyLevel number of concurrent threads estimated for initial sizing
*/
public void setInitialConcurrencyLevel(int initialConcurrencyLevel) {
this.initialConcurrencyLevel = initialConcurrencyLevel;
}
/**
* <p>
* Method getConfigStream answers an InputStream over the Sieve
* configuration file. It is located by searching the classpath of the
* current ClassLoader.
* </p>
* <p>
* The context classloader is searched first. If a suitably named resource
* is found then this is returned. Otherwise, the classloader used to load
* this class is searched for the resource.
* </p>
*
* @return InputStream
* @throws IOException
*/
private InputStream getConfigStream(String configName) throws IOException {
InputStream stream = null;
// Context classloader is usually right in a JEE evironment
final ClassLoader contextClassLoader = Thread.currentThread()
.getContextClassLoader();
if (contextClassLoader != null) {
stream = contextClassLoader.getResourceAsStream(configName);
}
// Sometimes context classloader will not be set conventionally
// So, try class classloader
if (null == stream) {
stream = ConfigurationManager.class.getClassLoader()
.getResourceAsStream(configName);
}
if (null == stream)
throw new IOException("Resource \"" + configName + "\" not found");
return stream;
}
/**
* Method getCommandMap answers a Map of Command names and their associated
* class names, lazily initialized if required.
*
* @return Map not null
*/
public ConcurrentMap<String, String> getCommandMap() {
if (null == fieldCommandMap) {
fieldCommandMap = new ConcurrentHashMap<String, String>();
}
return fieldCommandMap;
}
/**
* Method getTestMap answers a Map of Test names and their associated class
* names, lazily initialized if required.
*
* @return Map not null
*/
public ConcurrentMap<String, String> getTestMap() {
if (null == fieldTestMap) {
fieldTestMap = new ConcurrentHashMap<String, String>();
}
return fieldTestMap;
}
/**
* Method getComparatorMap answers a Map of Comparator names and their
* associated class names, lazily initialized if required.
*
* @return Map not null
*/
public ConcurrentMap<String, String> getComparatorMap() {
if (null == fieldComparatorMap) {
fieldComparatorMap = new ConcurrentHashMap<String, String>();
}
return fieldComparatorMap;
}
/**
* Method parse uses the Digester to parse the XML statements in the Sieve
* configuration file into Java objects.
*
* @throws SAXException
* @throws IOException
*/
private void parse() throws SAXException, IOException {
setCommandMap(loadConfiguration(COMMANDSMAP_PROPERTIES));
setTestMap(loadConfiguration(TESTSMAP_PROPERTIES));
setComparatorMap(loadConfiguration(COMPARATORSMAP_PROPERTIES));
}
private ConcurrentMap<String, String> loadConfiguration(final String name) throws IOException {
final Properties properties = loadProperties(name);
final ConcurrentMap<String, String> result =
new ConcurrentHashMap<String, String>(properties.size(), 1.0f, initialConcurrencyLevel);
for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
result.put(entry.getKey().toString(), entry.getValue().toString());
}
return result;
}
private Properties loadProperties(final String name) throws IOException {
final InputStream is = getConfigStream(name);
final Properties p = new Properties();
p.load(is);
return p;
}
/**
* Sets the commandMap.
*
* @param commandMap The commandMap to set
*/
private void setCommandMap(ConcurrentMap<String, String> commandMap) {
fieldCommandMap = commandMap;
}
/**
* Sets the testMap.
*
* @param testMap The testMap to set
*/
private void setTestMap(ConcurrentMap<String, String> testMap) {
fieldTestMap = testMap;
}
/**
* Sets the comparatorMap.
*
* @param comparatorMap The comparatorMap to set
*/
private void setComparatorMap(ConcurrentMap<String, String> comparatorMap) {
fieldComparatorMap = comparatorMap;
}
public ComparatorManager getComparatorManager() {
return new ComparatorManagerImpl(fieldComparatorMap);
}
public CommandManager getCommandManager() {
return new CommandManagerImpl(fieldCommandMap);
}
public TestManager getTestManager() {
return new TestManagerImpl(fieldTestMap);
}
public SieveFactory build() {
return new SieveFactory(getCommandManager(), getComparatorManager(),
getTestManager());
}
}