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; sascha@70: import de.intevation.artifacts.ServiceFactory; ingo@125: import de.intevation.artifacts.UserFactory; sascha@70: sascha@263: sascha@263: import de.intevation.artifactdatabase.rest.HTTPServer; sascha@263: sascha@70: import java.util.ArrayList; 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 Sascha L. Teichmann 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: 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: ingo@249: /** sascha@89: * Default export signing secret. sascha@89: * PLEASE CHANGE THE SECRET VIA THE XPATH EXPORT_SECRET sascha@89: * IN THE CONFIGURATION.. 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: */ sascha@5: protected Object 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@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@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(); 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: */ sascha@5: public Object 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: sascha@263: public HTTPServer getHTTPServer() { sascha@263: return httpServer; sascha@263: } sascha@5: } ingo@79: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :