You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2012/10/18 18:37:44 UTC

svn commit: r1399731 [2/3] - in /tomcat/sandbox/storeconfig6: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/catalina/ src/main/java/org/apache/catalina/storeconfig/ src/main/resources/ src/main/r...

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServerSF.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServerSF.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServerSF.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServerSF.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import java.io.PrintWriter;
+
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Service;
+import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.deploy.NamingResources;
+import org.apache.catalina.mbeans.ServerLifecycleListener;
+
+/**
+ * Store server.xml Server element and childs (
+ * Listener,GlobalNamingResource,Service)
+ * 
+ * @author Peter Rossbach
+ */
+public class StandardServerSF extends StoreFactoryBase {
+
+    /**
+     * Store the specified Server properties.
+     * 
+     * @param aWriter
+     *            PrintWriter to which we are storing
+     * @param indent
+     *            Number of spaces to indent this element
+     * @param aServer
+     *            Object to be stored
+     * 
+     * @exception Exception
+     *                if an exception occurs while storing
+     * @see org.apache.catalina.storeconfig.IStoreFactory#store(java.io.PrintWriter,
+     *      int, java.lang.Object)
+     */
+    public void store(PrintWriter aWriter, int indent, Object aServer)
+            throws Exception {
+        storeXMLHead(aWriter);
+        super.store(aWriter, indent, aServer);
+    }
+
+    /**
+     * Store Childs from this StandardServer descrition
+     * 
+     * @param aWriter
+     * @param indent
+     * @param aObject
+     * @param parentDesc
+     * @throws Exception
+     */
+    public void storeChilds(PrintWriter aWriter, int indent, Object aObject,
+            StoreDescription parentDesc) throws Exception {
+        if (aObject instanceof StandardServer) {
+            StandardServer server = (StandardServer) aObject;
+            // Store nested <Listener> elements
+            if (server instanceof Lifecycle) {
+                LifecycleListener listeners[] = ((Lifecycle) server)
+                        .findLifecycleListeners();
+                storeElementArray(aWriter, indent, listeners);
+                LifecycleListener listener = null;
+                for (int i = 0; listener == null && i < listeners.length; i++)
+                    if (listeners[i] instanceof ServerLifecycleListener)
+                        listener = listeners[i];
+                if (listener != null) {
+                    StoreDescription elementDesc = getRegistry()
+                            .findDescription(
+                                    StandardServer.class.getName()
+                                            + ".[ServerLifecycleListener]");
+                    if (elementDesc != null) {
+                        elementDesc.getStoreFactory().store(aWriter, indent,
+                                listener);
+                    }
+                }
+            }
+            // Store nested <GlobalNamingResources> element
+            NamingResources globalNamingResources = server
+                    .getGlobalNamingResources();
+            StoreDescription elementDesc = getRegistry().findDescription(
+                    NamingResources.class.getName()
+                            + ".[GlobalNamingResources]");
+            if (elementDesc != null) {
+                elementDesc.getStoreFactory().store(aWriter, indent,
+                        globalNamingResources);
+            }
+            // Store nested <Service> elements
+            Service services[] = server.findServices();
+            storeElementArray(aWriter, indent, services);
+        }
+    }
+
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServiceSF.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServiceSF.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServiceSF.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StandardServiceSF.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import java.io.PrintWriter;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Executor;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardService;
+
+/**
+ * Store server.xml Element Service and all childs 
+ * @author Peter Rossbach (pero@apache.org)
+ */
+public class StandardServiceSF extends StoreFactoryBase {
+
+    /**
+     * Store Childs from this StandardService description
+     * 
+     * @param aWriter
+     * @param indent
+     * @param aService
+     * @throws Exception
+     */
+    public void storeChilds(PrintWriter aWriter, int indent, Object aService,
+            StoreDescription parentDesc) throws Exception {
+        if (aService instanceof StandardService) {
+            StandardService service = (StandardService) aService;
+            // Store nested <Listener> elements
+            if (service instanceof Lifecycle) {
+                LifecycleListener listeners[] = ((Lifecycle) service)
+                        .findLifecycleListeners();
+                storeElementArray(aWriter, indent, listeners);
+            }
+            // Store nested <Executor> elements
+            Executor[] executors = service.findExecutors();
+            storeElementArray(aWriter, indent, executors);
+
+            Connector connectors[] = service.findConnectors();
+            storeElementArray(aWriter, indent, connectors);
+
+            // Store nested <Engine> element (or other appropriate container)
+            Container container = service.getContainer();
+            if (container != null) {
+                StoreDescription elementDesc = getRegistry().findDescription(
+                        container.getClass());
+                if (elementDesc != null) {
+                    IStoreFactory factory = elementDesc.getStoreFactory();
+                    factory.store(aWriter, indent, container);
+                }
+            }
+        }
+
+    }
+
+}
\ No newline at end of file

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreAppender.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreAppender.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreAppender.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreAppender.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,390 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.PrintWriter;
+import java.util.Iterator;
+
+import org.apache.catalina.deploy.ResourceBase;
+import org.apache.tomcat.util.IntrospectionUtils;
+
+/**
+ * StoreAppends generate really the xml tag elements
+ * 
+ * @author Peter Rossbach
+ *  
+ */
+public class StoreAppender {
+
+    /**
+     * The set of classes that represent persistable properties.
+     */
+    private static Class persistables[] = { String.class, Integer.class,
+            Integer.TYPE, Boolean.class, Boolean.TYPE, Byte.class, Byte.TYPE,
+            Character.class, Character.TYPE, Double.class, Double.TYPE,
+            Float.class, Float.TYPE, Long.class, Long.TYPE, Short.class,
+            Short.TYPE, };
+
+    /**
+     * print the closing tag
+     * 
+     * @param aWriter
+     * @param aDesc
+     * @throws Exception
+     */
+    public void printCloseTag(PrintWriter aWriter, StoreDescription aDesc)
+            throws Exception {
+        aWriter.print("</");
+        aWriter.print(aDesc.getTag());
+        aWriter.println(">");
+    }
+
+    /**
+     * print only the open tag with all attributes
+     * 
+     * @param aWriter
+     * @param indent
+     * @param bean
+     * @param aDesc
+     * @throws Exception
+     */
+    public void printOpenTag(PrintWriter aWriter, int indent, Object bean,
+            StoreDescription aDesc) throws Exception {
+        aWriter.print("<");
+        aWriter.print(aDesc.getTag());
+        if (aDesc.isAttributes() && bean != null)
+            printAttributes(aWriter, indent, bean, aDesc);
+        aWriter.println(">");
+    }
+
+    /**
+     * Print tag with all attributes
+     * 
+     * @param aWriter
+     * @param indent
+     * @param bean
+     * @param aDesc
+     * @throws Exception
+     */
+    public void printTag(PrintWriter aWriter, int indent, Object bean,
+            StoreDescription aDesc) throws Exception {
+        aWriter.print("<");
+        aWriter.print(aDesc.getTag());
+        if (aDesc.isAttributes() && bean != null)
+            printAttributes(aWriter, indent, bean, aDesc);
+        aWriter.println("/>");
+    }
+
+    /**
+     * print the value from tag as content
+     * 
+     * @param aWriter
+     * @param tag
+     * @param content
+     * @throws Exception
+     */
+    public void printTagContent(PrintWriter aWriter, String tag, String content)
+            throws Exception {
+        aWriter.print("<");
+        aWriter.print(tag);
+        aWriter.print(">");
+        aWriter.print(convertStr(content));
+        aWriter.print("</");
+        aWriter.print(tag);
+        aWriter.println(">");
+    }
+
+    /**
+     * print an array of values
+     * 
+     * @param aWriter
+     * @param tag
+     * @param indent
+     * @param elements
+     */
+    public void printTagValueArray(PrintWriter aWriter, String tag, int indent,
+            String[] elements) {
+        if (elements != null && elements.length > 0) {
+            printIndent(aWriter, indent + 2);
+            aWriter.print("<");
+            aWriter.print(tag);
+            aWriter.print(">");
+            for (int i = 0; i < elements.length; i++) {
+                printIndent(aWriter, indent + 4);
+                aWriter.print(elements[i]);
+                if (i + 1 < elements.length)
+                    aWriter.println(",");
+            }
+            printIndent(aWriter, indent + 2);
+            aWriter.print("</");
+            aWriter.print(tag);
+            aWriter.println(">");
+        }
+    }
+
+    /**
+     * print a array of elements
+     * 
+     * @param aWriter
+     * @param tag
+     * @param indent
+     * @param elements
+     */
+    public void printTagArray(PrintWriter aWriter, String tag, int indent,
+            String[] elements) throws Exception {
+        if (elements != null) {
+            for (int i = 0; i < elements.length; i++) {
+                printIndent(aWriter, indent);
+                printTagContent(aWriter, tag, elements[i]);
+            }
+        }
+    }
+
+    /**
+     * Print some spaces
+     * 
+     * @param aWriter
+     * @param indent
+     *            number of spaces
+     */
+    public void printIndent(PrintWriter aWriter, int indent) {
+        for (int i = 0; i < indent; i++) {
+            aWriter.print(' ');
+        }
+    }
+
+    /**
+     * Store the relevant attributes of the specified JavaBean, plus a
+     * <code>className</code> attribute defining the fully qualified Java
+     * class name of the bean.
+     * 
+     * @param writer
+     *            PrintWriter to which we are storing
+     * @param bean
+     *            Bean whose properties are to be rendered as attributes,
+     * 
+     * @exception Exception
+     *                if an exception occurs while storing
+     */
+    public void printAttributes(PrintWriter writer, int indent, Object bean,
+            StoreDescription desc) throws Exception {
+
+        printAttributes(writer, indent, true, bean, desc);
+
+    }
+
+    /**
+     * Store the relevant attributes of the specified JavaBean.
+     * 
+     * @param writer
+     *            PrintWriter to which we are storing
+     * @param include
+     *            Should we include a <code>className</code> attribute?
+     * @param bean
+     *            Bean whose properties are to be rendered as attributes,
+     * @param desc
+     *            RegistryDescrpitor from this bean
+     * 
+     * @exception Exception
+     *                if an exception occurs while storing
+     */
+    public void printAttributes(PrintWriter writer, int indent,
+            boolean include, Object bean, StoreDescription desc)
+            throws Exception {
+
+        // Render a className attribute if requested
+        if (include && desc != null && !desc.isStandard()) {
+            writer.print(" className=\"");
+            writer.print(bean.getClass().getName());
+            writer.print("\"");
+        }
+
+        // Acquire the list of properties for this bean
+        PropertyDescriptor descriptors[] = Introspector.getBeanInfo(
+                bean.getClass()).getPropertyDescriptors();
+        if (descriptors == null) {
+            descriptors = new PropertyDescriptor[0];
+        }
+
+        // Create blank instance
+        Object bean2 = defaultInstance(bean);
+        for (int i = 0; i < descriptors.length; i++) {
+            if (descriptors[i] instanceof IndexedPropertyDescriptor) {
+                continue; // Indexed properties are not persisted
+            }
+            if (!isPersistable(descriptors[i].getPropertyType())
+                    || (descriptors[i].getReadMethod() == null)
+                    || (descriptors[i].getWriteMethod() == null)) {
+                continue; // Must be a read-write primitive or String
+            }
+            if (desc.isTransientAttribute(descriptors[i].getName())) {
+                continue; // Skip the specified exceptions
+            }
+            Object value = IntrospectionUtils.getProperty(bean, descriptors[i]
+                    .getName());
+            if (value == null) {
+                continue; // Null values are not persisted
+            }
+            Object value2 = IntrospectionUtils.getProperty(bean2,
+                    descriptors[i].getName());
+            if (value.equals(value2)) {
+                // The property has its default value
+                continue;
+            }
+            printAttribute(writer, indent, bean, desc, descriptors[i].getName(), bean2, value);
+        }
+
+        if (bean instanceof ResourceBase) {
+            ResourceBase resource = (ResourceBase) bean;
+            for (Iterator iter = resource.listProperties(); iter.hasNext();) {
+                String name = (String) iter.next();
+                Object value = resource.getProperty(name);
+                if (!isPersistable(value.getClass())) {
+                    continue;
+                }
+                if (desc.isTransientAttribute(name)) {
+                    continue; // Skip the specified exceptions
+                }
+                printValue(writer, indent, name, value);
+
+            }
+        }
+    }
+
+    /**
+     * @param writer
+     * @param indent
+     * @param bean
+     * @param desc
+     * @param attributeName
+     * @param bean2
+     * @param value
+     */
+    protected void printAttribute(PrintWriter writer, int indent, Object bean, StoreDescription desc, String attributeName, Object bean2, Object value) {
+        if (isPrintValue(bean, bean2, attributeName, desc))
+            printValue(writer, indent, attributeName, value);
+    }
+
+    /**
+     * print this Attribute value or not
+     * 
+     * @param bean
+     *            orginal bean
+     * @param bean2
+     *            default bean
+     * @param attrName
+     *            attribute name
+     * @param desc
+     *            StoreDescription from bean
+     * @return True if it's a printing value
+     */
+    public boolean isPrintValue(Object bean, Object bean2, String attrName,
+            StoreDescription desc) {
+        boolean printValue = false;
+
+        Object value = IntrospectionUtils.getProperty(bean, attrName);
+        if (value != null) {
+            Object value2 = IntrospectionUtils.getProperty(bean2, attrName);
+            printValue = !value.equals(value2);
+
+        }
+        return printValue;
+    }
+
+    /**
+     * generate default Instance
+     * 
+     * @param bean
+     * @return an object from same class as bean parameter
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     */
+    public Object defaultInstance(Object bean) throws InstantiationException,
+            IllegalAccessException {
+        return bean.getClass().newInstance();
+    }
+
+    /**
+     * print an attribute value
+     * 
+     * @param writer
+     * @param name
+     * @param value
+     */
+    public void printValue(PrintWriter writer, int indent, String name,
+            Object value) {
+        if (!(value instanceof String)) {
+            value = value.toString();
+        }
+        writer.println();
+        printIndent(writer, indent + 4);
+        writer.print(name);
+        writer.print("=\"");
+        String strValue = convertStr((String) value);
+        writer.print(strValue);
+        writer.print("\"");
+    }
+
+    /**
+     * Given a string, this method replaces all occurrences of ' <', '>', '&',
+     * and '"'.
+     */
+    public String convertStr(String input) {
+
+        StringBuffer filtered = new StringBuffer(input.length());
+        char c;
+        for (int i = 0; i < input.length(); i++) {
+            c = input.charAt(i);
+            if (c == '<') {
+                filtered.append("&lt;");
+            } else if (c == '>') {
+                filtered.append("&gt;");
+            } else if (c == '\'') {
+                filtered.append("&apos;");
+            } else if (c == '"') {
+                filtered.append("&quot;");
+            } else if (c == '&') {
+                filtered.append("&amp;");
+            } else {
+                filtered.append(c);
+            }
+        }
+        return (filtered.toString());
+    }
+
+    /**
+     * Is the specified property type one for which we should generate a
+     * persistence attribute?
+     * 
+     * @param clazz
+     *            Java class to be tested
+     */
+    protected boolean isPersistable(Class clazz) {
+
+        for (int i = 0; i < persistables.length; i++) {
+            if (persistables[i] == clazz) {
+                return (true);
+            }
+        }
+        return (false);
+
+    }
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfig.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfig.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfig.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfig.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.io.PrintWriter;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Host;
+import org.apache.catalina.Server;
+import org.apache.catalina.ServerFactory;
+import org.apache.catalina.Service;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.mbeans.MBeanUtils;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * Store Server/Service/Host/Context at file or PrintWriter. Default server.xml
+ * is at $catalina.base/conf/server.xml
+ * 
+ * @author Peter Rossbach
+ *  
+ */
+public class StoreConfig implements IStoreConfig {
+    private static Log log = LogFactory.getLog(StoreConfig.class);
+
+    private String serverFilename = "conf/server.xml";
+
+    private StoreRegistry registry;
+
+    /**
+     * get server.xml location
+     * 
+     * @return The server file name
+     */
+    public String getServerFilename() {
+        return serverFilename;
+    }
+
+    /**
+     * set new server.xml location
+     * 
+     * @param string
+     */
+    public void setServerFilename(String string) {
+        serverFilename = string;
+    }
+
+    /*
+     * Get the StoreRegistry with all factory to generate the
+     * server.xml/context.xml files
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#getRegistry()
+     */
+    public StoreRegistry getRegistry() {
+        return registry;
+    }
+
+    /*
+     * set StoreRegistry
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#setRegistry(org.apache.catalina.config.ConfigurationRegistry)
+     */
+    public void setRegistry(StoreRegistry aRegistry) {
+        registry = aRegistry;
+    }
+
+    /**
+     * Store current Server
+     * 
+     * @see org.apache.catalina.ServerFactory#getServer()
+     */
+    public synchronized void storeConfig() {
+        store(ServerFactory.getServer());
+    }
+
+    /**
+     * Store Server from Object Name (Catalina:type=Server)
+     * 
+     * @param aServerName
+     *            Server ObjectName
+     * @param backup
+     * @param externalAllowed
+     *            s *
+     * @throws MalformedObjectNameException
+     */
+    public synchronized void storeServer(String aServerName, boolean backup,
+            boolean externalAllowed) throws MalformedObjectNameException {
+        if (aServerName == null || aServerName.length() == 0) {
+            if (log.isErrorEnabled())
+                log.error("Please, call with a correct server ObjectName!");
+            return;
+        }
+        MBeanServer mserver = MBeanUtils.createServer();
+        ObjectName objectName = new ObjectName(aServerName);
+        if (mserver.isRegistered(objectName)) {
+            try {
+                Server aServer = (Server) mserver.getAttribute(objectName,
+                        "managedResource");
+                StoreDescription desc = null;
+                desc = getRegistry().findDescription(StandardContext.class);
+                if (desc != null) {
+                    boolean oldSeparate = desc.isStoreSeparate();
+                    boolean oldBackup = desc.isBackup();
+                    boolean oldExternalAllowed = desc.isExternalAllowed();
+                    try {
+                        desc.setStoreSeparate(true);
+                        desc.setBackup(backup);
+                        desc.setExternalAllowed(externalAllowed);
+                        store((Server) aServer);
+                    } finally {
+                        desc.setStoreSeparate(oldSeparate);
+                        desc.setBackup(oldBackup);
+                        desc.setExternalAllowed(oldExternalAllowed);
+                    }
+                } else
+                    store((Server) aServer);
+            } catch (Exception e) {
+                if (log.isInfoEnabled())
+                    log.info("Object " + aServerName
+                            + " is no a Server instance or store exception", e);
+            }
+        } else if (log.isInfoEnabled())
+            log.info("Server " + aServerName + " not found!");
+    }
+
+    /**
+     * Store a Context from ObjectName
+     * 
+     * @param aContextName
+     *            MBean ObjectName
+     * @param backup
+     * @param externalAllowed
+     * @throws MalformedObjectNameException
+     */
+    public synchronized void storeContext(String aContextName, boolean backup,
+            boolean externalAllowed) throws MalformedObjectNameException {
+        if (aContextName == null || aContextName.length() == 0) {
+            if (log.isErrorEnabled())
+                log.error("Please, call with a correct context ObjectName!");
+            return;
+        }
+        MBeanServer mserver = MBeanUtils.createServer();
+        ObjectName objectName = new ObjectName(aContextName);
+        if (mserver.isRegistered(objectName)) {
+            try {
+                Context aContext = (Context) mserver.getAttribute(objectName,
+                        "managedResource");
+                String configFile = aContext.getConfigFile();
+                if (configFile != null) {
+                    try {
+                        StoreDescription desc = null;
+                        desc = getRegistry().findDescription(
+                                aContext.getClass());
+                        if (desc != null) {
+                            boolean oldSeparate = desc.isStoreSeparate();
+                            boolean oldBackup = desc.isBackup();
+                            boolean oldExternalAllowed = desc
+                                    .isExternalAllowed();
+                            try {
+                                desc.setStoreSeparate(true);
+                                desc.setBackup(backup);
+                                desc.setExternalAllowed(externalAllowed);
+                                desc.getStoreFactory()
+                                        .store(null, -2, aContext);
+                            } finally {
+                                desc.setStoreSeparate(oldSeparate);
+                                desc.setBackup(oldBackup);
+                                desc.setBackup(oldExternalAllowed);
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error(e);
+                    }
+                } else
+                    log.error("Missing configFile at Context "
+                            + aContext.getPath() + " to store!");
+            } catch (Exception e) {
+                if (log.isInfoEnabled())
+                    log
+                            .info(
+                                    "Object "
+                                            + aContextName
+                                            + " is no a context instance or store exception",
+                                    e);
+            }
+        } else if (log.isInfoEnabled())
+            log.info("Context " + aContextName + " not found!");
+    }
+
+    /**
+     * Write the configuration information for this entire <code>Server</code>
+     * out to the server.xml configuration file.
+     *  
+     */
+    public synchronized void store(Server aServer) {
+
+        StoreFileMover mover = new StoreFileMover(System
+                .getProperty("catalina.base"), getServerFilename(),
+                getRegistry().getEncoding());
+        // Open an output writer for the new configuration file
+        try {
+            PrintWriter writer = mover.getWriter();
+
+            try {
+                store(writer, -2, aServer);
+            } finally {
+                // Flush and close the output file
+                try {
+                    writer.flush();
+                } catch (Exception e) {
+                    log.error(e);
+                }
+                try {
+                    writer.close();
+                } catch (Exception e) {
+                    throw (e);
+                }
+            }
+            mover.move();
+        } catch (Exception e) {
+            log.error(e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#store(org.apache.catalina.Context)
+     */
+    public synchronized void store(Context aContext) {
+        String configFile = aContext.getConfigFile();
+        if (configFile != null) {
+            try {
+                StoreDescription desc = null;
+                desc = getRegistry().findDescription(aContext.getClass());
+                if (desc != null) {
+                    boolean old = desc.isStoreSeparate();
+                    try {
+                        desc.setStoreSeparate(true);
+                        desc.getStoreFactory().store(null, -2, aContext);
+                    } finally {
+                        desc.setStoreSeparate(old);
+                    }
+                }
+            } catch (Exception e) {
+                log.error(e);
+            }
+        } else
+            log.error("Missing configFile at Context " + aContext.getPath());
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#store(java.io.PrintWriter,
+     *      int, org.apache.catalina.Context)
+     */
+    public synchronized void store(PrintWriter aWriter, int indent,
+            Context aContext) {
+        boolean oldSeparate = true;
+        StoreDescription desc = null;
+        try {
+            desc = getRegistry().findDescription(aContext.getClass());
+            oldSeparate = desc.isStoreSeparate();
+            desc.setStoreSeparate(false);
+            desc.getStoreFactory().store(aWriter, indent, aContext);
+        } catch (Exception e) {
+            log.error(e);
+        } finally {
+            if (desc != null)
+                desc.setStoreSeparate(oldSeparate);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#store(java.io.PrintWriter,
+     *      int, org.apache.catalina.Host)
+     */
+    public synchronized void store(PrintWriter aWriter, int indent, Host aHost) {
+        try {
+            StoreDescription desc = getRegistry().findDescription(
+                    aHost.getClass());
+            desc.getStoreFactory().store(aWriter, indent, aHost);
+        } catch (Exception e) {
+            log.error(e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.catalina.config.IStoreConfig#store(java.io.PrintWriter,
+     *      int, org.apache.catalina.Service)
+     */
+    public synchronized void store(PrintWriter aWriter, int indent,
+            Service aService) {
+        try {
+            StoreDescription desc = getRegistry().findDescription(
+                    aService.getClass());
+            desc.getStoreFactory().store(aWriter, indent, aService);
+        } catch (Exception e) {
+            log.error(e);
+        }
+    }
+
+    /**
+     * Store the state of this Server MBean (which will recursively store
+     * everything)
+     * 
+     * @param writer
+     * @param indent
+     * @param aServer
+     */
+    public synchronized void store(PrintWriter writer, int indent,
+            Server aServer) {
+        try {
+            StoreDescription desc = getRegistry().findDescription(
+                    aServer.getClass());
+            desc.getStoreFactory().store(writer, indent, aServer);
+        } catch (Exception e) {
+            log.error(e);
+        }
+    }
+
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.io.InputStream;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.mbeans.MBeanUtils;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.modeler.ManagedBean;
+import org.apache.tomcat.util.modeler.Registry;
+
+/**
+ * Load and Register StoreConfig MBean <i>Catalina:type=StoreConfig,resource="url"</i>
+ * 
+ * @author Peter Rossbach
+ */
+public class StoreConfigLifecycleListener implements LifecycleListener {
+    private static Log log = LogFactory
+            .getLog(StoreConfigLifecycleListener.class);
+
+    IStoreConfig storeConfig;
+
+    private String storeConfigClass = "org.apache.catalina.storeconfig.StoreConfig";
+
+    private String storeRegistry = null;
+
+    /*
+     * register StoreRegistry after Start the complete Server
+     * 
+     * @see org.apache.catalina.LifecycleListener#lifecycleEvent(org.apache.catalina.LifecycleEvent)
+     */
+    public void lifecycleEvent(LifecycleEvent event) {
+        if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+            if (event.getSource() instanceof StandardServer) {
+                createMBean();
+            }
+        }
+    }
+
+    /**
+     * create StoreConfig MBean and load StoreRgistry MBeans name is
+     * <i>Catalina:type=StoreConfig </i>
+     */
+    protected void createMBean() {
+        StoreLoader loader = new StoreLoader();
+        try {
+            Class clazz = Class.forName(getStoreConfigClass(), true, this
+                    .getClass().getClassLoader());
+            storeConfig = (IStoreConfig) clazz.newInstance();
+            if (null == getStoreRegistry())
+                // default Loading
+                loader.load();
+            else
+                // load a spezial file registry (url)
+                loader.load(getStoreRegistry());
+            // use the loader Registry
+            storeConfig.setRegistry(loader.getRegistry());
+        } catch (Exception e) {
+            log.error("createMBean load", e);
+            return;
+        }
+        MBeanServer mserver = MBeanUtils.createServer();
+        InputStream descriptor = null;
+        try {
+            ObjectName objectName = new ObjectName("Catalina:type=StoreConfig" );
+            if (!mserver.isRegistered(objectName)) {
+                descriptor = this.getClass().getResourceAsStream(
+                        "mbeans-descriptors.xml");
+                Registry registry = MBeanUtils.createRegistry();
+                registry.loadMetadata(descriptor);
+                mserver.registerMBean(getManagedBean(storeConfig), objectName);
+            }
+        } catch (Exception ex) {
+            log.error("createMBean register MBean", ex);
+
+        } finally {
+            if (descriptor != null) {
+                try {
+                    descriptor.close();
+                    descriptor = null;
+                } catch (Exception ex) {
+                    log.error("createMBean register MBean", ex);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a ManagedBean (StoreConfig)
+     * 
+     * @param object
+     * @return The bean
+     * @throws Exception
+     */
+    protected DynamicMBean getManagedBean(Object object) throws Exception {
+        ManagedBean managedBean = Registry.getRegistry(null, null)
+                .findManagedBean(object.getClass().getName());
+        return managedBean.createMBean(object);
+    }
+
+    /**
+     * @return Returns the storeConfig.
+     */
+    public IStoreConfig getStoreConfig() {
+        return storeConfig;
+    }
+
+    /**
+     * @param storeConfig
+     *            The storeConfig to set.
+     */
+    public void setStoreConfig(IStoreConfig storeConfig) {
+        this.storeConfig = storeConfig;
+    }
+
+    /**
+     * @return Returns the storeConfigClass.
+     */
+    public String getStoreConfigClass() {
+        return storeConfigClass;
+    }
+
+    /**
+     * @param storeConfigClass
+     *            The storeConfigClass to set.
+     */
+    public void setStoreConfigClass(String storeConfigClass) {
+        this.storeConfigClass = storeConfigClass;
+    }
+
+    /**
+     * @return Returns the storeRegistry.
+     */
+    public String getStoreRegistry() {
+        return storeRegistry;
+    }
+
+    /**
+     * @param storeRegistry
+     *            The storeRegistry to set.
+     */
+    public void setStoreRegistry(String storeRegistry) {
+        this.storeRegistry = storeRegistry;
+    }
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreContextAppender.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreContextAppender.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreContextAppender.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreContextAppender.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardHost;
+
+/**
+ * store StandardContext Attributes ... 
+ * 
+ * @author Peter Rossbach
+ *  
+ */
+public class StoreContextAppender extends StoreAppender {
+
+    /**
+     * @param writer
+     * @param indent
+     * @param bean
+     * @param desc
+     * @param attributeName
+     * @param bean2
+     * @param value
+     */
+    protected void printAttribute(PrintWriter writer, int indent, Object bean, StoreDescription desc, String attributeName, Object bean2, Object value) {
+        if (isPrintValue(bean, bean2, attributeName, desc)) {
+            if(attributeName.equals("docBase")) {
+                if(bean instanceof StandardContext) {
+                    String docBase = ((StandardContext)bean).getOriginalDocBase() ;
+                    if(docBase != null)
+                        value = docBase ;
+                }
+            }
+            printValue(writer, indent, attributeName, value);
+        }
+    }
+
+    /*
+     * Print Context Values. <ul><li> Spezial handling to default workDir.
+     * </li><li> Don't save path at external context.xml </li><li> Don't
+     * generate docBase for host.appBase webapps <LI></ul>
+     * 
+     * @see org.apache.catalina.config.StoreAppender#isPrintValue(java.lang.Object,
+     *      java.lang.Object, java.lang.String,
+     *      org.apache.catalina.config.StoreDescription)
+     */
+    public boolean isPrintValue(Object bean, Object bean2, String attrName,
+            StoreDescription desc) {
+        boolean isPrint = super.isPrintValue(bean, bean2, attrName, desc);
+        if (isPrint) {
+            StandardContext context = ((StandardContext) bean);
+            if ("workDir".equals(attrName)) {
+                String defaultWorkDir = getDefaultWorkDir(context);
+                isPrint = !defaultWorkDir.equals(context.getWorkDir());
+            } else if ("path".equals(attrName)) {
+                isPrint = desc.isStoreSeparate() 
+                            && desc.isExternalAllowed()
+                            && context.getConfigFile() == null;
+            } else if ("docBase".equals(attrName)) {
+                Container host = context.getParent();
+                if (host instanceof StandardHost) {
+                    File appBase = getAppBase(((StandardHost) host));
+                    File docBase = getDocBase(context,appBase);
+                    isPrint = !appBase.equals(docBase.getParentFile());
+                }
+            }
+        }
+        return isPrint;
+    }
+
+    protected File getAppBase(StandardHost host) {
+
+        File appBase;
+        File file = new File(host.getAppBase());
+        if (!file.isAbsolute())
+            file = new File(System.getProperty("catalina.base"), host
+                    .getAppBase());
+        try {
+            appBase = file.getCanonicalFile();
+        } catch (IOException e) {
+            appBase = file;
+        }
+        return (appBase);
+
+    }
+
+    protected File getDocBase(StandardContext context, File appBase) {
+
+        File docBase;
+        String contextDocBase = context.getOriginalDocBase() ;
+        if(contextDocBase == null)
+            contextDocBase = context.getDocBase() ;
+        File file = new File(contextDocBase);
+        if (!file.isAbsolute())
+            file = new File(appBase, contextDocBase);
+        try {
+            docBase = file.getCanonicalFile();
+        } catch (IOException e) {
+            docBase = file;
+        }
+        return (docBase);
+
+    }
+
+    /**
+     * Make default Work Dir.
+     * 
+     * @param context
+     * @return The default working directory for the context.
+     */
+    protected String getDefaultWorkDir(StandardContext context) {
+        String defaultWorkDir = null;
+        String contextPath = context.getPath().length() == 0 ? "_" : context
+                .getPath().substring(1);
+        Container host = context.getParent();
+        if (host instanceof StandardHost) {
+            String hostWorkDir = ((StandardHost) host).getWorkDir();
+            if (hostWorkDir != null) {
+                defaultWorkDir = hostWorkDir + File.separator + contextPath;
+            } else {
+                String engineName = context.getParent().getParent().getName();
+                String hostName = context.getParent().getName();
+                defaultWorkDir = "work" + File.separator + engineName
+                        + File.separator + hostName + File.separator
+                        + contextPath;
+            }
+        }
+        return defaultWorkDir;
+    }
+
+    /*
+     * Generate a real default StandardContext TODO read and interpret the
+     * default context.xml and context.xml.default TODO Cache a Default
+     * StandardContext ( with reloading strategy) TODO remove really all
+     * elements, but detection is hard... To Listener or Valve from same class?>
+     * 
+     * @see org.apache.catalina.storeconfig.StoreAppender#defaultInstance(java.lang.Object)
+     */
+    public Object defaultInstance(Object bean) throws InstantiationException,
+            IllegalAccessException {
+        if (bean instanceof StandardContext) {
+            StandardContext defaultContext = new StandardContext();
+            /*
+             * if (!((StandardContext) bean).getOverride()) {
+             * defaultContext.setParent(((StandardContext)bean).getParent());
+             * ContextConfig contextConfig = new ContextConfig();
+             * defaultContext.addLifecycleListener(contextConfig);
+             * contextConfig.setContext(defaultContext);
+             * contextConfig.processContextConfig(new File(contextConfig
+             * .getBaseDir(), "conf/context.xml"));
+             * contextConfig.processContextConfig(new File(contextConfig
+             * .getConfigBase(), "context.xml.default")); }
+             */
+            return defaultContext;
+        } else
+            return super.defaultInstance(bean);
+    }
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreDescription.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreDescription.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreDescription.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreDescription.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Bean of a StoreDescription 
+ * @author Peter Rossbach 
+ * 
+ * <pre>
+ * 
+ *  &lt;Description
+ *  tag=&quot;Context&quot;
+ *  standard=&quot;true&quot;
+ *  default=&quot;true&quot; 
+ *  externalAllowed=&quot;true&quot; 
+ *  storeSeparate=&quot;true&quot;
+ *  backup=&quot;true&quot; 
+ *  childs=&quot;true&quot;
+ *  tagClass=&quot;org.apache.catalina.core.StandardContext&quot;
+ *  storeFactoryClass=&quot;org.apache.catalina.storeconfig.StandardContextSF&quot;
+ *  storeAppenderClass=&quot;org.apache.catalina.storeconfig.StoreContextAppender&quot;&gt;
+ *     &lt;TransientAttribute&gt;available&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;configFile&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;configured&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;displayName&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;distributable&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;domain&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;engineName&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;name&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;publicId&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;replaceWelcomeFiles&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;saveConfig&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;sessionTimeout&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;startupTime&lt;/TransientAttribute&gt;
+ *     &lt;TransientAttribute&gt;tldScanTime&lt;/TransientAttribute&gt;
+ *  &lt;/Description&gt;
+ * 
+ *  
+ * </pre>
+ */
+public class StoreDescription {
+
+    private String id;
+
+    private String tag;
+
+    private String tagClass;
+
+    private boolean standard = false;
+
+    private boolean backup = false;
+
+    private boolean externalAllowed = false;
+
+    private boolean externalOnly = false;
+
+    private boolean myDefault = false;
+
+    private boolean attributes = true;
+
+    private String storeFactoryClass;
+
+    private IStoreFactory storeFactory;
+
+    private String storeWriterClass;
+
+    private boolean childs = false;
+
+    private List transientAttributes;
+
+    private List transientChilds;
+
+    private boolean storeSeparate = false;
+
+    /**
+     * @return Returns the external.
+     */
+    public boolean isExternalAllowed() {
+        return externalAllowed;
+    }
+
+    /**
+     * @param external
+     *            The external to set.
+     */
+    public void setExternalAllowed(boolean external) {
+        this.externalAllowed = external;
+    }
+
+    public boolean isExternalOnly() {
+        return externalOnly;
+    }
+
+    public void setExternalOnly(boolean external) {
+        this.externalOnly = external;
+    }
+
+    /**
+     * @return Returns the standard.
+     */
+    public boolean isStandard() {
+        return standard;
+    }
+
+    /**
+     * @param standard
+     *            The standard to set.
+     */
+    public void setStandard(boolean standard) {
+        this.standard = standard;
+    }
+
+    /**
+     * @return Returns the backup.
+     */
+    public boolean isBackup() {
+        return backup;
+    }
+
+    /**
+     * @param backup
+     *            The backup to set.
+     */
+    public void setBackup(boolean backup) {
+        this.backup = backup;
+    }
+
+    /**
+     * @return Returns the myDefault.
+     */
+    public boolean isDefault() {
+        return myDefault;
+    }
+
+    /**
+     * @param aDefault
+     *            The myDefault to set.
+     */
+    public void setDefault(boolean aDefault) {
+        this.myDefault = aDefault;
+    }
+
+    /**
+     * @return Returns the storeFactory.
+     */
+    public String getStoreFactoryClass() {
+        return storeFactoryClass;
+    }
+
+    /**
+     * @param storeFactoryClass
+     *            The storeFactory to set.
+     */
+    public void setStoreFactoryClass(String storeFactoryClass) {
+        this.storeFactoryClass = storeFactoryClass;
+    }
+
+    /**
+     * @return Returns the storeFactory.
+     */
+    public IStoreFactory getStoreFactory() {
+        return storeFactory;
+    }
+
+    /**
+     * @param storeFactory
+     *            The storeFactory to set.
+     */
+    public void setStoreFactory(IStoreFactory storeFactory) {
+        this.storeFactory = storeFactory;
+    }
+
+    /**
+     * @return Returns the storeWriterClass.
+     */
+    public String getStoreWriterClass() {
+        return storeWriterClass;
+    }
+
+    /**
+     * @param storeWriterClass
+     *            The storeWriterClass to set.
+     */
+    public void setStoreWriterClass(String storeWriterClass) {
+        this.storeWriterClass = storeWriterClass;
+    }
+
+    /**
+     * @return Returns the tagClass.
+     */
+    public String getTag() {
+        return tag;
+    }
+
+    /**
+     * @param tag
+     *            The tag to set.
+     */
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+
+    /**
+     * @return Returns the tagClass.
+     */
+    public String getTagClass() {
+        return tagClass;
+    }
+
+    /**
+     * @param tagClass
+     *            The tagClass to set.
+     */
+    public void setTagClass(String tagClass) {
+        this.tagClass = tagClass;
+    }
+
+    /**
+     * @return Returns the transientAttributes.
+     */
+    public List getTransientAttributes() {
+        return transientAttributes;
+    }
+
+    /**
+     * @param transientAttributes
+     *            The transientAttributes to set.
+     */
+    public void setTransientAttributes(List transientAttributes) {
+        this.transientAttributes = transientAttributes;
+    }
+
+    public void addTransientAttribute(String attribute) {
+        if (transientAttributes == null)
+            transientAttributes = new ArrayList();
+        transientAttributes.add(attribute);
+    }
+
+    public void removeTransientAttribute(String attribute) {
+        if (transientAttributes != null)
+            transientAttributes.remove(attribute);
+    }
+
+    /**
+     * @return Returns the transientChilds.
+     */
+    public List getTransientChilds() {
+        return transientChilds;
+    }
+
+    /**
+     * @param transientChilds
+     *            The transientChilds to set.
+     */
+    public void setTransientChilds(List transientChilds) {
+        this.transientChilds = transientChilds;
+    }
+
+    public void addTransientChild(String classname) {
+        if (transientChilds == null)
+            transientChilds = new ArrayList();
+        transientChilds.add(classname);
+    }
+
+    public void removeTransientChild(String classname) {
+        if (transientChilds != null)
+            transientChilds.remove(classname);
+    }
+
+    /**
+     * is child transient, please don't save this.
+     * 
+     * @param classname
+     * @return is classname attribute?
+     */
+    public boolean isTransientChild(String classname) {
+        if (transientChilds != null)
+            return transientChilds.contains(classname);
+        return false;
+    }
+
+    /**
+     * is attribute transient, please don't save this.
+     * 
+     * @param attribute
+     * @return is transient attribute?
+     */
+    public boolean isTransientAttribute(String attribute) {
+        if (transientAttributes != null)
+            return transientAttributes.contains(attribute);
+        return false;
+    }
+
+    /**
+     * Return the real id or TagClass
+     * 
+     * @return Returns the id.
+     */
+    public String getId() {
+        if (id != null)
+            return id;
+        else
+            return getTagClass();
+    }
+
+    /**
+     * @param id
+     *            The id to set.
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * @return Returns the attributes.
+     */
+    public boolean isAttributes() {
+        return attributes;
+    }
+
+    /**
+     * @param attributes
+     *            The attributes to set.
+     */
+    public void setAttributes(boolean attributes) {
+        this.attributes = attributes;
+    }
+
+    /**
+     * @return True if it's a separate store
+     */
+    public boolean isStoreSeparate() {
+        return storeSeparate;
+    }
+
+    public void setStoreSeparate(boolean storeSeparate) {
+        this.storeSeparate = storeSeparate;
+    }
+
+    /**
+     * @return Returns the childs.
+     */
+    public boolean isChilds() {
+        return childs;
+    }
+
+    /**
+     * @param childs
+     *            The childs to set.
+     */
+    public void setChilds(boolean childs) {
+        this.childs = childs;
+    }
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryBase.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryBase.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryBase.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryBase.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.apache.catalina.util.StringManager;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * StoreFactory saves spezial elements.
+ * Output was generate with StoreAppenders.
+ * 
+ * @author Peter Rossbach
+ * @version 1.0
+ *  
+ */
+public class StoreFactoryBase implements IStoreFactory {
+    private static Log log = LogFactory.getLog(StoreFactoryBase.class);
+
+    private StoreRegistry registry;
+
+    private StoreAppender storeAppender = new StoreAppender();
+
+    /**
+     * The string manager for this package.
+     */
+    protected static final StringManager sm = StringManager
+            .getManager(Constants.Package);
+
+    /**
+     * The descriptive information string for this implementation.
+     */
+    private static final String info = "org.apache.catalina.config.StoreFactoryBase/1.0";
+
+    /**
+     * Return descriptive information about this Facotry implementation and the
+     * corresponding version number, in the format
+     * <code>&lt;description&gt;/&lt;version&gt;</code>.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+
+    /**
+     * @return Returns the storeAppender.
+     */
+    public StoreAppender getStoreAppender() {
+        return storeAppender;
+    }
+
+    /**
+     * @param storeAppender
+     *            The storeAppender to set.
+     */
+    public void setStoreAppender(StoreAppender storeAppender) {
+        this.storeAppender = storeAppender;
+    }
+
+    /*
+     * set Registry
+     * 
+     * @see org.apache.catalina.config.IStoreFactory#setRegistry(org.apache.catalina.config.ConfigurationRegistry)
+     */
+    public void setRegistry(StoreRegistry aRegistry) {
+        registry = aRegistry;
+
+    }
+
+    /*
+     * get Registry
+     * 
+     * @see org.apache.catalina.config.IStoreFactory#getRegistry()
+     */
+    public StoreRegistry getRegistry() {
+
+        return registry;
+    }
+
+    public void storeXMLHead(PrintWriter aWriter) {
+        // Store the beginning of this element
+        aWriter.print("<?xml version=\"1.0\" encoding=\"");
+        aWriter.print(getRegistry().getEncoding());
+        aWriter.println("\"?>");
+    }
+
+    /*
+     * Store a server.xml element with attributes and childs
+     * 
+     * @see org.apache.catalina.storeconfig.IStoreFactory#store(java.io.PrintWriter,
+     *      int, java.lang.Object)
+     */
+    public void store(PrintWriter aWriter, int indent, Object aElement)
+            throws Exception {
+
+        StoreDescription elementDesc = getRegistry().findDescription(
+                aElement.getClass());
+
+        if (elementDesc != null) {
+            if (log.isDebugEnabled())
+                log.debug(sm.getString("factory.storeTag",
+                        elementDesc.getTag(), aElement));
+            getStoreAppender().printIndent(aWriter, indent + 2);
+            if (!elementDesc.isChilds()) {
+                getStoreAppender().printTag(aWriter, indent, aElement,
+                        elementDesc);
+            } else {
+                getStoreAppender().printOpenTag(aWriter, indent + 2, aElement,
+                        elementDesc);
+                storeChilds(aWriter, indent + 2, aElement, elementDesc);
+                getStoreAppender().printIndent(aWriter, indent + 2);
+                getStoreAppender().printCloseTag(aWriter, elementDesc);
+            }
+        } else
+            log.warn(sm.getString("factory.storeNoDescriptor", aElement
+                    .getClass()));
+    }
+
+    /**
+     * Must Implement at subclass for sepzial store childs handling
+     * 
+     * @param aWriter
+     * @param indent
+     * @param aElement
+     * @param elementDesc
+     */
+    public void storeChilds(PrintWriter aWriter, int indent, Object aElement,
+            StoreDescription elementDesc) throws Exception {
+    }
+
+    /**
+     * Store only elements from storeChilds methods that are not a transient
+     * child.
+     * 
+     * @param aWriter current output writer
+     * @param indent indentation level
+     * @param aTagElement current tomcat element
+     * @throws Exception
+     */
+    protected void storeElement(PrintWriter aWriter, int indent,
+            Object aTagElement) throws Exception {
+        if (aTagElement != null) {
+            IStoreFactory elementFactory = getRegistry().findStoreFactory(
+                    aTagElement.getClass());
+
+            if (elementFactory != null) {
+                StoreDescription desc = getRegistry().findDescription(
+                        aTagElement.getClass());
+                if (!desc.isTransientChild(aTagElement.getClass().getName()))
+                    elementFactory.store(aWriter, indent, aTagElement);
+            } else {
+                log.warn(sm.getString("factory.storeNoDescriptor", aTagElement
+                        .getClass()));
+            }
+        }
+    }
+
+    /*
+     * Save a array of elements
+     * @param aWriter current output writer
+     * @param indent indentation level
+     * @param elements list of child elments to store!
+     */
+    protected void storeElementArray(PrintWriter aWriter, int indent,
+            Object[] elements) throws Exception {
+        if (elements != null) {
+            for (int i = 0; i < elements.length; i++) {
+                try {
+                    storeElement(aWriter, indent, elements[i]);
+                } catch (IOException ioe) {
+                    // ingore childs report error them self!
+                    // see StandartContext.storeWithBackup()
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryRule.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryRule.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryRule.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFactoryRule.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.storeconfig;
+
+import org.apache.tomcat.util.digester.Rule;
+import org.xml.sax.Attributes;
+
+/**
+ * <p>
+ * Rule that creates a new <code>IStoreFactory</code> instance, and associates
+ * it with the top object on the stack (which must implement
+ * <code>IStoreFactory</code>).
+ * </p>
+ * 
+ * @author Peter Rossbach
+ */
+
+public class StoreFactoryRule extends Rule {
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * Construct a new instance of this Rule.
+     * 
+     * @param storeFactoryClass
+     *            Default name of the StoreFactory implementation class to be
+     *            created
+     * @param attributeName
+     *            Name of the attribute that optionally includes an override
+     *            name of the IStoreFactory class
+     */
+    public StoreFactoryRule(String storeFactoryClass, String attributeName,
+            String storeAppenderClass, String appenderAttributeName) {
+
+        this.storeFactoryClass = storeFactoryClass;
+        this.attributeName = attributeName;
+        this.appenderAttributeName = appenderAttributeName;
+        this.storeAppenderClass = storeAppenderClass;
+
+    }
+
+    // ----------------------------------------------------- Instance Variables
+
+    /**
+     * The attribute name of an attribute that can override the implementation
+     * class name.
+     */
+    private String attributeName;
+
+    private String appenderAttributeName;
+
+    /**
+     * The name of the <code>IStoreFactory</code> implementation class.
+     */
+    private String storeFactoryClass;
+
+    private String storeAppenderClass;
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Handle the beginning of an XML element.
+     * 
+     * @param attributes
+     *            The attributes of this element
+     * 
+     * @exception Exception
+     *                if a processing error occurs
+     */
+    public void begin(String namespace, String name, Attributes attributes)
+            throws Exception {
+
+        IStoreFactory factory = (IStoreFactory) newInstance(attributeName,
+                storeFactoryClass, attributes);
+        StoreAppender storeAppender = (StoreAppender) newInstance(
+                appenderAttributeName, storeAppenderClass, attributes);
+        factory.setStoreAppender(storeAppender);
+
+        // Add this StoreFactory to our associated component
+        StoreDescription desc = (StoreDescription) digester.peek(0);
+        StoreRegistry registry = (StoreRegistry) digester.peek(1);
+        factory.setRegistry(registry);
+        desc.setStoreFactory(factory);
+
+    }
+
+    /**
+     * create new instance from attribte className!
+     * 
+     * @param attr class Name attribute
+     * @param defaultName Default Class
+     * @param attributes current digester attribute elements
+     * @return new config object instance
+     * @throws ClassNotFoundException
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     */
+    protected Object newInstance(String attr, String defaultName,
+            Attributes attributes) throws ClassNotFoundException,
+            InstantiationException, IllegalAccessException {
+        String className = defaultName;
+        if (attr != null) {
+            String value = attributes.getValue(attr);
+            if (value != null)
+                className = value;
+        }
+        Class clazz = Class.forName(className);
+        return clazz.newInstance();
+    }
+}
\ No newline at end of file

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFileMover.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFileMover.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFileMover.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreFileMover.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.sql.Timestamp;
+
+/**
+ * Move server.xml or context.xml as backup
+ * 
+ * @author Peter Rossbach
+ * 
+ * TODO Get Encoding from Registry
+ */
+public class StoreFileMover {
+
+    private String filename = "conf/server.xml";
+
+    private String encoding = "UTF-8";
+
+    private String basename = System.getProperty("catalina.base");
+
+    private File configOld;
+
+    private File configNew;
+
+    private File configSave;
+
+    /**
+     * @return Returns the configNew.
+     */
+    public File getConfigNew() {
+        return configNew;
+    }
+
+    /**
+     * @return Returns the configOld.
+     */
+    public File getConfigOld() {
+        return configOld;
+    }
+
+    /**
+     * @return Returns the configSave.
+     */
+    public File getConfigSave() {
+        return configSave;
+    }
+
+    /**
+     * @return Returns the basename.
+     */
+    public String getBasename() {
+        return basename;
+    }
+
+    /**
+     * @param basename
+     *            The basename to set.
+     */
+    public void setBasename(String basename) {
+        this.basename = basename;
+    }
+
+    /**
+     * @return The file name
+     */
+    public String getFilename() {
+        return filename;
+    }
+
+    /**
+     * @param string
+     */
+    public void setFilename(String string) {
+        filename = string;
+    }
+
+    /**
+     * @return The encoding
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * @param string
+     */
+    public void setEncoding(String string) {
+        encoding = string;
+    }
+
+    /**
+     * Calculate file objects for the old and new configuration files.
+     */
+    public StoreFileMover(String basename, String filename, String encoding) {
+        setBasename(basename);
+        setEncoding(encoding);
+        setFilename(filename);
+        init();
+    }
+
+    /**
+     * Calculate file objects for the old and new configuration files.
+     */
+    public StoreFileMover() {
+        init();
+    }
+
+    /**
+     * generate the Filename to new with TimeStamp
+     */
+    public void init() {
+        String configFile = getFilename();
+        configOld = new File(configFile);
+        if (!configOld.isAbsolute()) {
+            configOld = new File(getBasename(), configFile);
+        }
+        configNew = new File(configFile + ".new");
+        if (!configNew.isAbsolute()) {
+            configNew = new File(getBasename(), configFile + ".new");
+        }
+        if (!configNew.getParentFile().exists()) {
+            configNew.getParentFile().mkdirs();
+        }
+        String sb = getTimeTag();
+        configSave = new File(configFile + sb);
+        if (!configSave.isAbsolute()) {
+            configSave = new File(getBasename(), configFile + sb);
+        }
+    }
+
+    /**
+     * Shuffle old->save and new->old
+     * 
+     * @throws IOException
+     */
+    public void move() throws IOException {
+        if (configOld.renameTo(configSave)) {
+            if (!configNew.renameTo(configOld)) {
+                configSave.renameTo(configOld);
+                throw new IOException("Cannot rename "
+                        + configNew.getAbsolutePath() + " to "
+                        + configOld.getAbsolutePath());
+            }
+        } else {
+            if (!configOld.exists()) {
+                if (!configNew.renameTo(configOld)) {
+                    throw new IOException("Cannot move "
+                            + configNew.getAbsolutePath() + " to "
+                            + configOld.getAbsolutePath());
+                }
+            } else {
+                throw new IOException("Cannot rename "
+                    + configOld.getAbsolutePath() + " to "
+                    + configSave.getAbsolutePath());
+            }
+        }
+    }
+
+    /**
+     * Open an output writer for the new configuration file
+     * 
+     * @return The writer
+     * @throws IOException
+     */
+    public PrintWriter getWriter() throws IOException {
+        PrintWriter writer = null;
+        try {
+            writer = new PrintWriter(new OutputStreamWriter(
+                    new FileOutputStream(configNew), getEncoding()));
+        } catch (IOException e) {
+            if (writer != null) {
+                try {
+                    writer.close();
+                } catch (Throwable t) {
+                    ;
+                }
+            }
+            throw (e);
+        }
+        return writer;
+    }
+
+    /**
+     * Time value for backup yyyy-mm-dd.hh-mm-ss
+     * 
+     * @return The time
+     */
+    protected String getTimeTag() {
+        String ts = (new Timestamp(System.currentTimeMillis())).toString();
+        //        yyyy-mm-dd hh:mm:ss
+        //        0123456789012345678
+        StringBuffer sb = new StringBuffer(".");
+        sb.append(ts.substring(0, 10));
+        sb.append('.');
+        sb.append(ts.substring(11, 13));
+        sb.append('-');
+        sb.append(ts.substring(14, 16));
+        sb.append('-');
+        sb.append(ts.substring(17, 19));
+        return sb.toString();
+    }
+
+}

Added: tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreLoader.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreLoader.java?rev=1399731&view=auto
==============================================================================
--- tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreLoader.java (added)
+++ tomcat/sandbox/storeconfig6/src/main/java/org/apache/catalina/storeconfig/StoreLoader.java Thu Oct 18 16:37:42 2012
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.digester.Digester;
+import org.xml.sax.SAXException;
+
+/**
+ * 
+ * @author Peter Rossbach
+ * 
+ * <b>XML Format </b>
+ * 
+ * <pre>
+ *    
+ *       &lt;Registry name=&quot;&quot; encoding=&quot;UTF8&quot; &gt;
+ *       &lt;Description tag=&quot;Server&quot; standard=&quot;true&quot; default=&quot;true&quot;/&gt; 
+ *          tagClass=&quot;org.apache.catalina.core.StandardServer&quot;
+ *          storeFactory=&quot;org.apache.catalina.storeconfig.StandardServerSF&quot;&gt;
+ *        &lt;TransientAttributes&gt;
+ *          &lt;Attribute&gt;&lt;/Attribute&gt;
+ *        &lt;/TransientAttributes&gt;
+ *        &lt;TransientChilds&gt;
+ *          &lt;Child&gt;&lt;/Child&gt;
+ *        &lt;/TransientChilds&gt;
+ *       &lt;/Description&gt;
+ *   ...
+ *       &lt;/Tegistry&gt;
+ *     
+ * </pre>
+ * 
+ * 
+ * Convention:
+ * <ul>
+ * <li>Factories at subpackage <i>org.apache.catalina.core.storeconfig.xxxSF
+ * </i>.</li>
+ * <li>Element name are the unique Class name</li>
+ * <li>SF for StoreFactory</li>
+ * <li>standard implementation is false</li>
+ * </ul>
+ * other things:
+ * <ul>
+ * <li>Registry XML format is a very good option</li>
+ * <li>Store format is not fix</li>
+ * <li>We hope with the parent declaration we can build recursive child store
+ * operation //dream</li>
+ * <li>Problem is to access child data from array,collections or normal detail
+ * object</li>
+ * <li>Default definitions for Listener, Valve Resource? - Based on interface
+ * type!</li>
+ * </ul>
+ */
+public class StoreLoader {
+    private static Log log = LogFactory.getLog(StoreLoader.class);
+
+    /**
+     * The <code>Digester</code> instance used to parse registry descriptors.
+     */
+    protected static Digester digester = createDigester();
+
+    private StoreRegistry registry;
+    
+    private URL registryResource ;
+
+    /**
+     * @return Returns the registry.
+     */
+    public StoreRegistry getRegistry() {
+        return registry;
+    }
+
+    /**
+     * @param registry
+     *            The registry to set.
+     */
+    public void setRegistry(StoreRegistry registry) {
+        this.registry = registry;
+    }
+
+    /**
+     * Create and configure the Digester we will be using for setup store
+     * registry.
+     */
+    protected static Digester createDigester() {
+        long t1 = System.currentTimeMillis();
+        // Initialize the digester
+        Digester digester = new Digester();
+        digester.setValidating(false);
+        digester.setClassLoader(StoreRegistry.class.getClassLoader());
+
+        // Configure the actions we will be using
+        digester.addObjectCreate("Registry",
+                "org.apache.catalina.storeconfig.StoreRegistry", "className");
+        digester.addSetProperties("Registry");
+        digester
+                .addObjectCreate("Registry/Description",
+                        "org.apache.catalina.storeconfig.StoreDescription",
+                        "className");
+        digester.addSetProperties("Registry/Description");
+        digester.addRule("Registry/Description", new StoreFactoryRule(
+                "org.apache.catalina.storeconfig.StoreFactoryBase",
+                "storeFactoryClass",
+                "org.apache.catalina.storeconfig.StoreAppender",
+                "storeAppenderClass"));
+        digester.addSetNext("Registry/Description", "registerDescription",
+                "org.apache.catalina.storeconfig.StoreDescription");
+        digester.addCallMethod("Registry/Description/TransientAttribute",
+                "addTransientAttribute", 0);
+        digester.addCallMethod("Registry/Description/TransientChild",
+                "addTransientChild", 0);
+
+        long t2 = System.currentTimeMillis();
+        if (log.isDebugEnabled())
+            log.debug("Digester for server-registry.xml created " + (t2 - t1));
+        return (digester);
+
+    }
+
+    /**
+     * 
+     * @param aFile
+     * @return The server file
+     */
+    protected File serverFile(String aFile) {
+
+        if (aFile == null || (aFile != null && aFile.length() < 1))
+            aFile = "server-registry.xml";
+        File file = new File(aFile);
+        if (!file.isAbsolute())
+            file = new File(System.getProperty("catalina.base") + "/conf",
+                    aFile);
+        try {
+            file = file.getCanonicalFile();
+        } catch (IOException e) {
+            log.error(e);
+        }
+        return (file);
+    }
+
+    /**
+     * Load Description from external source
+     * 
+     * @param aURL
+     */
+    public void load(String aURL) {
+        synchronized (digester) {
+            File aRegistryFile = serverFile(aURL);
+            try {
+                registry = (StoreRegistry) digester.parse(aRegistryFile);
+                registryResource = aRegistryFile.toURL();
+            } catch (IOException e) {
+                log.error(e);
+            } catch (SAXException e) {
+                log.error(e);
+            }
+        }
+
+    }
+
+    /**
+     * Load from defaults
+     * <ul>
+     * <li>System Property URL catalina.storeregistry</li>
+     * <li>File $catalina.base/conf/server-registry.xml</li>
+     * <li>class resource org/apache/catalina/storeconfig/server-registry.xml
+     * </li>
+     * </ul>
+     */
+    public void load() {
+
+        InputStream is = null;
+        Throwable error = null;
+        registryResource = null ;
+        try {
+            String configUrl = getConfigUrl();
+            if (configUrl != null) {
+                is = (new URL(configUrl)).openStream();
+                if (log.isInfoEnabled())
+                    log
+                            .info("Find registry server-registry.xml from system property at url "
+                                    + configUrl);
+                ;
+                registryResource = new URL(configUrl);
+            }
+        } catch (Throwable t) {
+            // Ignore
+        }
+        if (is == null) {
+            try {
+                File home = new File(getCatalinaBase());
+                File conf = new File(home, "conf");
+                File reg = new File(conf, "server-registry.xml");
+                is = new FileInputStream(reg);
+                if (log.isInfoEnabled())
+                    log.info("Find registry server-registry.xml at file "
+                            + reg.getCanonicalPath());
+                ;
+                registryResource = reg.toURL() ;
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+        if (is == null) {
+            try {
+                is = StoreLoader.class
+                        .getResourceAsStream("/org/apache/catalina/storeconfig/server-registry.xml");
+                if (log.isInfoEnabled())
+                    log
+                            .info("Find registry server-registry.xml at classpath resource");
+                registryResource = StoreLoader.class
+                    .getResource("/org/apache/catalina/storeconfig/server-registry.xml");
+                
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+        if (is != null) {
+            try {
+                synchronized (digester) {
+                    registry = (StoreRegistry) digester.parse(is);
+                }
+            } catch (Throwable t) {
+                error = t;
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+        if ((is == null) || (error != null)) {
+            log.error(error);
+        }
+    }
+
+    /**
+     * Get the value of the catalina.home environment variable.
+     */
+    private static String getCatalinaHome() {
+        return System.getProperty("catalina.home", System
+                .getProperty("user.dir"));
+    }
+
+    /**
+     * Get the value of the catalina.base environment variable.
+     */
+    private static String getCatalinaBase() {
+        return System.getProperty("catalina.base", getCatalinaHome());
+    }
+
+    /**
+     * Get the value of the configuration URL.
+     */
+    private static String getConfigUrl() {
+        return System.getProperty("catalina.storeconfig");
+    }
+    
+    
+
+    /**
+     * @return Returns the registryResource.
+     */
+    public URL getRegistryResource() {
+        return registryResource;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org