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