diff artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java @ 473:d0ac790a6c89 dive4elements-move

Moved directories to org.dive4elements
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 10:57:18 +0200
parents artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java@ddfaf255bb40
children 415df0fc4fa1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java	Thu Apr 25 10:57:18 2013 +0200
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2010 by Intevation GmbH
+ *
+ * This program is free software under the LGPL (>=v2.1)
+ * Read the file LGPL.txt coming with the software for details
+ * or visit http://www.gnu.org/licenses/ if it does not exist.
+ */
+
+package de.intevation.artifactdatabase;
+
+import de.intevation.artifacts.common.utils.Config;
+
+import de.intevation.artifacts.ArtifactCollectionFactory;
+import de.intevation.artifacts.ArtifactContextFactory;
+import de.intevation.artifacts.ArtifactFactory;
+import de.intevation.artifacts.CallContext;
+import de.intevation.artifacts.GlobalContext;
+import de.intevation.artifacts.Hook;
+import de.intevation.artifacts.ServiceFactory;
+import de.intevation.artifacts.UserFactory;
+
+import de.intevation.artifacts.common.utils.StringUtils;
+
+import de.intevation.artifactdatabase.rest.HTTPServer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Bootstrap facility for the global context and the artifact factories.
+ *
+ * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
+ */
+public class FactoryBootstrap
+{
+    private static Logger logger = Logger.getLogger(FactoryBootstrap.class);
+
+    /**
+     * XPath to figure out the class name of the context factory from
+     * the global configuration.
+     */
+    public static final String CONTEXT_FACTORY =
+        "/artifact-database/factories/context-factory/text()";
+
+    /**
+     * The name of the default context factory.
+     */
+    public static final String DEFAULT_CONTEXT_FACTORY =
+        "de.intevation.artifactdatabase.DefaultArtifactContextFactory";
+
+    /**
+     * XPath to figure out the names of the artifact factories from
+     * the global configuration to be exposed by the artifact database.
+     */
+    public static final String ARTIFACT_FACTORIES =
+        "/artifact-database/factories/artifact-factories/artifact-factory";
+
+    /**
+     * XPath to figure out the names of the service factories from
+     * the global configuration to build the services offered by the
+     * artifact database.
+     */
+    public static final String SERVICE_FACTORIES =
+        "/artifact-database/factories/service-factories/service-factory";
+
+    /**
+     * XPath to figure out the class name of the user factory from global
+     * configuration.
+     */
+    public static final String USER_FACTORY =
+        "/artifact-database/factories/user-factory";
+
+    /**
+     * The name of the default user factory.
+     */
+    public static final String DEFAULT_USER_FACTORY =
+        "de.intevation.artifactdatabase.DefaultUserFactory";
+
+    /**
+     * XPath to figure out the class name of the collection factory from global
+     * configuration.
+     */
+    public static final String COLLECTION_FACTORY =
+        "/artifact-database/factories/collection-factory";
+
+    /**
+     * The name of the default user factory.
+     */
+    public static final String DEFAULT_COLLECTION_FACTORY =
+        "de.intevation.artifactdatabase.DefaultArtifactCollectionFactory";
+
+    /**
+     * XPath to figure out the secret used to sign the artifact exports
+     * made by the artfifact database server.
+     */
+    public static final String EXPORT_SECRET =
+        "/artifact-database/export-secret/text()";
+
+    /**
+     * XPAth that points to a configuration node for a CallContext.Listener.
+     */
+    public static final String CALLCONTEXT_LISTENER =
+        "/artifact-database/callcontext-listener";
+
+    /**
+     * XPath that points to configuration nodes for hooks.
+     */
+    public static final String HOOKS =
+        "/artifact-database/hooks/hook";
+
+    public static final String HTTP_SERVER =
+        "/artifact-database/rest-server/http-server/text()";
+
+    public static final String DEFAULT_HTTP_SERVER =
+        "de.intevation.artifactdatabase.rest.Standalone";
+
+    public static final String LIFETIME_LISTENERS =
+        "/artifact-database/lifetime-listeners/listener";
+
+    public static final String BACKEND_LISTENERS =
+        "/artifact-database/backend-listeners/listener";
+
+    /**
+     * Default export signing secret.
+     * <strong>PLEASE CHANGE THE SECRET VIA THE XPATH EXPORT_SECRET
+     * IN THE CONFIGURATION.</strong>.
+     */
+    public static final String DEFAULT_EXPORT_SECRET =
+        "!!!CHANGE ME! I'M NO SECRET!!!";
+
+    /**
+     * Reference to the global context build by the global context factory.
+     */
+    protected GlobalContext context;
+
+    /**
+     * List of the artifact factories to be exposed by the
+     * artifact database.
+     */
+    protected ArtifactFactory [] artifactFactories;
+
+    /**
+     * List of service factories which creates services that are
+     * exposed by the artifact database.
+     */
+    protected ServiceFactory [] serviceFactories;
+
+    /**
+     * The factory that is used to create and list users.
+     */
+    protected UserFactory userFactory;
+
+    /**
+     * The factory that is used to create new artifact collections.
+     */
+    protected ArtifactCollectionFactory collectionFactory;
+
+    /**
+     * The CallContext.Listener.
+     */
+    protected CallContext.Listener callContextListener;
+
+    protected List<Hook> postFeedHooks;
+
+    protected List<Hook> postAdvanceHooks;
+
+    protected List<Hook> postDescribeHooks;
+
+    protected List<LifetimeListener> lifetimeListeners;
+
+    protected List<BackendListener> backendListeners;
+
+    /**
+     * byte array holding the export signing secret.
+     */
+    protected byte [] exportSecret;
+
+    protected HTTPServer httpServer;
+
+
+    /**
+     * Default constructor
+     */
+    public FactoryBootstrap() {
+    }
+
+    void buildContext() {
+        String className = Config.getStringXPath(
+            CONTEXT_FACTORY, DEFAULT_CONTEXT_FACTORY);
+
+        ArtifactContextFactory factory = null;
+
+        try {
+            Class clazz = Class.forName(className);
+            factory = (ArtifactContextFactory)clazz.newInstance();
+        }
+        catch (ClassNotFoundException cnfe) {
+            logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+
+        if (factory == null) {
+            factory = new DefaultArtifactContextFactory();
+        }
+
+        logger.info("Using class '" + factory.getClass().getName()
+            + "' for context creation.");
+
+        context = factory.createArtifactContext(Config.getConfig());
+    }
+
+
+    /**
+     * Scans the global configuration to load the configured collection factory
+     * and sets it up.
+     */
+    protected void loadCollectionFactory() {
+
+        logger.info("loading collection factory.");
+
+        Node factory = Config.getNodeXPath(COLLECTION_FACTORY);
+
+        String className = Config.getStringXPath(
+            factory, "text()", DEFAULT_COLLECTION_FACTORY);
+
+        try {
+            Class clazz       = Class.forName(className);
+            collectionFactory = (ArtifactCollectionFactory) clazz.newInstance();
+
+            collectionFactory.setup(Config.getConfig(), factory);
+        }
+        catch (ClassNotFoundException cnfe) {
+            logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+    }
+
+    /**
+     * Scans the global configuration to load the configured
+     * artifact factories and sets them up.
+     */
+    protected void loadArtifactFactories() {
+
+        logger.info("loading artifact factories");
+
+        ArrayList loadedFactories = new ArrayList();
+
+        NodeList nodes = Config.getNodeSetXPath(ARTIFACT_FACTORIES);
+
+        if (nodes == null) {
+            logger.warn("No factories found");
+        }
+
+        Document config = Config.getConfig();
+
+        for (int i = 0, N = nodes != null ? nodes.getLength() : 0; i < N; ++i) {
+            String className = nodes.item(i).getTextContent().trim();
+
+            ArtifactFactory factory = null;
+
+            try {
+                Class clazz = Class.forName(className);
+                factory = (ArtifactFactory)clazz.newInstance();
+            }
+            catch (ClassNotFoundException cnfe) {
+                logger.error(cnfe.getLocalizedMessage(), cnfe);
+            }
+            catch (InstantiationException ie) {
+                logger.error(ie.getLocalizedMessage(), ie);
+            }
+            catch (ClassCastException cce) {
+                logger.error(cce.getLocalizedMessage(), cce);
+            }
+            catch (IllegalAccessException iae) {
+                logger.error(iae.getLocalizedMessage(), iae);
+            }
+
+            if (factory != null) {
+                factory.setup(config, nodes.item(i));
+                loadedFactories.add(factory);
+                logger.info("Registering '"
+                    + factory.getName() + "' as artifact factory.");
+            }
+        }
+
+        artifactFactories = (ArtifactFactory [])loadedFactories.toArray(
+            new ArtifactFactory[loadedFactories.size()]);
+    }
+
+    /**
+     * Scans the global configuration for the configured service factories
+     * and sets them up.
+     */
+    protected void loadServiceFactories() {
+
+        logger.info("loading service factories");
+
+        ArrayList loadedFactories = new ArrayList();
+
+        NodeList nodes = Config.getNodeSetXPath(SERVICE_FACTORIES);
+
+        if (nodes == null) {
+            logger.warn("No factories found");
+        }
+
+        Document config = Config.getConfig();
+
+        for (int i = 0, N = nodes != null ? nodes.getLength() : 0; i < N; ++i) {
+            String className = nodes.item(i).getTextContent().trim();
+
+            ServiceFactory factory = null;
+
+            try {
+                Class clazz = Class.forName(className);
+                factory = (ServiceFactory)clazz.newInstance();
+            }
+            catch (ClassNotFoundException cnfe) {
+                logger.error(cnfe.getLocalizedMessage(), cnfe);
+            }
+            catch (InstantiationException ie) {
+                logger.error(ie.getLocalizedMessage(), ie);
+            }
+            catch (ClassCastException cce) {
+                logger.error(cce.getLocalizedMessage(), cce);
+            }
+            catch (IllegalAccessException iae) {
+                logger.error(iae.getLocalizedMessage(), iae);
+            }
+
+            if (factory != null) {
+                factory.setup(config, nodes.item(i));
+                loadedFactories.add(factory);
+                logger.info( "Registering '" + factory.getName()
+                    + "' as service factory.");
+            }
+        }
+
+        serviceFactories = (ServiceFactory [])loadedFactories.toArray(
+            new ServiceFactory[loadedFactories.size()]);
+    }
+
+
+    /**
+     * Scans the global configuration for the configured user factory.
+     */
+    protected void loadUserFactory() {
+        logger.info("loading user factory");
+
+        Node factory = Config.getNodeXPath(USER_FACTORY);
+
+        String className = Config.getStringXPath(
+            factory, "text()", DEFAULT_USER_FACTORY);
+
+        try {
+            Class clazz = Class.forName(className);
+            userFactory = (UserFactory) clazz.newInstance();
+
+            userFactory.setup(Config.getConfig(), factory);
+        }
+        catch (ClassNotFoundException cnfe) {
+                logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+    }
+
+
+    protected void loadCallContextListener() {
+        logger.info("loading CallContext.Listener");
+
+        Node listener = Config.getNodeXPath(CALLCONTEXT_LISTENER);
+
+        if (listener == null) {
+            return;
+        }
+
+        String className = Config.getStringXPath(listener, "text()");
+
+        try {
+            Class clazz         = Class.forName(className);
+            callContextListener = (CallContext.Listener) clazz.newInstance();
+
+            callContextListener.setup(Config.getConfig(), listener);
+        }
+        catch (ClassNotFoundException cnfe) {
+            logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+    }
+
+    protected void loadHTTPServer() {
+        logger.info("loading HTTPServer");
+
+        String className = Config.getStringXPath(
+            HTTP_SERVER, DEFAULT_HTTP_SERVER);
+
+        logger.info("using HTTP server: " + className);
+
+        try {
+            Class clazz = Class.forName(className);
+            httpServer  = (HTTPServer)clazz.newInstance();
+
+            httpServer.setup(Config.getConfig());
+        }
+        catch (ClassNotFoundException cnfe) {
+            logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+    }
+
+    protected void loadLifetimeListeners() {
+        logger.info("loading lifetime listeners");
+
+        NodeList nodes = Config.getNodeSetXPath(LIFETIME_LISTENERS);
+
+        if (nodes == null) {
+            logger.debug("no lifetime listeners configure");
+            return;
+        }
+
+        List<LifetimeListener> ltls = new ArrayList<LifetimeListener>();
+
+        for (int i = 0, N = nodes.getLength(); i < N; ++i) {
+            Node node = nodes.item(i);
+            String className = node.getTextContent();
+            if (className == null
+            || (className = className.trim()).length() == 0) {
+                continue;
+            }
+            try {
+                Class clazz = Class.forName(className);
+                LifetimeListener listener =
+                    (LifetimeListener)clazz.newInstance();
+
+                listener.setup(Config.getConfig());
+
+                ltls.add(listener);
+            }
+            catch (ClassNotFoundException cnfe) {
+                logger.error(cnfe.getLocalizedMessage(), cnfe);
+            }
+            catch (InstantiationException ie) {
+                logger.error(ie.getLocalizedMessage(), ie);
+            }
+            catch (ClassCastException cce) {
+                logger.error(cce.getLocalizedMessage(), cce);
+            }
+            catch (IllegalAccessException iae) {
+                logger.error(iae.getLocalizedMessage(), iae);
+            }
+        }
+
+        lifetimeListeners = ltls;
+    }
+
+    protected void loadBackendListeners() {
+        logger.info("loading backend listeners");
+
+        NodeList nodes = Config.getNodeSetXPath(BACKEND_LISTENERS);
+
+        if (nodes == null) {
+            logger.debug("no backend listeners configure");
+            return;
+        }
+
+        List<BackendListener> bls = new ArrayList<BackendListener>();
+
+        for (int i = 0, N = nodes.getLength(); i < N; ++i) {
+            Node node = nodes.item(i);
+            String className = node.getTextContent();
+            if (className == null
+            || (className = className.trim()).length() == 0) {
+                continue;
+            }
+            try {
+                Class clazz = Class.forName(className);
+                BackendListener listener =
+                    (BackendListener)clazz.newInstance();
+
+                bls.add(listener);
+            }
+            catch (ClassNotFoundException cnfe) {
+                logger.error(cnfe.getLocalizedMessage(), cnfe);
+            }
+            catch (InstantiationException ie) {
+                logger.error(ie.getLocalizedMessage(), ie);
+            }
+            catch (ClassCastException cce) {
+                logger.error(cce.getLocalizedMessage(), cce);
+            }
+            catch (IllegalAccessException iae) {
+                logger.error(iae.getLocalizedMessage(), iae);
+            }
+        }
+
+        backendListeners = bls;
+    }
+
+    protected void loadHooks() {
+        logger.info("loading hooks");
+
+        postFeedHooks     = new ArrayList<Hook>();
+        postAdvanceHooks  = new ArrayList<Hook>();
+        postDescribeHooks = new ArrayList<Hook>();
+
+        NodeList nodes = Config.getNodeSetXPath(HOOKS);
+
+        if (nodes == null) {
+            logger.info("No hooks found");
+            return;
+        }
+
+        for (int i = 0, len = nodes.getLength(); i < len; i++) {
+            Node   cfg     = nodes.item(i);
+            String applies = Config.getStringXPath(cfg, "@applies");
+
+            if (applies == null || applies.length() == 0) {
+                continue;
+            }
+
+            Hook     hook  = loadHook(cfg);
+            String[] apply = applies.split(",");
+
+            for (String a: apply) {
+                a = a.trim().toLowerCase();
+
+                if (a.equals("post-feed")) {
+                    postFeedHooks.add(hook);
+                }
+                else if (a.equals("post-advance")) {
+                    postAdvanceHooks.add(hook);
+                }
+                else if (a.equals("post-describe")) {
+                    postDescribeHooks.add(hook);
+                }
+            }
+        }
+    }
+
+    protected Hook loadHook(Node hookCfg) {
+        if (hookCfg == null) {
+            return null;
+        }
+
+        Hook hook = null;
+
+        String className = Config.getStringXPath(hookCfg, "@class");
+
+        try {
+            Class clazz = Class.forName(className);
+            hook        = (Hook) clazz.newInstance();
+
+            hook.setup(hookCfg);
+        }
+        catch (ClassNotFoundException cnfe) {
+            logger.error(cnfe.getLocalizedMessage(), cnfe);
+        }
+        catch (InstantiationException ie) {
+            logger.error(ie.getLocalizedMessage(), ie);
+        }
+        catch (ClassCastException cce) {
+            logger.error(cce.getLocalizedMessage(), cce);
+        }
+        catch (IllegalAccessException iae) {
+            logger.error(iae.getLocalizedMessage(), iae);
+        }
+
+        return hook;
+    }
+
+    /**
+     * Fetches the export signing secret from the global configuration.
+     * If none is found if defaults to the DEFAULT_EXORT_SECRET which
+     * is insecure.
+     */
+    protected void setupExportSecret() {
+        String secret = Config.getStringXPath(EXPORT_SECRET);
+
+        if (secret == null) {
+            logger.warn("NO EXPORT SECRET SET! USING INSECURE DEFAULT!");
+            secret = DEFAULT_EXPORT_SECRET;
+        }
+
+        exportSecret = StringUtils.getUTF8Bytes(secret);
+    }
+
+    /**
+     * Loads all the dynamic classes configured by the global configuration.
+     */
+    public void boot() {
+        setupExportSecret();
+        buildContext();
+        loadCollectionFactory();
+        loadArtifactFactories();
+        loadServiceFactories();
+        loadUserFactory();
+        loadCallContextListener();
+        loadHTTPServer();
+        loadHooks();
+        loadLifetimeListeners();
+        loadBackendListeners();
+    }
+
+    /**
+     * Returns the artifact collection factory.
+     *
+     * @return the artifact collection factory.
+     */
+    public ArtifactCollectionFactory getArtifactCollectionFactory() {
+        return collectionFactory;
+    }
+
+    /**
+     * Returns the list of ready to use artifact factories.
+     * @return The list of artifact factories.
+     */
+    public ArtifactFactory [] getArtifactFactories() {
+        return artifactFactories;
+    }
+
+    /**
+     * Returns the ready to use service factories.
+     * @return The list of service factories.
+     */
+    public ServiceFactory [] getServiceFactories() {
+        return serviceFactories;
+    }
+
+    /**
+     * Returns the user factory.
+     *
+     * @return the user factory.
+     */
+    public UserFactory getUserFactory() {
+        return userFactory;
+    }
+
+    /**
+     * Returns the global context created by the global context factory.
+     * @return The global context.
+     */
+    public GlobalContext getContext() {
+        return context;
+    }
+
+    /**
+     * Returns the signing secret to be used when ex- and importing
+     * artifacts from and into the artifact database.
+     * @return the byte array containg the signing secret.
+     */
+    public byte [] getExportSecret() {
+        return exportSecret;
+    }
+
+    /**
+     * Returns a CallContext.Listener if configured or null.
+     *
+     * @return a CallContext.Listener.
+     */
+    public CallContext.Listener getCallContextListener() {
+        return callContextListener;
+    }
+
+    public List<Hook> getPostFeedHooks() {
+        return postFeedHooks;
+    }
+
+    public List<Hook> getPostAdvanceHooks() {
+        return postAdvanceHooks;
+    }
+
+    public List<Hook> getPostDescribeHooks() {
+        return postDescribeHooks;
+    }
+
+    public HTTPServer getHTTPServer() {
+        return httpServer;
+    }
+
+    public List<LifetimeListener> getLifetimeListeners() {
+        return lifetimeListeners;
+    }
+
+    public List<BackendListener> getBackendListeners() {
+        return backendListeners;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org