# HG changeset patch # User gernotbelger # Date 1539194878 -7200 # Node ID 05caf2e731d03f82944167421a4041afe8e39c62 # Parent 1c2ce0501305e6f8586fd8d1e12da1e632b7a54c Allow to add additional restful services via configuration. diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/pom.xml --- a/artifact-database/pom.xml Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/pom.xml Wed Oct 10 20:07:58 2018 +0200 @@ -91,5 +91,10 @@ jetty 6.1.26 + + org.restlet.jse + org.restlet.ext.httpclient + 2.0.7 + diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/src/main/java/org/dive4elements/artifactdatabase/ArtifactDatabaseImpl.java --- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/ArtifactDatabaseImpl.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/ArtifactDatabaseImpl.java Wed Oct 10 20:07:58 2018 +0200 @@ -407,6 +407,8 @@ */ protected HashMap name2service; + private Map> restServices; + /** * The factory that is used to create new artifact collections. */ @@ -464,6 +466,8 @@ protected List lifetimeListeners; + private String serverAddress; + /** * Default constructor. */ @@ -493,10 +497,13 @@ backgroundIds = new HashSet(); backgroundMsgs = new HashMap>(); + + this.serverAddress = bootstrap.getHTTPServer().getServerAddress(); setupArtifactCollectionFactory(bootstrap); setupArtifactFactories(bootstrap); setupServices(bootstrap); + setupRestServices(bootstrap); setupUserFactory(bootstrap); setupCallContextListener(bootstrap); setupHooks(bootstrap); @@ -638,6 +645,17 @@ } /** + * Used to extract the service factories from the bootstrap + * parameters, setting up the services and building the internal + * lookup tables. + * @param bootstrap The bootstrap parameters. + */ + private void setupRestServices(FactoryBootstrap bootstrap) { + + restServices = new HashMap>(bootstrap.getRestServiceNames()); + } + + /** * Wires a storage backend to this artifact database and * establishes a callback to be able to revive artifacts * via the serializers of this artifact factories. @@ -1984,5 +2002,15 @@ public String findArtifactUser(final String artifactIdentifier) { return backend.findUserName(artifactIdentifier); } + + @Override + public String getServerAddress() { + return this.serverAddress; + } + + @Override + public Map> getRestServices() { + return restServices; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java --- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java Wed Oct 10 20:07:58 2018 +0200 @@ -20,11 +20,12 @@ import org.dive4elements.artifacts.UserFactory; import org.dive4elements.artifacts.common.utils.StringUtils; - import org.dive4elements.artifactdatabase.rest.HTTPServer; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; @@ -70,6 +71,13 @@ "/artifact-database/factories/service-factories/service-factory"; /** + * XPath to figure out the names of the addtional restful services from + * the global configuration. + */ + public static final String RESTFUL_SERVICES = + "/artifact-database/factories/restful-services/restful-service"; + + /** * XPath to figure out the class name of the user factory from global * configuration. */ @@ -144,6 +152,8 @@ * artifact database. */ protected ArtifactFactory [] artifactFactories; + + private Map> restServices; /** * List of service factories which creates services that are @@ -361,6 +371,40 @@ new ServiceFactory[loadedFactories.size()]); } + /** + * Scans the global configuration for the configured service factories + * and sets them up. + */ + private void loadRestfulServices() { + + logger.info("loading additional restful services"); + + restServices = new HashMap>(); + + final NodeList nodes = Config.getNodeSetXPath(RESTFUL_SERVICES); + + if (nodes == null) + return; + + for (int i = 0; i < nodes.getLength(); ++i) { + + final Node node = nodes.item(i); + + final String className = Config.getStringXPath( node, "@class"); + final String path = Config.getStringXPath( node, "@path"); + + try { + final Class clazz = Class.forName(className); + restServices.put(path, clazz); + } + catch (final ClassNotFoundException cnfe) { + logger.error(cnfe.getLocalizedMessage(), cnfe); + } + catch (final ClassCastException cce) { + logger.error(cce.getLocalizedMessage(), cce); + } + } + } /** * Scans the global configuration for the configured user factory. @@ -638,6 +682,7 @@ loadCollectionFactory(); loadArtifactFactories(); loadServiceFactories(); + loadRestfulServices(); loadUserFactory(); loadCallContextListener(); loadHTTPServer(); @@ -729,5 +774,9 @@ public List getBackendListeners() { return backendListeners; } + + public Map> getRestServiceNames() { + return restServices; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/HTTPServer.java --- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/HTTPServer.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/HTTPServer.java Wed Oct 10 20:07:58 2018 +0200 @@ -1,13 +1,13 @@ package org.dive4elements.artifactdatabase.rest; +import org.dive4elements.artifacts.ArtifactDatabase; import org.w3c.dom.Document; -import org.dive4elements.artifacts.ArtifactDatabase; - public interface HTTPServer { void setup(Document document); void startAsServer(ArtifactDatabase database); -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : + + String getServerAddress(); +} \ No newline at end of file diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/RestApp.java --- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/RestApp.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/RestApp.java Wed Oct 10 20:07:58 2018 +0200 @@ -8,14 +8,14 @@ package org.dive4elements.artifactdatabase.rest; -import org.dive4elements.artifacts.ArtifactDatabase; - +import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; +import org.dive4elements.artifacts.ArtifactDatabase; import org.restlet.Application; import org.restlet.Context; import org.restlet.Restlet; - import org.restlet.routing.Router; /** @@ -25,32 +25,21 @@ * * @author Sascha L. Teichmann */ -public class RestApp -extends Application -{ +public class RestApp extends Application { + /** * The central artifact database instance to work with. */ - protected ArtifactDatabase database; - - /** - * Default constructor - */ - public RestApp() { - } - - public RestApp(Context context, ArtifactDatabase database) { - super(context); - this.database = database; - } + private final ArtifactDatabase database; /** * Constructor to create REST appliction bound to a specific * artifact database. * - * @param database The artifact database to be used. + * @param database + * The artifact database to be used. */ - public RestApp(ArtifactDatabase database) { + public RestApp(final ArtifactDatabase database) { this.database = database; } @@ -63,35 +52,35 @@ @Override public Restlet createRoot() { - Context context = getContext(); - - ConcurrentMap map = context.getAttributes(); - map.put("database", database); + final Context context = getContext(); - Router router = new Router(context); + final ConcurrentMap map = context.getAttributes(); + map.put("database", this.database); - router.attach(ServicesResource.PATH, ServicesResource.class); - router.attach(ServiceResource.PATH, ServiceResource.class); - router.attach(FactoriesResource.PATH, FactoriesResource.class); - router.attach(CreateResource.PATH, CreateResource.class); - router.attach(ArtifactResource.PATH, ArtifactResource.class); + final Router router = new Router(context); + + router.attach(ServicesResource.PATH, ServicesResource.class); + router.attach(ServiceResource.PATH, ServiceResource.class); + router.attach(FactoriesResource.PATH, FactoriesResource.class); + router.attach(CreateResource.PATH, CreateResource.class); + router.attach(ArtifactResource.PATH, ArtifactResource.class); router.attach(ArtifactOutResource.PATH, ArtifactOutResource.class); - router.attach(ExportResource.PATH, ExportResource.class); - router.attach(ImportResource.PATH, ImportResource.class); - router.attach(CreateUserResource.PATH, CreateUserResource.class); - router.attach(ListUsersResource.PATH, ListUsersResource.class); - router.attach(UserResource.PATH, UserResource.class); - router.attach(FindUserResource.PATH, FindUserResource.class); - router.attach( - CreateCollectionResource.PATH, CreateCollectionResource.class); - router.attach( - ListCollectionsResource.PATH, ListCollectionsResource.class); - router.attach( - CollectionResource.PATH, CollectionResource.class); - router.attach( - CollectionOutResource.PATH, CollectionOutResource.class); + router.attach(ExportResource.PATH, ExportResource.class); + router.attach(ImportResource.PATH, ImportResource.class); + router.attach(CreateUserResource.PATH, CreateUserResource.class); + router.attach(ListUsersResource.PATH, ListUsersResource.class); + router.attach(UserResource.PATH, UserResource.class); + router.attach(FindUserResource.PATH, FindUserResource.class); + router.attach(CreateCollectionResource.PATH, CreateCollectionResource.class); + router.attach(ListCollectionsResource.PATH, ListCollectionsResource.class); + router.attach(CollectionResource.PATH, CollectionResource.class); + router.attach(CollectionOutResource.PATH, CollectionOutResource.class); + + /* register any additional services */ + final Map> restServices = this.database.getRestServices(); + for (final Entry> entry : restServices.entrySet()) + router.attach(entry.getKey(), entry.getValue()); return router; } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : +} \ No newline at end of file diff -r 1c2ce0501305 -r 05caf2e731d0 artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/Standalone.java --- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/Standalone.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/rest/Standalone.java Wed Oct 10 20:07:58 2018 +0200 @@ -89,6 +89,12 @@ listen = XMLUtils.xpathString(document, LISTEN_INTERFACE, null); maxThreads = XMLUtils.xpathString(document, MAX_THREADS, null); } + + @Override + public String getServerAddress() { + String host = (this.listen == null || this.listen.trim().length() == 0 ) ? "localhost" : this.listen; + return String.format("http://%s:%d", host, this.port); + } protected Server createServer() { return listen != null && listen.length() > 0 diff -r 1c2ce0501305 -r 05caf2e731d0 artifacts/src/main/java/org/dive4elements/artifacts/ArtifactDatabase.java --- a/artifacts/src/main/java/org/dive4elements/artifacts/ArtifactDatabase.java Mon Sep 24 17:59:17 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/artifacts/ArtifactDatabase.java Wed Oct 10 20:07:58 2018 +0200 @@ -14,6 +14,7 @@ import org.w3c.dom.Document; import java.util.Date; +import java.util.Map; /** * Interface of an artifact managing database. @@ -296,5 +297,10 @@ throws ArtifactDatabaseException; String findArtifactUser(String artifactIdentifier); + + String getServerAddress(); + + /** an additional list of rest services (path and implementing class) that should be registered */ + Map> getRestServices(); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :