[jbosscache-commits] JBoss Cache SVN: r6888 - in core/branches/flat/src/main/java/org/jboss/starobrno/config: parsing and 1 other directories.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Wed Oct 8 12:37:44 EDT 2008
Author: manik.surtani at jboss.com
Date: 2008-10-08 12:37:44 -0400 (Wed, 08 Oct 2008)
New Revision: 6888
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/CacheConfigsXmlParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ConfigFilesConvertor.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/JGroupsStackParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ParsedAttributes.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigHelper.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlParserBase.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/BuddyElementParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/CustomInterceptorsElementParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/EvictionElementParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/LoadersElementParser.java
Log:
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/CacheConfigsXmlParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/CacheConfigsXmlParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/CacheConfigsXmlParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,140 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.util.FileLookup;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Parser able to parse a series of cache configurations stored in an
+ * XML document with the following structure:
+ * <pre>
+ * <cache-configs>
+ * <cache-config name="configA">
+ * ....
+ * </cache-config>
+ * <cache-config name="configB">
+ * ....
+ * </cache-config>
+ * </cache-configs>
+ * </pre>
+ * <p/>
+ * The '....' represents the normal content of the mbean element in a
+ * JBC -service.xml config file.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class CacheConfigsXmlParser
+{
+ /**
+ * Name of the root element in a cache configs XML document
+ */
+ public static final String DOCUMENT_ROOT = "cache-configs";
+ /**
+ * Name of the element that represents an individual cache configuration
+ * in a cache configs XML document.
+ */
+ public static final String CONFIG_ROOT = "cache-config";
+ public static final String QUALIFIED_CONFIG_ROOT = "registry:cache-config";
+
+ /**
+ * Name of the attribute in a {@link #CONFIG_ROOT cache-config} element that specifies
+ * the name of the configuration.
+ */
+ public static final String CONFIG_NAME = "name";
+
+ private static final Log log = LogFactory.getLog(CacheConfigsXmlParser.class);
+
+
+ public Map<String, Configuration> parseConfigs(String fileName) throws CloneNotSupportedException
+ {
+ FileLookup fileLookup = new FileLookup();
+ InputStream is = fileLookup.lookupFile(fileName);
+ if (is == null)
+ {
+ throw new ConfigurationException("Unable to find config file " + fileName + " either in classpath or on the filesystem!");
+ }
+
+ return parseConfigs(is);
+ }
+
+ public Map<String, Configuration> parseConfigs(InputStream stream) throws CloneNotSupportedException
+ {
+ // loop through all elements in XML.
+ Element root = getDocumentRoot(stream);
+
+ NodeList list = root.getElementsByTagName(CONFIG_ROOT);
+ if (list == null || list.getLength() == 0)
+ {
+ // try looking for a QUALIFIED_CONFIG_ROOT
+ list = root.getElementsByTagName(QUALIFIED_CONFIG_ROOT);
+ if (list == null || list.getLength() == 0)
+ throw new ConfigurationException("Can't find " + CONFIG_ROOT + " or " + QUALIFIED_CONFIG_ROOT + " tag");
+ }
+
+ Map<String, Configuration> result = new HashMap<String, Configuration>();
+
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node node = list.item(i);
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ {
+ continue;
+ }
+
+ Element element = (Element) node;
+ String name = element.getAttribute(CONFIG_NAME);
+ if (name == null || name.trim().length() == 0)
+ throw new ConfigurationException("Element " + element + " has no name attribute");
+
+ XmlConfigurationParser parser = new XmlConfigurationParser();
+ Configuration c = null;
+ if (parser.isValidElementRoot(element))
+ {
+ c = parser.parseElementIgnoringRoot(element);
+ }
+
+ // Prove that we can successfully clone it
+ c = c.clone();
+ result.put(name.trim(), c);
+ }
+
+ return result;
+ }
+
+ private Element getDocumentRoot(InputStream stream)
+ {
+ RootElementBuilder rootElementBuilder = new RootElementBuilder(false);
+ return rootElementBuilder.readRoot(stream);
+ }
+}
\ No newline at end of file
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/CacheConfigsXmlParser.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ConfigFilesConvertor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ConfigFilesConvertor.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ConfigFilesConvertor.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,139 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.jboss.cache.util.FileLookup;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Class used for converting a config file from from 2.x version to 3.x verison.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class ConfigFilesConvertor
+{
+ /**
+ * Writes to the <b>os</b> the 3.x configuration file resulted by transforming the 2.x configuration file passed in
+ * as <b>is</b>. Transformation is performed according to the <b>xsltFile</b>. The xslt file is looked up using a
+ * {@link org.jboss.cache.util.FileLookup}
+ */
+ public void parse(InputStream is, OutputStream os, String xsltFile) throws Exception
+ {
+ InputStream xsltInStream = new FileLookup().lookupFile(xsltFile);
+
+ Document document = getInputDocument(is);
+
+ // Use a Transformer for output
+ Transformer transformer = getTransformer(xsltInStream);
+
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(os);
+ transformer.transform(source, result);
+ xsltInStream.close();
+ }
+
+ /**
+ * Writes to the <b>os</b> the 3.x configuration file resulted by transforming the 2.x configuration file passed in
+ * as <b>inputFile</b>. Transformation is performed according to the <b>xsltFile</b>. Both <b>inputFile</b> and he xslt
+ * file are looked up using a {@link org.jboss.cache.util.FileLookup}
+ */
+ public void parse(String inputFile, OutputStream os, String xsltFile) throws Exception
+ {
+ InputStream stream = new FileLookup().lookupFile(inputFile);
+ try
+ {
+ parse(stream, os, xsltFile);
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
+ /**
+ * usage : java org.jboss.cache.config.parsing.ConfigFilesConvertor -Dsource=config-2.x.xml -Ddestination=config-3.x.xnl
+ */
+ public static void main(String[] argv) throws Exception
+ {
+ String sourceName = System.getProperty("source");
+ if (sourceName == null)
+ {
+ System.err.println("Missing property 'source'.");
+ System.exit(1);
+ }
+ String destinationName = System.getProperty("destination");
+ if (destinationName == null)
+ {
+ System.err.println("Missing property 'destination'.");
+ System.exit(1);
+ }
+ File oldConfig = new File(sourceName);
+ if (!oldConfig.exists())
+ {
+ System.err.println("File specified as input ('" + sourceName + ") does not exist.");
+ System.exit(1);
+ }
+ ConfigFilesConvertor convertor = new ConfigFilesConvertor();
+ File destination = new File(destinationName);
+ if (!destination.exists()) destination.createNewFile();
+
+ FileInputStream is = new FileInputStream(oldConfig);
+ FileOutputStream fos = new FileOutputStream(destinationName);
+ convertor.parse(is, fos, "config2to3.xslt");
+ is.close();
+ System.out.println("File successfully created.");
+ }
+
+ private Transformer getTransformer(InputStream xsltInStream)
+ throws TransformerConfigurationException
+ {
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ StreamSource stylesource = new StreamSource(xsltInStream);
+ return tFactory.newTransformer(stylesource);
+ }
+
+ private Document getInputDocument(InputStream is)
+ throws ParserConfigurationException, SAXException, IOException
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ return builder.parse(is);
+ }
+}
\ No newline at end of file
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/JGroupsStackParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/JGroupsStackParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/JGroupsStackParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,107 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+/**
+ * The purpose of this class is to parse the jgroups configuration from the config file into an compact string
+ * that can be passed as a config to the channel.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class JGroupsStackParser
+{
+ /**
+ * Parses the cluster config which is used to start a JGroups channel
+ *
+ * @param config an old-style JGroups protocol config String
+ */
+ public String parseClusterConfigXml(Element config)
+ {
+ StringBuilder buffer = new StringBuilder();
+ NodeList stack = config.getChildNodes();
+ int length = stack.getLength();
+
+ for (int s = 0; s < length; s++)
+ {
+ org.w3c.dom.Node node = stack.item(s);
+ if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+ {
+ continue;
+ }
+
+ // Ignore Namespace until JGroups defines one
+ Element tag = (Element) node;
+ String protocol = tag.getLocalName();
+ if (protocol == null)
+ {
+ protocol = tag.getNodeName(); // try a non-namespace aware version
+ }
+ buffer.append(protocol);
+ processAttributes(buffer, tag);
+ buffer.append(':');
+ }
+ if (buffer.length() > 0)
+ {
+ //Remove the trailing ':'
+ buffer.setLength(buffer.length() - 1);
+ }
+ return buffer.toString();
+ }
+
+ private void processAttributes(StringBuilder buffer, Element tag)
+ {
+ NamedNodeMap attrs = tag.getAttributes();
+ int attrLength = attrs.getLength();
+ if (attrLength > 0)
+ {
+ buffer.append('(');
+ }
+ for (int a = 0; a < attrLength; a++)
+ {
+ Attr attr = (Attr) attrs.item(a);
+ processSingleAttribute(buffer, attr);
+ if (a < attrLength - 1)
+ {
+ buffer.append(';');
+ }
+ }
+ if (attrLength > 0)
+ {
+ buffer.append(')');
+ }
+ }
+
+ private void processSingleAttribute(StringBuilder buffer, Attr attr)
+ {
+ String name = attr.getName();
+ String value = attr.getValue();
+ buffer.append(name);
+ buffer.append('=');
+ buffer.append(value);
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ParsedAttributes.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ParsedAttributes.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/ParsedAttributes.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.w3c.dom.Element;
+
+import java.util.Map;
+
+/**
+ * Helper class for holding attributes defined in configuration file.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class ParsedAttributes
+{
+ public final Map<String, String> stringAttribs;
+ public final Map<String, Element> xmlAttribs;
+
+ ParsedAttributes(Map strings, Map elements)
+ {
+ this.stringAttribs = strings;
+ this.xmlAttribs = elements;
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/RootElementBuilder.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.util.xml.JBossEntityResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.InputStream;
+
+/**
+ * Parses an xml files and validates xml elements form {@link RootElementBuilder#JBOSSCACHE_CORE_NS} namespace
+ * according to the configured schema.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class RootElementBuilder
+{
+
+ private static final JBossEntityResolver resolver = new JBossEntityResolver();
+
+ public static final String JBOSSCACHE_CORE_NS = "urn:jboss:jbosscache-core:config:3.0";
+ public static final String JBOSSCACHE_REPO_NS = "urn:jboss:jbosscache-core:cache-repo:3.0";
+
+ static
+ {
+ // Globally register this namespace
+ JBossEntityResolver.registerEntity(JBOSSCACHE_CORE_NS, "jbosscache-config-3.0.xsd");
+ JBossEntityResolver.registerEntity(JBOSSCACHE_REPO_NS, "jbosscache-registry-3.0.xsd");
+ }
+
+ private static final Log log = LogFactory.getLog(RootElementBuilder.class);
+ private ErrorHandler errorHandler;
+ private boolean isValidating;
+ public static final String VALIDATING_SYSTEM_PROPERTY = "jbosscache.config.validate";
+
+ public RootElementBuilder(ErrorHandler errorHandler)
+ {
+ this.errorHandler = errorHandler;
+ isValidating = System.getProperty(VALIDATING_SYSTEM_PROPERTY) == null || Boolean.getBoolean(VALIDATING_SYSTEM_PROPERTY);
+ }
+
+ public RootElementBuilder(ErrorHandler errorHandler, boolean validating)
+ {
+ this.errorHandler = errorHandler;
+ isValidating = validating;
+ }
+
+ public RootElementBuilder()
+ {
+ this(new FailureErrorHandler());
+ }
+
+ public RootElementBuilder(boolean validating)
+ {
+ this(new FailureErrorHandler(), validating);
+ }
+
+ public Element readRoot(InputStream config)
+ {
+ try
+ {
+ DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+ docBuilderFactory.setNamespaceAware(true);
+ if (isValidating)
+ {
+ docBuilderFactory.setValidating(true);
+ docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
+ String[] value = {JBOSSCACHE_CORE_NS, JBOSSCACHE_REPO_NS};
+ docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", value);
+ }
+ DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
+ parser.setEntityResolver(resolver);
+ parser.setErrorHandler(errorHandler);
+ Document doc = parser.parse(config);
+ Element root = doc.getDocumentElement();
+ root.normalize();
+ return root;
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ throw new ConfigurationException("Could not parse the config file");
+ }
+ }
+
+ /**
+ * Default schema validation error handler, that throws an exception on validation errors.
+ */
+ private static class FailureErrorHandler implements ErrorHandler
+ {
+ public void warning(SAXParseException exception) throws SAXException
+ {
+ logAndThrowException(exception);
+ }
+
+ public void error(SAXParseException exception) throws SAXException
+ {
+ logAndThrowException(exception);
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException
+ {
+ logAndThrowException(exception);
+ }
+
+ private void logAndThrowException(SAXParseException exception)
+ {
+ log.error("Configuration warning: " + exception.getMessage());
+ throw new ConfigurationException("Incorrect configuration file. Use '-Djbosscache.config.validate=false' to disable validation.", exception);
+ }
+ }
+
+ public boolean isValidating()
+ {
+ return isValidating;
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigHelper.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigHelper.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigHelper.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,616 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.util.BeanUtils;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.util.StringPropertyReplacer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorManager;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * A simple XML utility class for reading configuration elements
+ *
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
+ */
+public class XmlConfigHelper
+{
+ private static final Log log = LogFactory.getLog(XmlConfigHelper.class);
+
+ /**
+ * The root of a JBoss Cache configuration XML file. This is the <tt><mbean></tt> tag.
+ */
+ public static final String ROOT = "mbean";
+
+ /**
+ * The <tt><attribute></tt> tag which forms the bulk of JBoss Cache configuration elements
+ */
+ public static final String ATTR = "attribute";
+
+ /**
+ * The <tt><config></tt> tag may be embedded in the contents of an <tt><attribute></tt>, to specify more
+ * complex configuration for certain parameters.
+ */
+ public static final String CONFIG_ATTR = "config";
+
+ /**
+ * The <tt><name></tt> attribute to an <tt><attribute></tt> tag.
+ */
+ public static final String NAME = "name";
+
+
+ /**
+ * Returns the contents of a specific node of given element name, provided a certain attribute exists and is set to value.
+ * E.g., if you have a {@link Element} which represents the following XML snippet:
+ * <pre>
+ * <ItemQuantity Colour="Red">100</ItemQuantity>
+ * <ItemQuantity Colour="Blue">30</ItemQuantity>
+ * <ItemQuantity Colour="Black">10</ItemQuantity>
+ * <pre>
+ * <p/>
+ * The following results could be expected:
+ * </p>
+ * <pre>
+ * getTagContents(element, "Red", "ItemQuantity", "Colour"); // 100
+ * getTagContents(element, "Black", "ItemQuantity", "Colour"); // 10
+ * getTagContents(element, "Blah", "ItemQuantity", "Colour"); // null
+ * getTagContents(element, "Red", "Blah", "Colour"); // null
+ * getTagContents(element, "Black", "ItemQuantity", "Blah"); // null
+ * </pre>
+ * <p/>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ * </p>
+ *
+ * @param elem - element to search through.
+ * @param value - expected value to match against
+ * @param elementName - element name
+ * @param attributeName - attribute name of the element that would contain the expected value.
+ * @return the contents of the matched element, or null if not found/matched
+ */
+ public static String getTagContents(Element elem, String value, String elementName, String attributeName)
+ {
+ NodeList list = elem.getElementsByTagName(elementName);
+
+ for (int s = 0; s < list.getLength(); s++)
+ {
+ org.w3c.dom.Node node = list.item(s);
+ if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+ continue;
+
+ Element element = (Element) node;
+ String name = element.getAttribute(attributeName);
+ if (name.equals(value))
+ {
+ return getElementContent(element, true);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves the value of a given attribute for the first encountered instance of a tag in an element.
+ * <p/>
+ * E.g., if you have a {@link Element} which represents the following XML snippet:
+ * </p>
+ * <pre>
+ * <ItemQuantity Colour="Red">100</ItemQuantity>
+ * <ItemQuantity Colour="Blue">30</ItemQuantity>
+ * <ItemQuantity Colour="Black">10</ItemQuantity>
+ * <pre>
+ * <p/>
+ * The following results could be expected:
+ * </p>
+ * <pre>
+ * getAttributeValue(element, "ItemQuantity", "Colour"); // "Red"
+ * getTagContents(element, "Blah", "Colour"); // null
+ * getTagContents(element, "ItemQuantity", "Blah"); // null
+ * </pre>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ *
+ * @param elem - element to search through.
+ * @param elementName - element name
+ * @param attributeName - attribute name of the element that would contain the expected value.
+ * @return the contents of the matched attribute, or null if not found/matched
+ */
+ public static String getAttributeValue(Element elem, String elementName, String attributeName)
+ {
+ NodeList list = elem.getElementsByTagName(elementName);
+
+ for (int s = 0; s < list.getLength(); s++)
+ {
+ org.w3c.dom.Node node = list.item(s);
+ if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+ continue;
+
+ Element element = (Element) node;
+ String value = element.getAttribute(attributeName);
+ return value == null ? null : StringPropertyReplacer.replaceProperties(value);
+
+ }
+ return null;
+ }
+
+ /**
+ * Returns a named sub-element of the current element passed in.
+ * <p/>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ *
+ * @param element - element to search through.
+ * @param subElementName - the name of a sub element to look for
+ * @return the first matching sub element, if found, or null otherwise.
+ */
+ public static Element getSubElement(Element element, String subElementName)
+ {
+ NodeList nl = element.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++)
+ {
+ Node node = nl.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE && subElementName.equals(((Element) node).getTagName()))
+ {
+ return (Element) node;
+ }
+ }
+
+ if (log.isDebugEnabled()) log.debug("getSubElement(): Does not exist for " + subElementName);
+ return null;
+ }
+
+ /**
+ * Reads the contents of the element passed in.
+ * <p/>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ *
+ * @param element - element to search through.
+ * @param trim - if true, whitespace is trimmed before returning
+ * @return the contents of the element passed in. Will return an empty String if the element is empty.
+ */
+ public static String getElementContent(Element element, boolean trim)
+ {
+ NodeList nl = element.getChildNodes();
+ String attributeText = "";
+ for (int i = 0; i < nl.getLength(); i++)
+ {
+ Node n = nl.item(i);
+ if (n instanceof Text)
+ {
+ attributeText += StringPropertyReplacer.replaceProperties(((Text) n).getData());
+ }
+ } // end of for ()
+ if (trim)
+ attributeText = attributeText.trim();
+ return attributeText;
+ }
+
+ /**
+ * Reads the contents of the first occurence of elementName under the given element, trimming results of whitespace.
+ * <p/>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ *
+ * @param element - element to search through.
+ * @param elementName - name of the element to find within the element passed in
+ * @return may return an empty String of not found.
+ */
+ public static String readStringContents(Element element, String elementName)
+ {
+ NodeList nodes = element.getElementsByTagName(elementName);
+ if (nodes.getLength() > 0)
+ {
+ Node node = nodes.item(0);
+ Element ne = (Element) node;
+ NodeList nl2 = ne.getChildNodes();
+ Node node2 = nl2.item(0);
+ if (node2 != null)
+ {
+ String value = node2.getNodeValue();
+ if (value == null)
+ return "";
+ return StringPropertyReplacer.replaceProperties(value.trim());
+ }
+ else
+ {
+ return "";
+ }
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Escapes backslashes ('\') with additional backslashes in a given String, returning a new, escaped String.
+ *
+ * @param value String to escape. Cannot be null.
+ * @return escaped String. Never is null.
+ */
+ public static String escapeBackslashes(String value)
+ {
+ StringBuilder buf = new StringBuilder(value);
+ for (int looper = 0; looper < buf.length(); looper++)
+ {
+ char curr = buf.charAt(looper);
+ char next = 0;
+ if (looper + 1 < buf.length())
+ next = buf.charAt(looper + 1);
+
+ if (curr == '\\')
+ {
+ if (next != '\\')
+ { // only if not already escaped
+ buf.insert(looper, '\\'); // escape backslash
+ }
+ looper++; // skip past extra backslash (either the one we added or existing)
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Reads the contents of a named sub element within a given element, and attempts to parse the contents as a Java
+ * properties file.
+ * <p/>
+ * E.g., if you have a {@link Element} which represents the following XML snippet:
+ * <p/>
+ * <pre>
+ * <props>
+ * my.attrib.1 = blah
+ * my.attrib.2 = blahblah
+ * </props>
+ * <pre>
+ * <p/>
+ * The following results could be expected:
+ * <p/>
+ * <pre>
+ * Properties p = readPropertiesContents(element, "props");
+ * p.getProperty("my.attrib.1"); // blah
+ * p.getProperty("my.attrib.2"); // blahblah
+ * </pre>
+ * None of the parameters should be null - otherwise the method may throw a NullPointerException.
+ *
+ * @param element - element to search through.
+ * @param elementName - name of the element to find within the element passed in
+ * @return a {@link Properties} object, never null.
+ * @throws IOException if unable to parse the contents of the element
+ */
+ public static Properties readPropertiesContents(Element element, String elementName)
+ {
+ String stringContents = readStringContents(element, elementName);
+ if (stringContents == null) return new Properties();
+ // JBCACHE-531: escape all backslash characters
+ stringContents = escapeBackslashes(stringContents);
+ ByteArrayInputStream is = null;
+ Properties properties = null;
+ try
+ {
+ is = new ByteArrayInputStream(stringContents.trim().getBytes("ISO8859_1"));
+ properties = new Properties();
+ properties.load(is);
+ is.close();
+ }
+ catch (IOException e)
+ {
+ log.warn("Unexpected", e);
+ throw new ConfigurationException("Exception occured while reading properties from XML document", e);
+ }
+ return properties;
+ }
+
+ /**
+ * Similar to {@link #readStringContents(org.w3c.dom.Element,String)} except that it returns a boolean.
+ *
+ * @param element - element to search through.
+ * @param elementName - name of the element to find within the element passed in
+ * @return the contents of the element as a boolean, or false if not found.
+ */
+ public static boolean readBooleanContents(Element element, String elementName)
+ {
+ return readBooleanContents(element, elementName, false);
+ }
+
+ /**
+ * Similar to {@link #readStringContents(org.w3c.dom.Element,String)} except that it returns a boolean.
+ *
+ * @param element - element to search through.
+ * @param elementName - name of the element to find within the element passed in
+ * @param defaultValue - value to return if the element is not found or cannot be parsed.
+ * @return the contents of the element as a boolean
+ */
+ public static boolean readBooleanContents(Element element, String elementName, boolean defaultValue)
+ {
+ String val = readStringContents(element, elementName);
+ if (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false"))
+ {
+ // needs to be done this way because of JBBUILD-351
+ return Boolean.valueOf(val);
+ //return Boolean.parseBoolean(val);
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Converts a String representing an XML snippet into an {@link org.w3c.dom.Element}.
+ *
+ * @param xml snippet as a string
+ * @return a DOM Element
+ * @throws Exception if unable to parse the String or if it doesn't contain valid XML.
+ */
+ public static Element stringToElementInCoreNS(String xml) throws Exception
+ {
+ xml = "<wrapper xmlns='" + RootElementBuilder.JBOSSCACHE_CORE_NS + "'>" + xml + "</wrapper>";
+ ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes("utf8"));
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document d = builder.parse(bais);
+ bais.close();
+ return getFirstChildElement(d.getDocumentElement());
+ }
+
+ /**
+ * Converts a String representing an XML snippet into an {@link org.w3c.dom.Element}.
+ *
+ * @param xml snippet as a string
+ * @return a DOM Element
+ * @throws Exception if unable to parse the String or if it doesn't contain valid XML.
+ */
+ public static Element stringToElement(String xml) throws Exception
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes("utf8"));
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document d = builder.parse(bais);
+ bais.close();
+ return d.getDocumentElement();
+ }
+
+ /**
+ * Gets the first child element of an element
+ *
+ * @param element the parent
+ * @return the first child element or null if there isn't one
+ */
+ public static Element getFirstChildElement(Element element)
+ {
+ Node child = element.getFirstChild();
+ while (child != null && child.getNodeType() != Node.ELEMENT_NODE)
+ child = child.getNextSibling();
+
+ return (Element) child;
+ }
+
+ /**
+ * Returns the root element of a given input stream
+ *
+ * @param is stream to parse
+ * @return XML DOM element, or null if unable to parse stream
+ */
+ public static Element getDocumentRoot(InputStream is)
+ {
+ Document doc;
+ try
+ {
+ InputSource xmlInp = new InputSource(is);
+
+ DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+ docBuilderFactory.setNamespaceAware(true);
+ DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
+ doc = parser.parse(xmlInp);
+ Element root = doc.getDocumentElement();
+ root.normalize();
+ return root;
+ }
+ catch (SAXParseException err)
+ {
+ log.error("Configurator SAXParse error", err);
+ }
+ catch (SAXException e)
+ {
+ log.error("Configurator SAX error", e);
+ }
+ catch (Exception pce)
+ {
+ log.error("Configurator general error", pce);
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves the boolean value of a given attribute for the first encountered instance of elementName
+ *
+ * @param elem - element to search
+ * @param elementName - name of element to find
+ * @param attributeName - name of attribute to retrieve the value of
+ * @param defaultValue - default value to return if not found
+ */
+ public static boolean readBooleanAttribute(Element elem, String elementName, String attributeName, boolean defaultValue)
+ {
+ String val = getAttributeValue(elem, elementName, attributeName);
+ if (val != null)
+ {
+ if (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false"))
+ {
+ //return Boolean.parseBoolean(val);
+ // needs to be done this way because of JBBUILD-351
+ return Boolean.valueOf(val);
+ }
+ }
+
+ return defaultValue;
+ }
+
+ public static void setValues(Object target, Map<?, ?> attribs, boolean isXmlAttribs, boolean failOnMissingSetter)
+ {
+ Class objectClass = target.getClass();
+
+ // go thru simple string setters first.
+ for (Map.Entry entry : attribs.entrySet())
+ {
+ String propName = (String) entry.getKey();
+ String setter = BeanUtils.setterName(propName);
+ Method method;
+
+ try
+ {
+ if (isXmlAttribs)
+ {
+ method = objectClass.getMethod(setter, Element.class);
+ method.invoke(target, entry.getValue());
+ }
+ else
+ {
+ method = objectClass.getMethod(setter, String.class);
+ method.invoke(target, entry.getValue());
+ }
+
+ continue;
+ }
+ catch (NoSuchMethodException me)
+ {
+ // this is ok, but certainly log this as a warning
+ // this is hugely noisy!
+ //if (log.isWarnEnabled()) log.warn("Unrecognised attribute " + propName + ". Please check your configuration. Ignoring!!");
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unable to invoke setter " + setter + " on " + objectClass, e);
+ }
+
+ boolean setterFound = false;
+ // if we get here, we could not find a String or Element setter.
+ for (Method m : objectClass.getMethods())
+ {
+ if (setter.equals(m.getName()))
+ {
+ Class paramTypes[] = m.getParameterTypes();
+ if (paramTypes.length != 1)
+ {
+ if (log.isTraceEnabled())
+ log.trace("Rejecting setter " + m + " on class " + objectClass + " due to incorrect number of parameters");
+ continue; // try another param with the same name.
+ }
+
+ Class parameterType = paramTypes[0];
+ PropertyEditor editor = PropertyEditorManager.findEditor(parameterType);
+ if (editor == null)
+ {
+ throw new ConfigurationException("Couldn't find a property editor for parameter type " + parameterType);
+ }
+
+ editor.setAsText((String) attribs.get(propName));
+
+ Object parameter = editor.getValue();
+ //if (log.isDebugEnabled()) log.debug("Invoking setter method: " + setter + " with parameter \"" + parameter + "\" of type " + parameter.getClass());
+
+ try
+ {
+ m.invoke(target, parameter);
+ setterFound = true;
+ break;
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unable to invoke setter " + setter + " on " + objectClass, e);
+ }
+ }
+ }
+ if (!setterFound && failOnMissingSetter)
+ throw new ConfigurationException("Couldn't find a setter named [" + setter + "] which takes a single parameter, for parameter " + propName + " on class [" + objectClass + "]");
+ }
+ }
+
+ public static ParsedAttributes extractAttributes(Element source)
+ {
+ Map<String, String> stringAttribs = new HashMap<String, String>();
+ Map<String, Element> xmlAttribs = new HashMap<String, Element>();
+ NodeList list = source.getElementsByTagName(ATTR);
+ if (log.isDebugEnabled()) log.debug("Attribute size: " + list.getLength());
+
+ // loop through attributes
+ for (int loop = 0; loop < list.getLength(); loop++)
+ {
+ Node node = list.item(loop);
+ if (node.getNodeType() != Node.ELEMENT_NODE) continue;
+
+ // for each element (attribute) ...
+ Element element = (Element) node;
+ String name = element.getAttribute(NAME);
+ String valueStr = getElementContent(element, true);
+
+ Element valueXml = null;
+ if (valueStr.length() == 0)
+ {
+ // This may be an XML element ...
+ valueXml = getSubElement(element, CONFIG_ATTR);
+ if (valueXml != null) xmlAttribs.put(name, valueXml);
+ }
+ else
+ {
+ if (valueStr.length() > 0) stringAttribs.put(name, valueStr);
+ }
+ }
+ return new ParsedAttributes(stringAttribs, xmlAttribs);
+ }
+
+ public static String toString(Element e)
+ {
+ try
+ {
+ TransformerFactory tfactory = TransformerFactory.newInstance();
+ Transformer xform = tfactory.newTransformer();
+ Source src = new DOMSource(e);
+ java.io.StringWriter writer = new StringWriter();
+ Result result = new javax.xml.transform.stream.StreamResult(writer);
+ xform.transform(src, result);
+ return writer.toString();
+ }
+ catch (Exception ex)
+ {
+ return "Unable to convert to string: " + ex.toString();
+ }
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,406 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.util.FileLookup;
+import org.jboss.starobrno.config.BuddyReplicationConfig;
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.starobrno.config.CustomInterceptorConfig;
+import org.jboss.starobrno.config.parsing.element.BuddyElementParser;
+import org.jboss.starobrno.config.parsing.element.CustomInterceptorsElementParser;
+import org.jboss.starobrno.config.parsing.element.EvictionElementParser;
+import org.jboss.starobrno.config.parsing.element.LoadersElementParser;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ErrorHandler;
+
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Reads in XMLconfiguration files and spits out a {@link org.jboss.cache.config.Configuration} object.
+ * By default this class uses a validating parser (configurable).
+ * <p/>
+ * Following system properties can be used for customizing parser behavior:
+ * <ul>
+ * <li> <b>-Djbosscache.config.validate=false</b> will make the parser non-validating </li>
+ * <li> <b>-Djbosscache.config.schemaLocation=url</b> allows one to specify a validation schema that would override the one specified in the the xml document </li>
+ * </ul>
+ * This class is stateful and one instance should be used for parsing a single configuration file.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @see org.jboss.cache.config.parsing.RootElementBuilder
+ * @since 3.0
+ */
+public class XmlConfigurationParser extends XmlParserBase
+{
+
+ private static final Log log = LogFactory.getLog(XmlConfigurationParser.class);
+ private RootElementBuilder rootElementBuilder;
+
+ /**
+ * the resulting configuration.
+ */
+ private Configuration config = new Configuration();
+ private Element root;
+
+ /**
+ * If validation is on (default) one can specify an error handler for handling validation errors.
+ * The default error handler just logs parsing errors received.
+ */
+ public XmlConfigurationParser(ErrorHandler errorHandler)
+ {
+ rootElementBuilder = new RootElementBuilder(errorHandler);
+ }
+
+ /**
+ * Same as {@link #XmlConfigurationParser(org.xml.sax.ErrorHandler)}.
+ *
+ * @param validating should the underlaying parser disable the validation?
+ */
+ public XmlConfigurationParser(boolean validating, ErrorHandler errorHandler)
+ {
+ rootElementBuilder = new RootElementBuilder(errorHandler, validating);
+ }
+
+ /**
+ * Constructs a parser having validation enabled with a ErrorHandler that only logs the parser errors.
+ */
+ public XmlConfigurationParser()
+ {
+ rootElementBuilder = new RootElementBuilder();
+ }
+
+ /**
+ * Parses an XML file and returns a new configuration.
+ * For looking up the file, {@link org.jboss.cache.util.FileLookup} is used.
+ *
+ * @see org.jboss.cache.util.FileLookup
+ */
+ public Configuration parseFile(String filename)
+ {
+ InputStream is = new FileLookup().lookupFile(filename);
+ if (is == null)
+ {
+ throw new ConfigurationException("Unable to find config file " + filename + " either in classpath or on the filesystem!");
+ }
+ return parseStream(is);
+ }
+
+ /**
+ * Similar to {@link #parseFile(String)}, just that it does not create the input stream.
+ */
+ public Configuration parseStream(InputStream configStream)
+ {
+ readRoot(configStream);
+ return processElements(false);
+ }
+
+ /**
+ * Root should be the <b>jbosscache</b> element in the configuration file.
+ */
+ public Configuration parseElement(Element root)
+ {
+ this.root = root;
+ this.root.normalize();
+ return processElements(false);
+ }
+
+ public Configuration parseElementIgnoringRoot(Element root)
+ {
+ this.root = root;
+ this.root.normalize();
+ return processElements(true);
+ }
+
+ public boolean isValidating()
+ {
+ return rootElementBuilder.isValidating();
+ }
+
+ private Configuration processElements(boolean ignoreRoot)
+ {
+ if (!ignoreRoot)
+ {
+ if (!"jbosscache".equals(root.getLocalName()) || !RootElementBuilder.JBOSSCACHE_CORE_NS.equals(root.getNamespaceURI()))
+ throw new ConfigurationException("Expected root element {" + RootElementBuilder.JBOSSCACHE_CORE_NS + "}" + "jbosscache");
+ }
+
+ try
+ {
+ configureLocking(getSingleElement("locking"));
+ configureTransaction(getSingleElement("transaction"));
+ configureReplication(getSingleElement("replication"));
+ configureSerialization(getSingleElement("serialization"));
+ configureInvalidation(getSingleElement("invalidation"));
+ configureStartup(getSingleElement("startup"));
+ configureStateRetrieval(getSingleElement("stateRetrieval"));
+ configureTransport(getSingleElement("transport"));
+ configureShutdown(getSingleElement("shutdown"));
+ configureJmxStatistics(getSingleElement("jmxStatistics"));
+ configureEviction(getSingleElement("eviction"));
+ configureCacheLoaders(getSingleElement("loaders"));
+ configureCustomInterceptors(getSingleElement("customInterceptors"));
+ configureListeners(getSingleElement("listeners"));
+ configureInvocationBatching(getSingleElement("invocationBatching"));
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unexpected exception while parsing the configuration file", e);
+ }
+ return config;
+ }
+
+ private void configureStateRetrieval(Element element)
+ {
+ if (element == null) return; //we might not have this configured
+ String fetchInMemoryState = getAttributeValue(element, "fetchInMemoryState");
+ if (existsAttribute(fetchInMemoryState)) config.setFetchInMemoryState(getBoolean(fetchInMemoryState));
+ String stateRetrievalTimeout = getAttributeValue(element, "timeout");
+ if (existsAttribute(stateRetrievalTimeout)) config.setStateRetrievalTimeout(getLong(stateRetrievalTimeout));
+
+ }
+
+ private void configureTransaction(Element element)
+ {
+ if (element == null) return;
+ String attrName = "transactionManagerLookupClass";
+ String txMngLookupClass = getAttributeValue(element, attrName);
+ if (existsAttribute(txMngLookupClass)) config.setTransactionManagerLookupClass(txMngLookupClass);
+ String syncRollbackPhase = getAttributeValue(element, "syncRollbackPhase");
+ if (existsAttribute(syncRollbackPhase)) config.setSyncRollbackPhase(getBoolean(syncRollbackPhase));
+ String syncCommitPhase = getAttributeValue(element, "syncCommitPhase");
+ if (existsAttribute(syncCommitPhase)) config.setSyncCommitPhase(getBoolean(syncCommitPhase));
+ }
+
+ private void configureSerialization(Element element)
+ {
+ if (element == null) return;
+ String objectInputStreamPoolSize = getAttributeValue(element, "objectInputStreamPoolSize");
+ if (existsAttribute(objectInputStreamPoolSize))
+ config.setObjectInputStreamPoolSize(getInt(objectInputStreamPoolSize));
+ String objectOutputStreamPoolSize = getAttributeValue(element, "objectOutputStreamPoolSize");
+ if (existsAttribute(objectOutputStreamPoolSize))
+ config.setObjectOutputStreamPoolSize(getInt(objectOutputStreamPoolSize));
+ String version = getAttributeValue(element, "version");
+ if (existsAttribute(version)) config.setReplVersionString(version);
+ String marshallerClass = getAttributeValue(element, "marshallerClass");
+ if (existsAttribute(marshallerClass)) config.setMarshallerClass(marshallerClass);
+ String useLazyDeserialization = getAttributeValue(element, "useLazyDeserialization");
+ if (existsAttribute(useLazyDeserialization)) config.setUseLazyDeserialization(getBoolean(useLazyDeserialization));
+ String useRegionBasedMarshalling = getAttributeValue(element, "useRegionBasedMarshalling");
+ if (existsAttribute(useRegionBasedMarshalling))
+ config.setUseRegionBasedMarshalling(getBoolean(useRegionBasedMarshalling));
+ }
+
+ private void configureCustomInterceptors(Element element)
+ {
+ if (element == null) return; //this element might be missing
+ CustomInterceptorsElementParser parser = new CustomInterceptorsElementParser();
+ List<CustomInterceptorConfig> interceptorConfigList = parser.parseCustomInterceptors(element);
+ config.setCustomInterceptors(interceptorConfigList);
+ }
+
+ private void configureListeners(Element element)
+ {
+ if (element == null) return; //this element is optional
+ String asyncPoolSizeStr = getAttributeValue(element, "asyncPoolSize");
+ if (existsAttribute(asyncPoolSizeStr))
+ {
+ try
+ {
+ config.setListenerAsyncPoolSize(Integer.parseInt(asyncPoolSizeStr));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new ConfigurationException("Unable to parse the asyncPoolSize attribute of the listeners element. Was [" + asyncPoolSizeStr + "]");
+ }
+ }
+ }
+
+ private void configureInvocationBatching(Element element)
+ {
+ if (element == null) return; //this element is optional
+ boolean enabled = getBoolean(getAttributeValue(element, "enabled"));
+ config.setInvocationBatchingEnabled(enabled);
+ }
+
+ private void configureBuddyReplication(Element element)
+ {
+ if (element == null) return;//buddy config might not exist, expect that
+ BuddyElementParser buddyElementParser = new BuddyElementParser();
+ BuddyReplicationConfig brConfig = buddyElementParser.parseBuddyElement(element);
+ config.setBuddyReplicationConfig(brConfig);
+ }
+
+ private void configureCacheLoaders(Element element)
+ {
+ if (element == null) return; //null cache loaders are allowed
+ LoadersElementParser clElementParser = new LoadersElementParser();
+ CacheLoaderConfig cacheLoaderConfig = clElementParser.parseLoadersElement(element);
+ config.setCacheLoaderConfig(cacheLoaderConfig);
+ }
+
+ private void configureEviction(Element element)
+ {
+ if (element == null) return; //no eviction might be configured
+ EvictionElementParser evictionElementParser = new EvictionElementParser();
+ config.setEvictionConfig(evictionElementParser.parseEvictionElement(element));
+ }
+
+ private void configureJmxStatistics(Element element)
+ {
+ if (element == null) return; //might not be specified
+ String enabled = getAttributeValue(element, "enabled");
+ config.setExposeManagementStatistics(getBoolean(enabled));
+ }
+
+ private void configureShutdown(Element element)
+ {
+ if (element == null) return;
+ String hookBehavior = getAttributeValue(element, "hookBehavior");
+ if (existsAttribute(hookBehavior)) config.setShutdownHookBehavior(hookBehavior);
+ }
+
+ private void configureTransport(Element element)
+ {
+ if (element == null) return; //transport might be missing
+ String clusterName = getAttributeValue(element, "clusterName");
+ if (existsAttribute(clusterName)) config.setClusterName(clusterName);
+ String multiplexerStack = getAttributeValue(element, "multiplexerStack");
+ if (existsAttribute(multiplexerStack)) config.setMultiplexerStack(multiplexerStack);
+ Element clusterConfig = getSingleElementInCoreNS("jgroupsConfig", element);
+ if (clusterConfig != null)
+ {
+ JGroupsStackParser stackParser = new JGroupsStackParser();
+ String clusterConfigStr = stackParser.parseClusterConfigXml(clusterConfig);
+ if (clusterConfigStr != null && clusterConfigStr.trim().length() > 0)
+ config.setClusterConfig(clusterConfigStr);
+ }
+ }
+
+ private void configureStartup(Element element)
+ {
+ if (element == null) return; //we might not have this configured
+ String inactiveOnStartup = getAttributeValue(element, "regionsInactiveOnStartup");
+ if (existsAttribute(inactiveOnStartup)) config.setInactiveOnStartup(getBoolean(inactiveOnStartup));
+ }
+
+ private void configureInvalidation(Element element)
+ {
+ if (element == null) return; //might be replication
+ Element async = getSingleElement("async");
+ if (async != null)
+ {
+ config.setCacheMode(Configuration.CacheMode.INVALIDATION_ASYNC);
+ configureAsyncMode(getSingleElementInCoreNS("async", element));
+ }
+ Element sync = getSingleElement("sync");
+ if (sync != null)
+ {
+ config.setCacheMode(Configuration.CacheMode.INVALIDATION_SYNC);
+ configureSyncMode(getSingleElementInCoreNS("sync", element));
+ }
+ }
+
+ private void configureReplication(Element element)
+ {
+ if (element == null) return; //might be we do not have a replication enabled
+ Element async = getSingleElement("async");
+ if (async != null)
+ {
+ config.setCacheMode(Configuration.CacheMode.REPL_ASYNC);
+ configureAsyncMode(getSingleElementInCoreNS("async", element));
+ }
+ Element sync = getSingleElement("sync");
+ if (sync != null)
+ {
+ config.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ configureSyncMode(getSingleElementInCoreNS("sync", element));
+ }
+ configureBuddyReplication(getSingleElementInCoreNS("buddy", element));
+ }
+
+ private void configureSyncMode(Element element)
+ {
+ String replTimeout = getAttributeValue(element, "replTimeout");
+ if (existsAttribute(replTimeout)) config.setSyncReplTimeout(getLong(replTimeout));
+ }
+
+ private void configureAsyncMode(Element element)
+ {
+ String useReplQueue = getAttributeValue(element, "useReplQueue");
+ if (existsAttribute(useReplQueue)) config.setUseReplQueue(getBoolean(useReplQueue));
+ String replQueueInterval = getAttributeValue(element, "replQueueInterval");
+ if (existsAttribute(replQueueInterval)) config.setReplQueueInterval(getLong(replQueueInterval));
+ String replQueueMaxElements = getAttributeValue(element, "replQueueMaxElements");
+ if (existsAttribute(replQueueMaxElements)) config.setReplQueueMaxElements(getInt(replQueueMaxElements));
+ String serializationExecutorPoolSize = getAttributeValue(element, "serializationExecutorPoolSize");
+ if (existsAttribute(serializationExecutorPoolSize))
+ config.setSerializationExecutorPoolSize(getInt(serializationExecutorPoolSize));
+ }
+
+ private void configureLocking(Element element)
+ {
+ String isolationLevel = getAttributeValue(element, "isolationLevel");
+ if (existsAttribute(isolationLevel)) config.setIsolationLevel(IsolationLevel.valueOf(isolationLevel));
+ String lockParentForChildInsertRemove = getAttributeValue(element, "lockParentForChildInsertRemove");
+ if (existsAttribute(lockParentForChildInsertRemove))
+ config.setLockParentForChildInsertRemove(getBoolean(lockParentForChildInsertRemove));
+ String lockAcquisitionTimeout = getAttributeValue(element, "lockAcquisitionTimeout");
+ if (existsAttribute(lockAcquisitionTimeout)) config.setLockAcquisitionTimeout(getLong(lockAcquisitionTimeout));
+ String nodeLockingScheme = getAttributeValue(element, "nodeLockingScheme");
+ if (existsAttribute(nodeLockingScheme)) config.setNodeLockingScheme(nodeLockingScheme);
+ String writeSkewCheck = getAttributeValue(element, "writeSkewCheck");
+ if (existsAttribute(writeSkewCheck)) config.setWriteSkewCheck(getBoolean(writeSkewCheck));
+ String concurrencyLevel = getAttributeValue(element, "concurrencyLevel");
+ if (existsAttribute(concurrencyLevel)) config.setConcurrencyLevel(getInt(concurrencyLevel));
+ }
+
+ private Element getSingleElement(String elementName)
+ {
+ return getSingleElementInCoreNS(elementName, root);
+ }
+
+ private void readRoot(InputStream config)
+ {
+ root = rootElementBuilder.readRoot(config);
+ }
+
+ /**
+ * Tests whether the element passed in is a modern (3.0) config element rather than a legacy one.
+ *
+ * @param element element to test
+ * @return true of the element is a modern one and can be parsed using the current parser.
+ */
+ public boolean isValidElementRoot(Element element)
+ {
+ // simply test for the "jbosscache" element.
+ NodeList elements = element.getElementsByTagName("jbosscache");
+ return elements != null && elements.getLength() > 0;
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlParserBase.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlParserBase.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlParserBase.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing;
+
+import org.jboss.util.StringPropertyReplacer;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Contains utility methods that might be useful to most of the parsers.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public abstract class XmlParserBase
+{
+
+ /**
+ * @see Integer#parseInt(String)
+ */
+ protected int getInt(String intStr)
+ {
+ return Integer.parseInt(intStr);
+ }
+
+ /**
+ * @see Long#parseLong(String)
+ */
+ protected long getLong(String longStr)
+ {
+ return Long.parseLong(longStr);
+ }
+
+ /**
+ * @see Boolean#valueOf(String)
+ */
+ protected boolean getBoolean(String str)
+ {
+ return str == null ? false : Boolean.valueOf(str);
+ }
+
+ /**
+ * @return true if the given value is not empty.
+ */
+ protected boolean existsAttribute(String attrValue)
+ {
+ return attrValue != null && attrValue.length() > 0;
+ }
+
+ /**
+ * Convenient method for retrieving a single element with the give name.
+ */
+ protected Element getSingleElement(String namespace, String elementName, Element parent)
+ {
+ NodeList nodeList = parent.getElementsByTagNameNS(namespace, elementName);
+ if (nodeList.getLength() == 0)
+ {
+ return null;
+ }
+ return (Element) nodeList.item(0);
+ }
+
+ /**
+ * Convenient method for retrieving a single element with the give name.
+ */
+ protected Element getSingleElementInCoreNS(String elementName, Element parent)
+ {
+ return getSingleElement(RootElementBuilder.JBOSSCACHE_CORE_NS, elementName, parent);
+ }
+
+ /**
+ * Beside querying the element for its attribute value, it will look into the value, if any, and replace the
+ * jboss properties(e.g. ${someValue:defaultValue}.
+ * <p/>
+ * {@link org.jboss.util.StringPropertyReplacer#replaceProperties(String)}
+ */
+ protected String getAttributeValue(Element element, String attrName)
+ {
+ if (element == null || attrName == null) return null;
+ String value = element.getAttribute(attrName);
+ return value == null ? null : StringPropertyReplacer.replaceProperties(value);
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/BuddyElementParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/BuddyElementParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/BuddyElementParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing.element;
+
+import org.jboss.cache.buddyreplication.NextMemberBuddyLocator;
+import org.jboss.starobrno.config.BuddyReplicationConfig;
+import org.jboss.starobrno.config.parsing.XmlConfigHelper;
+import org.jboss.starobrno.config.parsing.XmlParserBase;
+import org.w3c.dom.Element;
+
+import java.util.Properties;
+
+/**
+ * Utility class for parsing 'buddy' element in the .xml configuration file.
+ * <pre>
+ * Note: class does not rely on element position in the configuration file.
+ * It does not rely on element's name either.
+ * </pre>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class BuddyElementParser extends XmlParserBase
+{
+ public BuddyReplicationConfig parseBuddyElement(Element element)
+ {
+ BuddyReplicationConfig brc = new BuddyReplicationConfig();
+ String enabled = getAttributeValue(element, "enabled");
+ brc.setEnabled(getBoolean(enabled));
+ String buddyPoolName = getAttributeValue(element, "poolName");
+ if (existsAttribute(buddyPoolName)) brc.setBuddyPoolName(buddyPoolName);
+ String buddyCommunicationTimeout = getAttributeValue(element, "communicationTimeout");
+ if (existsAttribute(buddyCommunicationTimeout))
+ brc.setBuddyCommunicationTimeout(getInt(buddyCommunicationTimeout));
+
+ parseDataGravitationElement(getSingleElementInCoreNS("dataGravitation", element), brc);
+ BuddyReplicationConfig.BuddyLocatorConfig blc = parseBuddyLocatorConfig(getSingleElementInCoreNS("locator", element));
+ brc.setBuddyLocatorConfig(blc);
+ return brc;
+ }
+
+ private BuddyReplicationConfig.BuddyLocatorConfig parseBuddyLocatorConfig(Element element)
+ {
+ if (element == null) return defaultBuddyLocatorConfig();
+ BuddyReplicationConfig.BuddyLocatorConfig result = new BuddyReplicationConfig.BuddyLocatorConfig();
+ String buddyLocatorClass = getAttributeValue(element, "class");
+ if (existsAttribute(buddyLocatorClass)) result.setBuddyLocatorClass(buddyLocatorClass);
+ Properties existing = new Properties();
+ Properties configured = XmlConfigHelper.readPropertiesContents(element, "properties");
+ existing.putAll(configured);
+ result.setBuddyLocatorClass(buddyLocatorClass);
+ result.setBuddyLocatorProperties(existing);
+ return result;
+ }
+
+ private BuddyReplicationConfig.BuddyLocatorConfig defaultBuddyLocatorConfig()
+ {
+ BuddyReplicationConfig.BuddyLocatorConfig result = new BuddyReplicationConfig.BuddyLocatorConfig();
+ result.setBuddyLocatorClass(NextMemberBuddyLocator.class.getName());
+ Properties props = new Properties();
+ result.setBuddyLocatorProperties(props);
+ return result;
+ }
+
+ private void parseDataGravitationElement(Element element, BuddyReplicationConfig brc)
+ {
+ if (element == null) return;
+ String auto = getAttributeValue(element, "auto");
+ if (existsAttribute(auto)) brc.setAutoDataGravitation(getBoolean(auto));
+ String removeOnFind = getAttributeValue(element, "removeOnFind");
+ if (existsAttribute(removeOnFind)) brc.setDataGravitationRemoveOnFind(getBoolean(removeOnFind));
+ String searchBackupTrees = getAttributeValue(element, "searchBackupTrees");
+ if (existsAttribute(searchBackupTrees)) brc.setDataGravitationSearchBackupTrees(getBoolean(searchBackupTrees));
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/CustomInterceptorsElementParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/CustomInterceptorsElementParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/CustomInterceptorsElementParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing.element;
+
+
+import org.jboss.cache.util.Util;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.starobrno.config.CustomInterceptorConfig;
+import org.jboss.starobrno.config.parsing.ParsedAttributes;
+import org.jboss.starobrno.config.parsing.XmlConfigHelper;
+import org.jboss.starobrno.config.parsing.XmlParserBase;
+import org.jboss.starobrno.interceptors.base.CommandInterceptor;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class for parsing 'buddy' element in the .xml configuration file.
+ * <pre>
+ * Note: class does not rely on element position in the configuration file.
+ * It does not rely on element's name either.
+ * </pre>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class CustomInterceptorsElementParser extends XmlParserBase
+{
+ /**
+ * Iterates within the given element looking for custom interceptors.
+ *
+ * @param element should not be null
+ * @return a list which might be empty, never null
+ */
+ public List<CustomInterceptorConfig> parseCustomInterceptors(Element element)
+ {
+ NodeList interceptorNodes = element.getElementsByTagName("interceptor");
+ List<CustomInterceptorConfig> interceptorConfigs = new ArrayList<CustomInterceptorConfig>(interceptorNodes.getLength());
+ for (int i = 0; i < interceptorNodes.getLength(); i++)
+ {
+ boolean first = false;
+ boolean last = false;
+ int index = -1;
+ String after = null;
+ String before = null;
+
+ Element interceptorElement = (Element) interceptorNodes.item(i);
+ String position = getAttributeValue(interceptorElement, "position");
+ if (existsAttribute(position) && "first".equalsIgnoreCase(position))
+ {
+ first = true;
+ }
+ if (existsAttribute(position) && "last".equalsIgnoreCase(position))
+ {
+ last = true;
+ }
+ String indexStr = getAttributeValue(interceptorElement, "index");
+ index = existsAttribute(indexStr) ? getInt(indexStr) : -1;
+
+ before = getAttributeValue(interceptorElement, "before");
+ if (!existsAttribute(before)) before = null;
+ after = getAttributeValue(interceptorElement, "after");
+ if (!existsAttribute(after)) after = null;
+
+ CommandInterceptor interceptor = buildCommandInterceptor(interceptorElement);
+
+ CustomInterceptorConfig customInterceptorConfig = new CustomInterceptorConfig(interceptor, first, last, index, after, before);
+ interceptorConfigs.add(customInterceptorConfig);
+ }
+ return interceptorConfigs;
+ }
+
+ /**
+ * Builds the interceptor based on the interceptor class and also sets all its attributes.
+ */
+ private CommandInterceptor buildCommandInterceptor(Element element)
+ {
+ String interceptorClass = getAttributeValue(element, "class");
+ if (!existsAttribute(interceptorClass)) throw new ConfigurationException("Interceptor class cannot be empty!");
+ CommandInterceptor result;
+ try
+ {
+ result = (CommandInterceptor) Util.loadClass(interceptorClass).newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("CommandInterceptor class is not properly loaded in classloader", e);
+ }
+ ParsedAttributes attributes = XmlConfigHelper.extractAttributes(element);
+ XmlConfigHelper.setValues(result, attributes.stringAttribs, false, true);
+ return result;
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/EvictionElementParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/EvictionElementParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/EvictionElementParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,192 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing.element;
+
+import org.jboss.cache.util.Util;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.starobrno.config.EvictionAlgorithmConfig;
+import org.jboss.starobrno.config.EvictionConfig;
+import org.jboss.starobrno.config.EvictionRegionConfig;
+import org.jboss.starobrno.config.MissingPolicyException;
+import org.jboss.starobrno.config.parsing.ParsedAttributes;
+import org.jboss.starobrno.config.parsing.XmlConfigHelper;
+import org.jboss.starobrno.config.parsing.XmlParserBase;
+import org.jboss.starobrno.eviction.EvictionAlgorithm;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Knows how to parse the <b>eviction</b> xml element.
+ * <pre>
+ * Note: class does not rely on element position in the configuration file.
+ * It does not rely on element's name either.
+ * </pre>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class EvictionElementParser extends XmlParserBase
+{
+ public EvictionConfig parseEvictionElement(Element evictionElement)
+ {
+ EvictionConfig evictionConfig = new EvictionConfig();
+ String wakeUpInterval = getAttributeValue(evictionElement, "wakeUpInterval");
+ if (existsAttribute(wakeUpInterval))
+ {
+ evictionConfig.setWakeupInterval(getInt(wakeUpInterval));
+ }
+ else
+ {
+ throw new ConfigurationException("Missing mandatory attribute wakeUpInterval");
+ }
+
+ List<EvictionRegionConfig> evictionRegionConfigs = new LinkedList<EvictionRegionConfig>();
+ Element defaultRegion = getSingleElementInCoreNS("default", evictionElement);
+
+ if (defaultRegion != null)
+ {
+ EvictionRegionConfig defaultRegionConfig = getEvictionRegionConfig(defaultRegion, null, true);
+ if (defaultRegionConfig.getEvictionAlgorithmConfig() == null)
+ throw new MissingPolicyException("Default eviction region should have an evictionAlgorithmClass defined.");
+ evictionConfig.setDefaultEvictionRegionConfig(defaultRegionConfig);
+ }
+
+ NodeList regions = evictionElement.getElementsByTagName("region");
+ for (int i = 0; i < regions.getLength(); i++)
+ {
+ Element regionConfig = (Element) regions.item(i);
+ EvictionRegionConfig erc = getEvictionRegionConfig(regionConfig, evictionConfig.getDefaultEvictionRegionConfig(), false);
+ evictionConfig.applyDefaults(erc);
+ evictionRegionConfigs.add(erc);
+ }
+ evictionConfig.setEvictionRegionConfigs(evictionRegionConfigs);
+ return evictionConfig;
+ }
+
+ @SuppressWarnings("unchecked")
+ private EvictionRegionConfig getEvictionRegionConfig(Element element, EvictionRegionConfig defaultRegion, boolean isDefault)
+ {
+ EvictionRegionConfig erc = new EvictionRegionConfig();
+ erc.setRegionName(getAttributeValue(element, "name"));
+ String queueSize = getAttributeValue(element, "eventQueueSize");
+ if (existsAttribute(queueSize))
+ {
+ erc.setEventQueueSize(getInt(queueSize));
+ }
+ else if (defaultRegion == null)
+ {
+ erc.setEventQueueSize(EvictionConfig.EVENT_QUEUE_SIZE_DEFAULT);
+ }
+
+ String algorithmClassName = getAttributeValue(element, "algorithmClass");
+ EvictionAlgorithmConfig algorithmConfig = null; // every eviction region config needs an algorithm config.
+
+ if (existsAttribute(algorithmClassName))
+ {
+ EvictionAlgorithm algorithm;
+ Class<? extends EvictionAlgorithm> algorithmClass;
+ // try using a 'getInstance()' factory.
+
+ try
+ {
+ algorithmClass = Util.loadClass(algorithmClassName);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Unable to load eviction algorithm class [" + algorithmClassName + "]", e);
+ }
+
+
+ try
+ {
+ algorithm = Util.getInstance(algorithmClass);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unable to construct eviction algorithm class [" + algorithmClassName + "]", e);
+ }
+
+ try
+ {
+ algorithmConfig = Util.getInstance(algorithm.getConfigurationClass());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failed to instantiate eviction algorithm configuration class [" +
+ algorithm.getConfigurationClass() + "]", e);
+ }
+ }
+ else
+ {
+ if (!isDefault)
+ {
+ if (defaultRegion == null || defaultRegion.getEvictionAlgorithmConfig() == null)
+ {
+ throw new MissingPolicyException("There is no Eviction Algorithm Class specified on the region or for the entire cache!");
+ }
+ else
+ {
+ try
+ {
+ algorithmConfig = defaultRegion.getEvictionAlgorithmConfig().clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw new ConfigurationException("Unable to clone eviction algorithm configuration from default", e);
+ }
+ }
+ }
+ }
+
+ if (algorithmConfig != null)
+ {
+ parseEvictionPolicyConfig(element, algorithmConfig);
+
+ erc.setEvictionAlgorithmConfig(algorithmConfig);
+ }
+
+ String actionPolicyClass = getAttributeValue(element, "actionPolicyClass");
+ if (existsAttribute(actionPolicyClass))
+ {
+ erc.setEvictionActionPolicyClassName(actionPolicyClass);
+ }
+ else if (defaultRegion == null)
+ {
+ // this is the default region. Make sure we set the default EvictionActionPolicyClass.
+ erc.setEvictionActionPolicyClassName(EvictionConfig.EVICTION_ACTION_POLICY_CLASS_DEFAULT);
+ }
+
+
+ return erc;
+ }
+
+ public static void parseEvictionPolicyConfig(Element element, EvictionAlgorithmConfig target)
+ {
+ target.reset();
+ ParsedAttributes attributes = XmlConfigHelper.extractAttributes(element);
+ XmlConfigHelper.setValues(target, attributes.stringAttribs, false, true);
+ XmlConfigHelper.setValues(target, attributes.xmlAttribs, true, true);
+ }
+}
Added: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/LoadersElementParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/LoadersElementParser.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/element/LoadersElementParser.java 2008-10-08 16:37:44 UTC (rev 6888)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.starobrno.config.parsing.element;
+
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.starobrno.config.parsing.XmlConfigHelper;
+import org.jboss.starobrno.config.parsing.XmlParserBase;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.Properties;
+
+/**
+ * Utility class for parsing the 'loaders' element in the .xml configuration file.
+ * <pre>
+ * Note: class does not rely on element position in the configuration file.
+ * It does not rely on element's name either.
+ * </pre>
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 3.0
+ */
+public class LoadersElementParser extends XmlParserBase
+{
+ public CacheLoaderConfig parseLoadersElement(Element element)
+ {
+ CacheLoaderConfig cacheLoaderConfig = new CacheLoaderConfig();
+ String passivation = getAttributeValue(element, "passivation");
+ if (existsAttribute(passivation)) cacheLoaderConfig.setPassivation(getBoolean(passivation));
+ String shared = getAttributeValue(element, "shared");
+ if (existsAttribute(shared)) cacheLoaderConfig.setShared(getBoolean(shared));
+ String preload = getPreloadString(getSingleElementInCoreNS("preload", element));
+ if (preload != null) cacheLoaderConfig.setPreload(preload);
+
+ NodeList cacheLoaderNodes = element.getElementsByTagName("loader");
+ for (int i = 0; i < cacheLoaderNodes.getLength(); i++)
+ {
+ Element indivElement = (Element) cacheLoaderNodes.item(i);
+ CacheLoaderConfig.IndividualCacheLoaderConfig iclc = parseIndividualCacheLoaderConfig(indivElement);
+ cacheLoaderConfig.addIndividualCacheLoaderConfig(iclc);
+ }
+ return cacheLoaderConfig;
+ }
+
+ private CacheLoaderConfig.IndividualCacheLoaderConfig parseIndividualCacheLoaderConfig(Element indivElement)
+ {
+ CacheLoaderConfig.IndividualCacheLoaderConfig iclc = new CacheLoaderConfig.IndividualCacheLoaderConfig();
+
+ String async = getAttributeValue(indivElement, "async");
+ if (existsAttribute(async)) iclc.setAsync(getBoolean(async));
+ String fetchPersistentState = getAttributeValue(indivElement, "fetchPersistentState");
+ if (existsAttribute(fetchPersistentState)) iclc.setFetchPersistentState(getBoolean(fetchPersistentState));
+ String ignoreModifications = getAttributeValue(indivElement, "ignoreModifications");
+ if (existsAttribute(ignoreModifications)) iclc.setIgnoreModifications(getBoolean(ignoreModifications));
+ String purgeOnStartup = getAttributeValue(indivElement, "purgeOnStartup");
+ if (existsAttribute(purgeOnStartup)) iclc.setPurgeOnStartup(getBoolean(purgeOnStartup));
+ String clClass = getAttributeValue(indivElement, "class");
+ if (!existsAttribute(clClass))
+ throw new ConfigurationException("Missing 'class' attribute for cache loader configuration");
+ iclc.setClassName(clClass);
+ iclc.setProperties(XmlConfigHelper.readPropertiesContents(indivElement, "properties"));
+ CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = parseSingletonStoreConfig(getSingleElementInCoreNS("singletonStore", indivElement));
+ if (ssc != null)
+ {
+ iclc.setSingletonStoreConfig(ssc);
+ }
+ return iclc;
+ }
+
+ private String getPreloadString(Element preloadElement)
+ {
+ if (preloadElement == null) return null; //might be no preload
+ NodeList nodesToPreload = preloadElement.getElementsByTagName("node");
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < nodesToPreload.getLength(); i++)
+ {
+ Element node = (Element) nodesToPreload.item(i);
+ String fqn2preload = getAttributeValue(node, "fqn");
+ if (!existsAttribute(fqn2preload))
+ throw new ConfigurationException("Missing 'fqn' attribute in 'preload' element");
+ if (i > 0) result.append(",");
+ result.append(fqn2preload);
+ }
+ //no elements defined for preload so by default load the root
+ if (nodesToPreload.getLength() == 0)
+ {
+ result.append("/");
+ }
+ return result.toString();
+ }
+
+ public CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig parseSingletonStoreConfig(Element element)
+ {
+ if (element == null) return null; //might happen, this config option is not mandatory
+ boolean singletonStoreEnabled = getBoolean(getAttributeValue(element, "enabled"));
+ String singletonStoreClass = getAttributeValue(element, "class");
+ CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = new CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig();
+ if (existsAttribute(singletonStoreClass)) ssc.setSingletonStoreClass(singletonStoreClass);
+ Properties singletonStoreproperties = XmlConfigHelper.readPropertiesContents(element, "properties");
+ ssc.setSingletonStoreEnabled(singletonStoreEnabled);
+ ssc.setSingletonStoreClass(singletonStoreClass);
+ ssc.setSingletonStoreproperties(singletonStoreproperties);
+ return ssc;
+ }
+}
More information about the jbosscache-commits
mailing list