# 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 :