[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>&lt;mbean&gt;</tt> tag.
+    */
+   public static final String ROOT = "mbean";
+
+   /**
+    * The <tt>&lt;attribute&gt;</tt> tag which forms the bulk of JBoss Cache configuration elements
+    */
+   public static final String ATTR = "attribute";
+
+   /**
+    * The <tt>&lt;config&gt;</tt> tag may be embedded in the contents of an <tt>&lt;attribute&gt;</tt>, to specify more
+    * complex configuration for certain parameters.
+    */
+   public static final String CONFIG_ATTR = "config";
+
+   /**
+    * The <tt>&lt;name&gt;</tt> attribute to an <tt>&lt;attribute&gt;</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>
+    *   &lt;ItemQuantity Colour="Red"&gt;100&lt;/ItemQuantity&gt;
+    *   &lt;ItemQuantity Colour="Blue"&gt;30&lt;/ItemQuantity&gt;
+    *   &lt;ItemQuantity Colour="Black"&gt;10&lt;/ItemQuantity&gt;
+    * <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>
+    *   &lt;ItemQuantity Colour="Red"&gt;100&lt;/ItemQuantity&gt;
+    *   &lt;ItemQuantity Colour="Blue"&gt;30&lt;/ItemQuantity&gt;
+    *   &lt;ItemQuantity Colour="Black"&gt;10&lt;/ItemQuantity&gt;
+    * <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>
+    *   &lt;props&gt;
+    *       my.attrib.1 = blah
+    *       my.attrib.2 = blahblah
+    *   &lt;/props&gt;
+    * <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