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 :