/*
* eXist Open Source Native XML Database
* Copyright (C) 2009 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.util;
import org.apache.log4j.Logger;
import org.exist.Indexer;
import org.exist.cluster.ClusterComunication;
import org.exist.cluster.journal.JournalManager;
import org.exist.indexing.IndexManager;
import org.exist.memtree.SAXAdapter;
import org.exist.protocolhandler.eXistURLStreamHandlerFactory;
import org.exist.scheduler.JobException;
import org.exist.scheduler.Scheduler;
import org.exist.security.User;
import org.exist.security.XMLSecurityManager;
import org.exist.security.xacml.XACMLConstants;
import org.exist.storage.BrokerFactory;
import org.exist.storage.BrokerPool;
import org.exist.storage.CollectionCacheManager;
import org.exist.storage.DBBroker;
import org.exist.storage.DefaultCacheManager;
import org.exist.storage.IndexSpec;
import org.exist.storage.NativeBroker;
import org.exist.storage.NativeValueIndex;
import org.exist.storage.TextSearchEngine;
import org.exist.storage.XQueryPool;
import org.exist.storage.journal.Journal;
import org.exist.storage.serializers.Serializer;
import org.exist.storage.serializers.CustomMatchListenerFactory;
import org.exist.storage.txn.TransactionManager;
import org.exist.validation.GrammarPool;
import org.exist.validation.resolver.eXistXMLCatalogResolver;
import org.exist.xmldb.DatabaseImpl;
import org.exist.xquery.FunctionFactory;
import org.exist.xquery.PerformanceStats;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.XQueryWatchDog;
import org.exist.xslt.TransformerFactoryAllocator;
import org.quartz.SimpleTrigger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class Configuration implements ErrorHandler
{
private final static Logger LOG = Logger.getLogger(Configuration.class); //Logger
protected String configFilePath = null;
protected File existHome = null;
protected DocumentBuilder builder = null;
protected HashMap<String,Object> config = new HashMap<String,Object>(); //Configuration
public static final class JobConfig
{
private String type = null;
private String jobName = null;
private String resourceName = null;
private String schedule = null;
private long delay = -1;
private int repeat = SimpleTrigger.REPEAT_INDEFINITELY;
private Properties parameters = new Properties();
public JobConfig(String type, String jobName, String resourceName, String schedule) throws JobException
{
if(type != null)
{
this.type = type;
}
else
{
this.type = Scheduler.JOB_TYPE_USER;
}
this.jobName = jobName;
if(resourceName != null)
{
this.resourceName = resourceName;
}
else
{
throw new JobException(JobException.JOB_ABORT, "Job must have a resource for execution");
}
if(schedule == null && !type.equals(Scheduler.JOB_TYPE_STARTUP))
{
throw new JobException(JobException.JOB_ABORT, "Job must have a schedule");
}
else
{
this.schedule = schedule;
}
}
public String getType()
{
return type;
}
public String getJobName() {
return jobName;
}
public String getResourceName()
{
return resourceName;
}
public String getSchedule()
{
return schedule;
}
public void setDelay(long delay) {
this.delay = delay;
}
public void setRepeat(int repeat) {
this.repeat = repeat;
}
public long getDelay() {
return delay;
}
public int getRepeat() {
return repeat;
}
public void addParameter(String name, String value)
{
parameters.put(name, value);
}
public Properties getParameters()
{
return parameters;
}
}
public static final class IndexModuleConfig {
protected String id;
protected String className;
protected Element config;
public IndexModuleConfig(String id, String className, Element config) {
this.id = id;
this.className = className;
this.config = config;
}
public String getClassName() {
return className;
}
public Element getConfig() {
return config;
}
public String getId() {
return id;
}
}
public Configuration() throws DatabaseConfigurationException {
this(DatabaseImpl.CONF_XML, null);
}
public Configuration(String configFilename) throws DatabaseConfigurationException {
this(configFilename, null);
}
public Configuration(String configFilename, String existHomeDirname) throws DatabaseConfigurationException {
try {
InputStream is = null;
if (configFilename == null) {
// Default file name
configFilename = DatabaseImpl.CONF_XML;
}
// firstly, try to read the configuration from a file within the
// classpath
try {
is = Configuration.class.getClassLoader().getResourceAsStream(configFilename);
if (is != null) LOG.info("Reading configuration from classloader");
} catch (Exception e) {
// EB: ignore and go forward, e.g. in case there is an absolute
// file name for configFileName
LOG.debug(e);
}
// otherwise, secondly try to read configuration from file. Guess the
// location if necessary
if (is == null) {
existHome = (existHomeDirname != null) ? new File(existHomeDirname) : ConfigurationHelper.getExistHome(configFilename);
if (existHome == null) {
// EB: try to create existHome based on location of config file
// when config file points to absolute file location
File absoluteConfigFile = new File(configFilename);
if (absoluteConfigFile.isAbsolute() &&
absoluteConfigFile.exists() && absoluteConfigFile.canRead()) {
existHome = absoluteConfigFile.getParentFile();
configFilename = absoluteConfigFile.getName();
}
}
File configFile = new File(configFilename);
if (!configFile.isAbsolute() && existHome != null)
// try the passed or constructed existHome first
configFile = new File(existHome, configFilename);
if (configFile == null)
configFile = ConfigurationHelper.lookup(configFilename);
if (!configFile.exists() || !configFile.canRead())
throw new DatabaseConfigurationException("Unable to read configuration file at " + configFile.getAbsolutePath());
configFilePath = configFile.getAbsolutePath();
is = new FileInputStream(configFile);
// set dbHome to parent of the conf file found, to resolve relative
// path from conf file
existHomeDirname = configFile.getParentFile().getCanonicalPath();
LOG.info("Reading configuration from file " + configFile);
}
// initialize xml parser
// we use eXist's in-memory DOM implementation to work
// around a bug in Xerces
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
// factory.setFeature("http://apache.org/xml/features/validation/schema", true);
// factory.setFeature("http://apache.org/xml/features/validation/dynamic", true);
InputSource src = new InputSource(is);
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
SAXAdapter adapter = new SAXAdapter();
reader.setContentHandler(adapter);
reader.parse(src);
Document doc = adapter.getDocument();
//indexer settings
NodeList indexers = doc.getElementsByTagName(Indexer.CONFIGURATION_ELEMENT_NAME);
if (indexers.getLength() > 0) {
configureIndexer(existHomeDirname, doc, (Element) indexers.item(0));
}
//scheduler settings
NodeList schedulers = doc.getElementsByTagName(Scheduler.CONFIGURATION_ELEMENT_NAME);
if(schedulers.getLength() > 0) {
configureScheduler((Element) schedulers.item(0));
}
//db connection settings
NodeList dbcon = doc.getElementsByTagName(BrokerPool.CONFIGURATION_CONNECTION_ELEMENT_NAME);
if (dbcon.getLength() > 0) {
configureBackend(existHomeDirname, (Element) dbcon.item(0));
}
//transformer settings
NodeList transformers = doc.getElementsByTagName(TransformerFactoryAllocator.CONFIGURATION_ELEMENT_NAME);
if(transformers.getLength() > 0) {
configureTransformer((Element) transformers.item(0));
}
//serializer settings
NodeList serializers = doc.getElementsByTagName(Serializer.CONFIGURATION_ELEMENT_NAME);
if (serializers.getLength() > 0) {
configureSerializer((Element) serializers.item(0));
}
//XUpdate settings
NodeList xupdates = doc.getElementsByTagName(DBBroker.CONFIGURATION_ELEMENT_NAME);
if (xupdates.getLength() > 0) {
configureXUpdate((Element) xupdates.item(0));
}
//XQuery settings
NodeList xquery = doc.getElementsByTagName(XQueryContext.CONFIGURATION_ELEMENT_NAME);
if (xquery.getLength() > 0) {
configureXQuery((Element) xquery.item(0));
}
//XACML settings
NodeList xacml = doc.getElementsByTagName(XACMLConstants.CONFIGURATION_ELEMENT_NAME);
//TODO : check that we have only one element
if (xacml.getLength() > 0) {
configureXACML((Element)xacml.item(0));
}
//Cluster configuration
NodeList clusters = doc.getElementsByTagName(ClusterComunication.CONFIGURATION_ELEMENT_NAME);
if(clusters.getLength() > 0) {
configureCluster((Element)clusters.item(0));
}
//Validation
NodeList validations = doc.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_ELEMENT_NAME);
if (validations.getLength() > 0) {
configureValidation(existHomeDirname, doc, (Element) validations.item(0));
}
} catch (SAXException e) {
LOG.warn("error while reading config file: " + configFilename, e);
throw new DatabaseConfigurationException(e.getMessage());
} catch (ParserConfigurationException cfg) {
LOG.warn("error while reading config file: " + configFilename, cfg);
throw new DatabaseConfigurationException(cfg.getMessage());
} catch (IOException io) {
LOG.warn("error while reading config file: " + configFilename, io);
throw new DatabaseConfigurationException(io.getMessage());
}
}
private void configureCluster(Element cluster) {
String protocol = cluster.getAttribute(ClusterComunication.CLUSTER_PROTOCOL_ATTRIBUTE);
if(protocol != null) {
config.put(ClusterComunication.PROPERTY_CLUSTER_PROTOCOL, protocol);
LOG.debug(ClusterComunication.PROPERTY_CLUSTER_PROTOCOL + ": " + config.get(ClusterComunication.PROPERTY_CLUSTER_PROTOCOL));
}
String user = cluster.getAttribute(ClusterComunication.CLUSTER_USER_ATTRIBUTE);
if(user != null) {
config.put(ClusterComunication.PROPERTY_CLUSTER_USER, user);
LOG.debug(ClusterComunication.PROPERTY_CLUSTER_USER + ": " + config.get(ClusterComunication.PROPERTY_CLUSTER_USER));
}
String pwd = cluster.getAttribute(ClusterComunication.CLUSTER_PWD_ATTRIBUTE);
if(pwd != null) {
config.put(ClusterComunication.PROPERTY_CLUSTER_PWD, pwd);
LOG.debug(ClusterComunication.PROPERTY_CLUSTER_PWD + ": " + config.get(ClusterComunication.PROPERTY_CLUSTER_PWD));
}
String dir = cluster.getAttribute(JournalManager.JOURNAL_DIR_ATTRIBUTE);
if(dir != null) {
config.put(JournalManager.PROPERTY_JOURNAL_DIR, dir);
LOG.debug(JournalManager.PROPERTY_JOURNAL_DIR + ": " + config.get(JournalManager.PROPERTY_JOURNAL_DIR));
}
String excludedColl = cluster.getAttribute(ClusterComunication.CLUSTER_EXCLUDED_COLLECTIONS_ATTRIBUTE);
ArrayList list = new ArrayList();
if(excludedColl != null) {
String[] excl = excludedColl.split(",");
for(int i=0;i<excl.length;i++){
list.add(excl[i]);
}
}
if(!list.contains(NativeBroker.TEMP_COLLECTION))
list.add(NativeBroker.TEMP_COLLECTION);
config.put(ClusterComunication.PROPERTY_CLUSTER_EXCLUDED_COLLECTIONS, list);
LOG.debug(ClusterComunication.PROPERTY_CLUSTER_EXCLUDED_COLLECTIONS + ": " + config.get(ClusterComunication.PROPERTY_CLUSTER_EXCLUDED_COLLECTIONS));
/*Cluster parameters for test*/
String maxStore = cluster.getAttribute(JournalManager.CLUSTER_JOURNAL_MAXSTORE_ATTRIBUTE);
if(maxStore == null || maxStore.trim().length()==0) {
maxStore = "65000";
}
config.put(JournalManager.PROPERTY_CLUSTER_JOURNAL_MAXSTORE, Integer.valueOf(maxStore));
LOG.debug(JournalManager.PROPERTY_CLUSTER_JOURNAL_MAXSTORE + ": " + config.get(JournalManager.PROPERTY_CLUSTER_JOURNAL_MAXSTORE));
String shift = cluster.getAttribute(JournalManager.CLUSTER_JOURNAL_SHIFT_ATTRIBUTE);
if(shift == null || shift.trim().length()==0 ) {
shift = "100";
}
config.put(JournalManager.PROPERTY_CLUSTER_JOURNAL_SHIFT, Integer.valueOf(shift));
LOG.debug(JournalManager.PROPERTY_CLUSTER_JOURNAL_SHIFT + ": " + config.get(JournalManager.PROPERTY_CLUSTER_JOURNAL_SHIFT));
}
private void configureXQuery(Element xquery) throws DatabaseConfigurationException {
//java binding
String javabinding = xquery.getAttribute(FunctionFactory.ENABLE_JAVA_BINDING_ATTRIBUTE);
if(javabinding != null) {
config.put(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING, javabinding);
LOG.debug(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING + ": " + config.get(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING));
}
String disableDeprecated = xquery.getAttribute(FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_ATTRIBUTE);
config.put(FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS, Configuration.parseBoolean(disableDeprecated, FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_BY_DEFAULT));
LOG.debug(FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS + ": " + config.get(FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS));
String optimize = xquery.getAttribute(XQueryContext.ENABLE_QUERY_REWRITING_ATTRIBUTE);
if (optimize != null && optimize.length() > 0) {
config.put(XQueryContext.PROPERTY_ENABLE_QUERY_REWRITING, optimize);
LOG.debug(XQueryContext.PROPERTY_ENABLE_QUERY_REWRITING + ": " + config.get(XQueryContext.PROPERTY_ENABLE_QUERY_REWRITING));
}
String backwardCompatible = xquery.getAttribute(XQueryContext.XQUERY_BACKWARD_COMPATIBLE_ATTRIBUTE);
if (backwardCompatible != null && backwardCompatible.length() > 0) {
config.put(XQueryContext.PROPERTY_XQUERY_BACKWARD_COMPATIBLE, backwardCompatible);
LOG.debug(XQueryContext.PROPERTY_XQUERY_BACKWARD_COMPATIBLE + ": " + config.get(XQueryContext.PROPERTY_XQUERY_BACKWARD_COMPATIBLE));
}
String raiseErrorOnFailedRetrieval = xquery.getAttribute(XQueryContext.XQUERY_RAISE_ERROR_ON_FAILED_RETRIEVAL_ATTRIBUTE);
config.put(XQueryContext.PROPERTY_XQUERY_RAISE_ERROR_ON_FAILED_RETRIEVAL, Configuration.parseBoolean(raiseErrorOnFailedRetrieval, XQueryContext.XQUERY_RAISE_ERROR_ON_FAILED_RETRIEVAL_DEFAULT));
LOG.debug(XQueryContext.PROPERTY_XQUERY_RAISE_ERROR_ON_FAILED_RETRIEVAL + ": " + config.get(XQueryContext.PROPERTY_XQUERY_RAISE_ERROR_ON_FAILED_RETRIEVAL));
String trace = xquery.getAttribute(PerformanceStats.CONFIG_ATTR_TRACE);
config.put(PerformanceStats.CONFIG_PROPERTY_TRACE, trace);
//built-in-modules
Map classMap = new HashMap();
Map knownMappings = new HashMap();
XQueryContext.loadModuleClasses(xquery, classMap, knownMappings);
config.put(XQueryContext.PROPERTY_BUILT_IN_MODULES, classMap);
config.put(XQueryContext.PROPERTY_STATIC_MODULE_MAP, knownMappings);
}
public void configureXACML(Element xacml) {
String enable = xacml.getAttribute(XACMLConstants.ENABLE_XACML_ATTRIBUTE);
config.put(XACMLConstants.ENABLE_XACML_PROPERTY, Configuration.parseBoolean(enable, XACMLConstants.ENABLE_XACML_BY_DEFAULT));
LOG.debug(XACMLConstants.ENABLE_XACML_PROPERTY + ": " + config.get(XACMLConstants.ENABLE_XACML_PROPERTY));
String loadDefaults = xacml.getAttribute(XACMLConstants.LOAD_DEFAULT_POLICIES_ATTRIBUTE);
config.put(XACMLConstants.LOAD_DEFAULT_POLICIES_PROPERTY, Configuration.parseBoolean(loadDefaults, true));
LOG.debug(XACMLConstants.LOAD_DEFAULT_POLICIES_PROPERTY + ": " + config.get(XACMLConstants.LOAD_DEFAULT_POLICIES_PROPERTY));
}
/**
* @param xupdate
* @throws NumberFormatException
*/
private void configureXUpdate(Element xupdate) throws NumberFormatException {
String fragmentation = xupdate.getAttribute(DBBroker.XUPDATE_FRAGMENTATION_FACTOR_ATTRIBUTE);
if (fragmentation != null) {
config.put(DBBroker.PROPERTY_XUPDATE_FRAGMENTATION_FACTOR, new Integer(fragmentation));
LOG.debug(DBBroker.PROPERTY_XUPDATE_FRAGMENTATION_FACTOR + ": "
+ config.get(DBBroker.PROPERTY_XUPDATE_FRAGMENTATION_FACTOR));
}
String consistencyCheck = xupdate.getAttribute(DBBroker.XUPDATE_CONSISTENCY_CHECKS_ATTRIBUTE);
if (consistencyCheck != null) {
config.put(DBBroker.PROPERTY_XUPDATE_CONSISTENCY_CHECKS, parseBoolean(consistencyCheck, false));
LOG.debug(DBBroker.PROPERTY_XUPDATE_CONSISTENCY_CHECKS + ": "
+ config.get(DBBroker.PROPERTY_XUPDATE_CONSISTENCY_CHECKS));
}
}
private void configureTransformer(Element transformer) {
String className = transformer.getAttribute(TransformerFactoryAllocator.TRANSFORMER_CLASS_ATTRIBUTE);
if( className != null ) {
config.put( TransformerFactoryAllocator.PROPERTY_TRANSFORMER_CLASS, className );
LOG.debug( TransformerFactoryAllocator.PROPERTY_TRANSFORMER_CLASS + ": " +
config.get( TransformerFactoryAllocator.PROPERTY_TRANSFORMER_CLASS ) );
// Process any specified attributes that should be passed to the transformer factory
NodeList attrs = transformer.getElementsByTagName( TransformerFactoryAllocator.CONFIGURATION_TRANSFORMER_ATTRIBUTE_ELEMENT_NAME );
Hashtable attributes = new Properties();
for( int a = 0; a < attrs.getLength(); a++ ) {
Element attr = (Element)attrs.item( a );
String name = attr.getAttribute( "name" );
String value = attr.getAttribute( "value" );
String type = attr.getAttribute( "type" );
if( name == null || name.length() == 0 ) {
LOG.warn( "Discarded invalid attribute for TransformerFactory: '" + className + "', name not specified" );
} else if( type == null || type.length() == 0 || type.equalsIgnoreCase( "string" ) ) {
attributes.put( name, value );
} else if( type.equalsIgnoreCase( "boolean" ) ) {
attributes.put( name, Boolean.valueOf( value ) );
} else if( type.equalsIgnoreCase( "integer" ) ) {
try {
attributes.put( name, Integer.valueOf( value ) );
}
catch( NumberFormatException nfe ) {
LOG.warn( "Discarded invalid attribute for TransformerFactory: '" + className + "', name: " + name + ", value not integer: " + value );
}
} else {
// Assume string type
attributes.put( name, value );
}
}
config.put( TransformerFactoryAllocator.PROPERTY_TRANSFORMER_ATTRIBUTES, attributes );
}
String cachingValue = transformer.getAttribute(TransformerFactoryAllocator.TRANSFORMER_CACHING_ATTRIBUTE);
if (cachingValue != null) {
config.put(TransformerFactoryAllocator.PROPERTY_CACHING_ATTRIBUTE, parseBoolean(cachingValue, false));
LOG.debug(TransformerFactoryAllocator.PROPERTY_CACHING_ATTRIBUTE + ": " + config.get(TransformerFactoryAllocator.PROPERTY_CACHING_ATTRIBUTE));
}
}
/**
* @param serializer
*/
private void configureSerializer(Element serializer) {
String xinclude = serializer.getAttribute(Serializer.ENABLE_XINCLUDE_ATTRIBUTE);
if (xinclude != null) {
config.put(Serializer.PROPERTY_ENABLE_XINCLUDE, xinclude);
LOG.debug(Serializer.PROPERTY_ENABLE_XINCLUDE + ": " + config.get(Serializer.PROPERTY_ENABLE_XINCLUDE));
}
String xsl = serializer.getAttribute(Serializer.ENABLE_XSL_ATTRIBUTE);
if (xsl != null) {
config.put(Serializer.PROPERTY_ENABLE_XSL, xsl);
LOG.debug(Serializer.PROPERTY_ENABLE_XSL + ": " + config.get(Serializer.PROPERTY_ENABLE_XSL));
}
String indent = serializer.getAttribute(Serializer.INDENT_ATTRIBUTE);
if (indent != null) {
config.put(Serializer.PROPERTY_INDENT, indent);
LOG.debug(Serializer.PROPERTY_INDENT + ": " + config.get(Serializer.PROPERTY_INDENT));
}
String compress = serializer.getAttribute(Serializer.COMPRESS_OUTPUT_ATTRIBUTE);
if (compress != null) {
config.put(Serializer.PROPERTY_COMPRESS_OUTPUT, compress);
LOG.debug(Serializer.PROPERTY_COMPRESS_OUTPUT + ": " + config.get(Serializer.PROPERTY_COMPRESS_OUTPUT));
}
String internalId = serializer.getAttribute(Serializer.ADD_EXIST_ID_ATTRIBUTE);
if (internalId != null) {
config.put(Serializer.PROPERTY_ADD_EXIST_ID, internalId);
LOG.debug(Serializer.PROPERTY_ADD_EXIST_ID + ": " + config.get(Serializer.PROPERTY_ADD_EXIST_ID));
}
String tagElementMatches = serializer.getAttribute(Serializer.TAG_MATCHING_ELEMENTS_ATTRIBUTE);
if (tagElementMatches != null) {
config.put(Serializer.PROPERTY_TAG_MATCHING_ELEMENTS, tagElementMatches);
LOG.debug(Serializer.PROPERTY_TAG_MATCHING_ELEMENTS + ": " + config.get(Serializer.PROPERTY_TAG_MATCHING_ELEMENTS));
}
String tagAttributeMatches = serializer.getAttribute(Serializer.TAG_MATCHING_ATTRIBUTES_ATTRIBUTE);
if (tagAttributeMatches != null) {
config.put(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES, tagAttributeMatches);
LOG.debug(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES + ": " + config.get(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES));
}
NodeList nlFilters = serializer.getElementsByTagName(CustomMatchListenerFactory.CONFIGURATION_ELEMENT);
if (nlFilters == null)
return;
List filters = new ArrayList(nlFilters.getLength());
for (int i = 0; i < nlFilters.getLength(); i++) {
Element filterElem = (Element) nlFilters.item(i);
String filterClass = filterElem.getAttribute(CustomMatchListenerFactory.CONFIGURATION_ATTR_CLASS);
if (filterClass != null) {
filters.add(filterClass);
LOG.debug(CustomMatchListenerFactory.CONFIG_MATCH_LISTENERS + ": " + filterClass);
} else {
LOG.warn("Configuration element " + CustomMatchListenerFactory.CONFIGURATION_ELEMENT +
" needs an attribute 'class'");
}
}
config.put(CustomMatchListenerFactory.CONFIG_MATCH_LISTENERS, filters);
}
/**
* Reads the scheduler configuration
*/
private void configureScheduler(Element scheduler)
{
NodeList nlJobs = scheduler.getElementsByTagName(Scheduler.CONFIGURATION_JOB_ELEMENT_NAME);
if(nlJobs == null)
return;
ArrayList jobList = new ArrayList();
String jobType = null;
String jobName = null;
String jobResource = null;
String jobSchedule = null;
String jobDelay = null;
String jobRepeat = null;
for(int i = 0; i < nlJobs.getLength(); i++)
{
Element job = (Element)nlJobs.item(i);
//get the job type
jobType = job.getAttribute(Scheduler.JOB_TYPE_ATTRIBUTE);
if(jobType == null)
jobType = Scheduler.JOB_TYPE_USER; //default to user if unspecified
jobName = job.getAttribute(Scheduler.JOB_NAME_ATTRIBUTE);
//get the job resource
jobResource = job.getAttribute(Scheduler.JOB_CLASS_ATTRIBUTE);
if(jobResource == null)
jobResource = job.getAttribute(Scheduler.JOB_XQUERY_ATTRIBUTE);
//get the job schedule
jobSchedule = job.getAttribute(Scheduler.JOB_CRON_TRIGGER_ATTRIBUTE);
if(jobSchedule == null)
jobSchedule = job.getAttribute(Scheduler.JOB_PERIOD_ATTRIBUTE);
//create the job config
try
{
JobConfig jobConfig = new JobConfig(jobType, jobName, jobResource, jobSchedule);
//get and set the job delay
jobDelay = job.getAttribute(Scheduler.JOB_DELAY_ATTRIBUTE);
if(jobDelay != null && jobDelay.length() > 0)
{
jobConfig.setDelay(Long.parseLong(jobDelay));
}
//get and set the job repeat
jobRepeat = job.getAttribute(Scheduler.JOB_REPEAT_ATTRIBUTE);
if(jobRepeat != null && jobRepeat.length() > 0)
{
jobConfig.setRepeat(Integer.parseInt(jobRepeat));
}
NodeList params = job.getElementsByTagName(Scheduler.CONFIGURATION_JOB_PARAMETER_ELEMENT_NAME);
for(int p = 0; p < params.getLength(); p++)
{
Element param = (Element)params.item(p);
String name = param.getAttribute("name");
String value = param.getAttribute("value");
if(name == null || name.length() == 0)
{
LOG.warn("Discarded invalid parameter for '" + jobType + "' job '" + jobResource + "'");
}
else
{
jobConfig.addParameter(name, value);
}
}
jobList.add(jobConfig);
LOG.debug( "Configured scheduled '" + jobType + "' job '" + jobResource +
( jobSchedule == null ? "" : "' with trigger '" + jobSchedule) +
( jobDelay == null ? "" : "' with delay '" + jobDelay ) +
( jobRepeat == null ? "" : "' repetitions '" + jobRepeat ) + "'" );
}
catch(JobException je)
{
LOG.warn(je);
}
}
if(jobList.size() > 0)
{
JobConfig[] configs = new JobConfig[jobList.size()];
for(int i = 0; i < jobList.size(); i++)
{
configs[i] = (JobConfig)jobList.get(i);
}
config.put(Scheduler.PROPERTY_SCHEDULER_JOBS, configs);
}
}
/**
* @param dbHome
* @param con
* @throws DatabaseConfigurationException
*/
private void configureBackend(String dbHome, Element con) throws DatabaseConfigurationException {
String mysql = con.getAttribute(BrokerFactory.PROPERTY_DATABASE);
if (mysql != null) {
config.put(BrokerFactory.PROPERTY_DATABASE, mysql);
LOG.debug(BrokerFactory.PROPERTY_DATABASE + ": " + config.get(BrokerFactory.PROPERTY_DATABASE));
}
// directory for database files
String dataFiles = con.getAttribute(BrokerPool.DATA_DIR_ATTRIBUTE);
if (dataFiles != null) {
File df = ConfigurationHelper.lookup(dataFiles, dbHome);
if (!df.canRead())
throw new DatabaseConfigurationException(
"cannot read data directory: "
+ df.getAbsolutePath());
config.put(BrokerPool.PROPERTY_DATA_DIR, df.getAbsolutePath());
LOG.debug(BrokerPool.PROPERTY_DATA_DIR + ": " + config.get(BrokerPool.PROPERTY_DATA_DIR));
}
String cacheMem = con.getAttribute(DefaultCacheManager.CACHE_SIZE_ATTRIBUTE);
if (cacheMem != null) {
if (cacheMem.endsWith("M") || cacheMem.endsWith("m"))
cacheMem = cacheMem.substring(0, cacheMem.length() - 1);
try {
config.put(DefaultCacheManager.PROPERTY_CACHE_SIZE, new Integer(cacheMem));
LOG.debug(DefaultCacheManager.PROPERTY_CACHE_SIZE + ": " + config.get(DefaultCacheManager.PROPERTY_CACHE_SIZE) + "m");
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
String collectionCache = con.getAttribute(CollectionCacheManager.CACHE_SIZE_ATTRIBUTE);
if (collectionCache != null) {
if (collectionCache.endsWith("M") || collectionCache.endsWith("m"))
collectionCache = collectionCache.substring(0, collectionCache.length() - 1);
try {
config.put(CollectionCacheManager.PROPERTY_CACHE_SIZE, new Integer(collectionCache));
LOG.debug(CollectionCacheManager.PROPERTY_CACHE_SIZE + ": " + config.get(CollectionCacheManager.PROPERTY_CACHE_SIZE) + "m");
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
String pageSize = con.getAttribute(NativeBroker.PAGE_SIZE_ATTRIBUTE);
if (pageSize != null) {
try {
config.put(BrokerPool.PROPERTY_PAGE_SIZE, new Integer(pageSize));
LOG.debug(BrokerPool.PROPERTY_PAGE_SIZE + ": " + config.get(BrokerPool.PROPERTY_PAGE_SIZE));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
//Not clear : rather looks like a buffers count
String collCacheSize = con.getAttribute(BrokerPool.COLLECTION_CACHE_SIZE_ATTRIBUTE);
if (collCacheSize != null) {
try {
config.put(BrokerPool.PROPERTY_COLLECTION_CACHE_SIZE, new Integer(collCacheSize));
LOG.debug(BrokerPool.PROPERTY_COLLECTION_CACHE_SIZE + ": " + config.get(BrokerPool.PROPERTY_COLLECTION_CACHE_SIZE));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
String nodesBuffer = con.getAttribute(BrokerPool.NODES_BUFFER_ATTRIBUTE);
if (nodesBuffer != null) {
try {
config.put(BrokerPool.PROPERTY_NODES_BUFFER, new Integer(nodesBuffer));
LOG.debug(BrokerPool.PROPERTY_NODES_BUFFER + ": " + config.get(BrokerPool.PROPERTY_NODES_BUFFER));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
String docIds = con.getAttribute(BrokerPool.DOC_ID_MODE_ATTRIBUTE);
if (docIds != null) {
config.put(BrokerPool.DOC_ID_MODE_PROPERTY, docIds);
}
//Unused !
String buffers = con.getAttribute("buffers");
if (buffers != null) {
try {
config.put("db-connection.buffers", new Integer(buffers));
LOG.debug("db-connection.buffers: " + config.get("db-connection.buffers"));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
//Unused !
String collBuffers = con.getAttribute("collection_buffers");
if (collBuffers != null) {
try {
config.put("db-connection.collections.buffers", new Integer(collBuffers));
LOG.debug("db-connection.collections.buffers: " + config.get("db-connection.collections.buffers"));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
//Unused !
String wordBuffers = con.getAttribute("words_buffers");
if (wordBuffers != null)
try {
config.put("db-connection.words.buffers", new Integer(wordBuffers));
LOG.debug("db-connection.words.buffers: " + config.get("db-connection.words.buffers"));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
//Unused !
String elementBuffers = con.getAttribute("elements_buffers");
if (elementBuffers != null) {
try {
config.put("db-connection.elements.buffers", new Integer(elementBuffers));
LOG.debug("db-connection.elements.buffers: " + config.get("db-connection.elements.buffers"));
} catch (NumberFormatException nfe) {
LOG.warn(nfe);
}
}
NodeList securityConf = con.getElementsByTagName(BrokerPool.CONFIGURATION_SECURITY_ELEMENT_NAME);
String securityManagerClassName = BrokerPool.DEFAULT_SECURITY_CLASS;
if (securityConf.getLength()>0) {
Element security = (Element)securityConf.item(0);
securityManagerClassName = security.getAttribute("class");
//Unused
String encoding = security.getAttribute("password-encoding");
config.put("db-connection.security.password-encoding",encoding);
if (encoding!=null) {
LOG.info("db-connection.security.password-encoding: " + config.get("db-connection.security.password-encoding"));
User.setPasswordEncoding(encoding);
} else {
LOG.info("No password encoding set, defaulting.");
}
//Unused
String realm = security.getAttribute("password-realm");
config.put("db-connection.security.password-realm",realm);
if (realm!=null) {
LOG.info("db-connection.security.password-realm: " + config.get("db-connection.security.password-realm"));
User.setPasswordRealm(realm);
} else {
LOG.info("No password realm set, defaulting.");
}
}
try {
config.put(BrokerPool.PROPERTY_SECURITY_CLASS, Class.forName(securityManagerClassName));
LOG.debug(BrokerPool.PROPERTY_SECURITY_CLASS + ": " + config.get(BrokerPool.PROPERTY_SECURITY_CLASS));
} catch (Throwable ex) {
if (ex instanceof ClassNotFoundException) {
throw new DatabaseConfigurationException("Cannot find security manager class "+securityManagerClassName,ex);
} else {
throw new DatabaseConfigurationException("Cannot load security manager class "+securityManagerClassName+" due to "+ex.getMessage(),ex);
}
}
NodeList poolConf = con.getElementsByTagName(BrokerPool.CONFIGURATION_POOL_ELEMENT_NAME);
if (poolConf.getLength() > 0) {
configurePool((Element) poolConf.item(0));
}
NodeList queryPoolConf = con.getElementsByTagName(XQueryPool.CONFIGURATION_ELEMENT_NAME);
if (queryPoolConf.getLength() > 0) {
configureXQueryPool((Element) queryPoolConf.item(0));
}
NodeList watchConf = con.getElementsByTagName(XQueryWatchDog.CONFIGURATION_ELEMENT_NAME);
if (watchConf.getLength() > 0) {
configureWatchdog((Element) watchConf.item(0));
}
NodeList recoveries = con.getElementsByTagName(BrokerPool.CONFIGURATION_RECOVERY_ELEMENT_NAME);
if (recoveries.getLength() > 0) {
configureRecovery(dbHome, (Element)recoveries.item(0));
}
NodeList defaultPermissions = con.getElementsByTagName(XMLSecurityManager.CONFIGURATION_ELEMENT_NAME);
if (defaultPermissions.getLength() > 0) {
configurePermissions((Element)defaultPermissions.item(0));
}
}
private void configureRecovery(String dbHome, Element recovery) throws DatabaseConfigurationException {
String option = recovery.getAttribute(BrokerPool.RECOVERY_ENABLED_ATTRIBUTE);
setProperty(BrokerPool.PROPERTY_RECOVERY_ENABLED, parseBoolean(option, true));
LOG.debug(BrokerPool.PROPERTY_RECOVERY_ENABLED + ": " + config.get(BrokerPool.PROPERTY_RECOVERY_ENABLED));
option = recovery.getAttribute(Journal.RECOVERY_SYNC_ON_COMMIT_ATTRIBUTE);
setProperty(Journal.PROPERTY_RECOVERY_SYNC_ON_COMMIT, parseBoolean(option, true));
LOG.debug(Journal.PROPERTY_RECOVERY_SYNC_ON_COMMIT + ": " + config.get(Journal.PROPERTY_RECOVERY_SYNC_ON_COMMIT));
option = recovery.getAttribute(TransactionManager.RECOVERY_GROUP_COMMIT_ATTRIBUTE);
setProperty(TransactionManager.PROPERTY_RECOVERY_GROUP_COMMIT, parseBoolean(option, false));
LOG.debug(TransactionManager.PROPERTY_RECOVERY_GROUP_COMMIT + ": " + config.get(TransactionManager.PROPERTY_RECOVERY_GROUP_COMMIT));
option = recovery.getAttribute(Journal.RECOVERY_JOURNAL_DIR_ATTRIBUTE);
if (option != null) {
//DWES
File rf = ConfigurationHelper.lookup(option, dbHome);
if (!rf.canRead())
throw new DatabaseConfigurationException(
"cannot read data directory: "
+ rf.getAbsolutePath());
setProperty(Journal.PROPERTY_RECOVERY_JOURNAL_DIR, rf.getAbsolutePath());
LOG.debug(Journal.PROPERTY_RECOVERY_JOURNAL_DIR + ": " + config.get(Journal.PROPERTY_RECOVERY_JOURNAL_DIR));
}
option = recovery.getAttribute(Journal.RECOVERY_SIZE_LIMIT_ATTRIBUTE);
if (option != null) {
if (option.endsWith("M") || option.endsWith("m"))
option = option.substring(0, option.length() - 1);
try {
Integer size = new Integer(option);
setProperty(Journal.PROPERTY_RECOVERY_SIZE_LIMIT, size);
LOG.debug(Journal.PROPERTY_RECOVERY_SIZE_LIMIT + ": " + config.get(Journal.PROPERTY_RECOVERY_SIZE_LIMIT) + "m");
} catch (NumberFormatException e) {
throw new DatabaseConfigurationException("size attribute in recovery section needs to be a number");
}
}
option = recovery.getAttribute(TransactionManager.RECOVERY_FORCE_RESTART_ATTRIBUTE);
boolean value = false;
if (option != null) {
value = option.equals("yes");
}
setProperty(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART, new Boolean(value));
LOG.debug(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART + ": " + config.get(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART));
option = recovery.getAttribute(BrokerPool.RECOVERY_POST_RECOVERY_CHECK);
value = false;
if (option != null) {
value = option.equals("yes");
}
setProperty(BrokerPool.PROPERTY_RECOVERY_CHECK, new Boolean(value));
LOG.debug(BrokerPool.PROPERTY_RECOVERY_CHECK + ": " + config.get(BrokerPool.PROPERTY_RECOVERY_CHECK));
}
private void configurePermissions(Element defaultPermission) throws DatabaseConfigurationException {
String option = defaultPermission.getAttribute(XMLSecurityManager.COLLECTION_ATTRIBUTE);
if (option != null && option.length() > 0) {
try {
Integer perms = new Integer(Integer.parseInt(option, 8));
setProperty(XMLSecurityManager.PROPERTY_PERMISSIONS_COLLECTIONS, perms);
LOG.debug(XMLSecurityManager.PROPERTY_PERMISSIONS_COLLECTIONS + ": " + config.get(XMLSecurityManager.PROPERTY_PERMISSIONS_COLLECTIONS));
} catch (NumberFormatException e) {
throw new DatabaseConfigurationException("collection attribute in default-permissions section needs " +
"to be an octal number");
}
}
option = defaultPermission.getAttribute(XMLSecurityManager.RESOURCE_ATTRIBUTE);
if (option != null && option.length() > 0) {
try {
Integer perms = new Integer(Integer.parseInt(option, 8));
setProperty(XMLSecurityManager.PROPERTY_PERMISSIONS_RESOURCES, perms);
LOG.debug(XMLSecurityManager.PROPERTY_PERMISSIONS_RESOURCES + ": " + config.get(XMLSecurityManager.PROPERTY_PERMISSIONS_RESOURCES));
} catch (NumberFormatException e) {
throw new DatabaseConfigurationException("resource attribute in default-permissions section needs " +
"to be an octal number");
}
}
}
/**
* @param watchDog
*/
private void configureWatchdog(Element watchDog) {
String timeout = watchDog.getAttribute("query-timeout");
if (timeout != null) {
try {
config.put(XQueryWatchDog.PROPERTY_QUERY_TIMEOUT, new Long(timeout));
LOG.debug(XQueryWatchDog.PROPERTY_QUERY_TIMEOUT + ": " + config.get(XQueryWatchDog.PROPERTY_QUERY_TIMEOUT));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String maxOutput = watchDog.getAttribute("output-size-limit");
if (maxOutput != null) {
try {
config.put(XQueryWatchDog.PROPERTY_OUTPUT_SIZE_LIMIT, new Integer(maxOutput));
LOG.debug(XQueryWatchDog.PROPERTY_OUTPUT_SIZE_LIMIT + ": " + config.get(XQueryWatchDog.PROPERTY_OUTPUT_SIZE_LIMIT));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
}
/**
* @param queryPool
*/
private void configureXQueryPool(Element queryPool) {
String maxStackSize = queryPool.getAttribute(XQueryPool.MAX_STACK_SIZE_ATTRIBUTE);
if (maxStackSize != null) {
try {
config.put(XQueryPool.PROPERTY_MAX_STACK_SIZE, new Integer(maxStackSize));
LOG.debug(XQueryPool.PROPERTY_MAX_STACK_SIZE + ": " + config.get(XQueryPool.PROPERTY_MAX_STACK_SIZE));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String maxPoolSize = queryPool.getAttribute(XQueryPool.POOL_SIZE_ATTTRIBUTE);
if (maxPoolSize != null) {
try {
config.put(XQueryPool.PROPERTY_POOL_SIZE, new Integer(maxPoolSize));
LOG.debug(XQueryPool.PROPERTY_POOL_SIZE + ": " + config.get(XQueryPool.PROPERTY_POOL_SIZE));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String timeout = queryPool.getAttribute(XQueryPool.TIMEOUT_ATTRIBUTE);
if (timeout != null) {
try {
config.put(XQueryPool.PROPERTY_TIMEOUT, new Long(timeout));
LOG.debug(XQueryPool.PROPERTY_TIMEOUT + ": " + config.get(XQueryPool.PROPERTY_TIMEOUT));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String timeoutCheckInterval = queryPool.getAttribute(XQueryPool.TIMEOUT_CHECK_INTERVAL_ATTRIBUTE);
if (timeoutCheckInterval != null) {
try {
config.put(XQueryPool.PROPERTY_TIMEOUT_CHECK_INTERVAL, new Long(timeoutCheckInterval));
LOG.debug(XQueryPool.PROPERTY_TIMEOUT_CHECK_INTERVAL + ": " + config.get(XQueryPool.PROPERTY_TIMEOUT_CHECK_INTERVAL));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
}
/**
* @param pool
*/
private void configurePool(Element pool) {
String min = pool.getAttribute(BrokerPool.MIN_CONNECTIONS_ATTRIBUTE);
if (min != null) {
try {
config.put(BrokerPool.PROPERTY_MIN_CONNECTIONS, new Integer(min));
LOG.debug(BrokerPool.PROPERTY_MIN_CONNECTIONS + ": " + config.get(BrokerPool.PROPERTY_MIN_CONNECTIONS));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String max = pool.getAttribute(BrokerPool.MAX_CONNECTIONS_ATTRIBUTE);
if (max != null) {
try {
config.put(BrokerPool.PROPERTY_MAX_CONNECTIONS, new Integer(max));
LOG.debug(BrokerPool.PROPERTY_MAX_CONNECTIONS + ": " + config.get(BrokerPool.PROPERTY_MAX_CONNECTIONS));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String sync = pool.getAttribute(BrokerPool.SYNC_PERIOD_ATTRIBUTE);
if (sync != null) {
try {
config.put(BrokerPool.PROPERTY_SYNC_PERIOD, new Long(sync));
LOG.debug(BrokerPool.PROPERTY_SYNC_PERIOD + ": " + config.get(BrokerPool.PROPERTY_SYNC_PERIOD));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String maxShutdownWait = pool.getAttribute(BrokerPool.SHUTDOWN_DELAY_ATTRIBUTE);
if (maxShutdownWait != null) {
try {
config.put(BrokerPool.PROPERTY_SHUTDOWN_DELAY, new Long(maxShutdownWait));
LOG.debug(BrokerPool.PROPERTY_SHUTDOWN_DELAY + ": " + config.get(BrokerPool.PROPERTY_SHUTDOWN_DELAY));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
}
/**
* @param dbHome
* @param doc
* @param indexer
* @throws DatabaseConfigurationException
* @throws MalformedURLException
* @throws IOException
*/
private void configureIndexer(String dbHome, Document doc, Element indexer) throws DatabaseConfigurationException, MalformedURLException {
String parseNum = indexer.getAttribute(TextSearchEngine.INDEX_NUMBERS_ATTRIBUTE);
if (parseNum != null) {
config.put(TextSearchEngine.PROPERTY_INDEX_NUMBERS, parseBoolean(parseNum, false));
LOG.debug(TextSearchEngine.PROPERTY_INDEX_NUMBERS + ": " + config.get(TextSearchEngine.PROPERTY_INDEX_NUMBERS));
}
String stemming = indexer.getAttribute(TextSearchEngine.STEM_ATTRIBUTE);
if (stemming != null) {
config.put(TextSearchEngine.PROPERTY_STEM, parseBoolean(stemming, false));
LOG.debug(TextSearchEngine.PROPERTY_STEM + ": " + config.get(TextSearchEngine.PROPERTY_STEM));
}
String termFreq = indexer.getAttribute(TextSearchEngine.STORE_TERM_FREQUENCY_ATTRIBUTE);
if (termFreq != null) {
config.put(TextSearchEngine.PROPERTY_STORE_TERM_FREQUENCY, parseBoolean(termFreq, false));
LOG.debug(TextSearchEngine.PROPERTY_STORE_TERM_FREQUENCY + ": " + config.get(TextSearchEngine.PROPERTY_STORE_TERM_FREQUENCY));
}
String tokenizer = indexer.getAttribute(TextSearchEngine.TOKENIZER_ATTRIBUTE);
if (tokenizer != null) {
config.put(TextSearchEngine.PROPERTY_TOKENIZER, tokenizer);
LOG.debug(TextSearchEngine.PROPERTY_TOKENIZER + ": " + config.get(TextSearchEngine.PROPERTY_TOKENIZER));
}
String caseSensitive = indexer.getAttribute(NativeValueIndex.INDEX_CASE_SENSITIVE_ATTRIBUTE);
if (caseSensitive != null) {
config.put(NativeValueIndex.PROPERTY_INDEX_CASE_SENSITIVE, parseBoolean(caseSensitive, false));
LOG.debug(NativeValueIndex.PROPERTY_INDEX_CASE_SENSITIVE + ": " + config.get(NativeValueIndex.PROPERTY_INDEX_CASE_SENSITIVE));
}
// stopwords
NodeList stopwords = indexer.getElementsByTagName(TextSearchEngine.CONFIGURATION_STOPWORDS_ELEMENT_NAME);
if (stopwords.getLength() > 0) {
String stopwordFile = ((Element) stopwords.item(0)).getAttribute(TextSearchEngine.STOPWORD_FILE_ATTRIBUTE);
File sf = ConfigurationHelper.lookup(stopwordFile, dbHome);
if (sf.canRead()) {
config.put(TextSearchEngine.PROPERTY_STOPWORD_FILE, stopwordFile);
LOG.debug(TextSearchEngine.PROPERTY_STOPWORD_FILE + ": " + config.get(TextSearchEngine.PROPERTY_STOPWORD_FILE));
}
}
int depth = 3;
String indexDepth = indexer.getAttribute(NativeBroker.INDEX_DEPTH_ATTRIBUTE);
if (indexDepth != null) {
try {
depth = Integer.parseInt(indexDepth);
if (depth < 3) {
LOG.warn("parameter index-depth should be >= 3 or you will experience a severe " +
"performance loss for node updates (XUpdate or XQuery update extensions)");
depth = 3;
}
config.put(NativeBroker.PROPERTY_INDEX_DEPTH, new Integer(depth));
LOG.debug(NativeBroker.PROPERTY_INDEX_DEPTH + ": " + config.get(NativeBroker.PROPERTY_INDEX_DEPTH));
} catch (NumberFormatException e) {
LOG.warn(e);
}
}
String suppressWS = indexer.getAttribute(Indexer.SUPPRESS_WHITESPACE_ATTRIBUTE);
if (suppressWS != null) {
config.put(Indexer.PROPERTY_SUPPRESS_WHITESPACE, suppressWS);
LOG.debug(Indexer.PROPERTY_SUPPRESS_WHITESPACE + ": " + config.get(Indexer.PROPERTY_SUPPRESS_WHITESPACE));
}
String suppressWSmixed = indexer.getAttribute(Indexer.PRESERVE_WS_MIXED_CONTENT_ATTRIBUTE);
if (suppressWSmixed != null) {
config.put(Indexer.PROPERTY_PRESERVE_WS_MIXED_CONTENT, parseBoolean(suppressWSmixed, false));
LOG.debug(Indexer.PROPERTY_PRESERVE_WS_MIXED_CONTENT + ": " + config.get(Indexer.PROPERTY_PRESERVE_WS_MIXED_CONTENT));
}
// index settings
NodeList cl = doc.getElementsByTagName(Indexer.CONFIGURATION_INDEX_ELEMENT_NAME);
if (cl.getLength() > 0) {
Element elem = (Element) cl.item(0);
IndexSpec spec = new IndexSpec(null, elem);
config.put(Indexer.PROPERTY_INDEXER_CONFIG, spec);
//LOG.debug(Indexer.PROPERTY_INDEXER_CONFIG + ": " + config.get(Indexer.PROPERTY_INDEXER_CONFIG));
}
// index modules
NodeList modules = indexer.getElementsByTagName(IndexManager.CONFIGURATION_ELEMENT_NAME);
if (modules.getLength() > 0) {
modules = ((Element) modules.item(0)).getElementsByTagName(IndexManager.CONFIGURATION_MODULE_ELEMENT_NAME);
IndexModuleConfig modConfig[] = new IndexModuleConfig[modules.getLength()];
for (int i = 0; i < modules.getLength(); i++) {
Element elem = (Element) modules.item(i);
String className = elem.getAttribute(IndexManager.INDEXER_MODULES_CLASS_ATTRIBUTE);
String id = elem.getAttribute(IndexManager.INDEXER_MODULES_ID_ATTRIBUTE);
if (className == null || className.length() == 0)
throw new DatabaseConfigurationException("Required attribute class is missing for module");
if (id == null || id.length() == 0)
throw new DatabaseConfigurationException("Required attribute id is missing for module");
modConfig[i] = new IndexModuleConfig(id, className, elem);
}
config.put(IndexManager.PROPERTY_INDEXER_MODULES, modConfig);
}
}
private void configureValidation(String dbHome, Document doc, Element validation)
throws DatabaseConfigurationException {
// Register custom protocol URL
// TODO DWES move to different location?
eXistURLStreamHandlerFactory.init();
// Determine validation mode
String mode = validation.getAttribute(XMLReaderObjectFactory.VALIDATION_MODE_ATTRIBUTE);
if (mode != null) {
config.put(XMLReaderObjectFactory.PROPERTY_VALIDATION_MODE, mode);
LOG.debug(XMLReaderObjectFactory.PROPERTY_VALIDATION_MODE + ": "
+ config.get(XMLReaderObjectFactory.PROPERTY_VALIDATION_MODE));
}
// Extract catalogs
LOG.debug("Creating eXist catalog resolver");
eXistXMLCatalogResolver resolver = new eXistXMLCatalogResolver();
NodeList entityResolver = validation.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_ENTITY_RESOLVER_ELEMENT_NAME);
if (entityResolver.getLength() > 0) {
Element r = (Element) entityResolver.item(0);
NodeList catalogs = r.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_CATALOG_ELEMENT_NAME);
LOG.debug("Found "+catalogs.getLength()+" catalog uri entries.");
LOG.debug("Using dbHome="+dbHome);
// Determine webapps directory. SingleInstanceConfiguration cannot
// be used at this phase. Trick is to check wether dbHOME is
// pointing to a WEB-INF directory, meaning inside war file)
File webappHome=null;
if(dbHome==null){ /// DWES Why? let's make jUnit happy
webappHome=new File("webapp").getAbsoluteFile();
} else if(dbHome.endsWith("WEB-INF")){
webappHome = new File(dbHome).getParentFile().getAbsoluteFile();
} else {
webappHome = new File(dbHome, "webapp").getAbsoluteFile();
}
LOG.debug("using webappHome="+webappHome.toURI().toString());
// Get and store all URIs
List allURIs= new ArrayList();
for (int i = 0; i < catalogs.getLength(); i++) {
String uri = ((Element) catalogs.item(i)).getAttribute("uri");
if(uri!=null){ // when uri attribute is filled in
// Substitute string, creating an uri from a local file
if(uri.indexOf("${WEBAPP_HOME}")!=-1){
uri=uri.replaceAll("\\$\\{WEBAPP_HOME\\}", webappHome.toURI().toString() );
}
// Add uri to confiuration
LOG.info("Add catalog uri "+uri+"");
allURIs.add(uri);
}
}
resolver.setCatalogs(allURIs);
// Store all configured URIs
config.put(XMLReaderObjectFactory.CATALOG_URIS, allURIs);
}
// Store resolver
config.put(XMLReaderObjectFactory.CATALOG_RESOLVER, resolver);
// cache
GrammarPool gp = new GrammarPool();
config.put(XMLReaderObjectFactory.GRAMMER_POOL, gp);
}
public String getConfigFilePath() {
return configFilePath;
}
public File getExistHome() {
return existHome;
}
public Object getProperty(String name) {
return config.get(name);
}
public Object getProperty(String name, Object defaultValue) {
Object value = config.get(name);
if(value == null) {
return defaultValue;
}
return value;
}
public boolean hasProperty(String name) {
return config.containsKey(name);
}
public void setProperty(String name, Object obj) {
config.put(name, obj);
}
/**
* Takes the passed string and converts it to a non-null
* <code>Boolean</code> object. If value is null, the specified
* default value is used. Otherwise, Boolean.TRUE is returned if
* and only if the passed string equals "yes" or
* "true", ignoring case.
*
* @param value The string to parse
* @param defaultValue The default if the string is null
* @return The parsed <code>Boolean</code>
*/
public static Boolean parseBoolean(String value, boolean defaultValue) {
if(value == null)
return Boolean.valueOf(defaultValue);
return Boolean.valueOf("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value));
}
public int getInteger(String name) {
Object obj = getProperty(name);
if ((obj == null) || !(obj instanceof Integer))
return -1;
return ((Integer) obj).intValue();
}
/**
* (non-Javadoc)
*
* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
*/
public void error(SAXParseException exception) throws SAXException {
System.err.println("error occured while reading configuration file "
+ "[line: " + exception.getLineNumber() + "]:"
+ exception.getMessage());
}
/**
* (non-Javadoc)
*
* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
*/
public void fatalError(SAXParseException exception) throws SAXException {
System.err.println("error occured while reading configuration file "
+ "[line: " + exception.getLineNumber() + "]:"
+ exception.getMessage());
}
/**
* (non-Javadoc)
*
* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
*/
public void warning(SAXParseException exception) throws SAXException {
System.err.println("error occured while reading configuration file "
+ "[line: " + exception.getLineNumber() + "]:"
+ exception.getMessage());
}
}