changeset 18:aafa3884b2c4

new AnnotationStore restlet for HTML-UI. reorganisation of classes.
author casties
date Wed, 05 Sep 2012 18:05:54 +0200
parents e9dfac5b0566
children f0f55ab768c9
files pom.xml src/main/java/de/mpiwg/itgroup/annotations/Actor.java src/main/java/de/mpiwg/itgroup/annotations/NS.java src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java src/main/java/de/mpiwg/itgroup/annotations/old/AnnotationServerDb.java src/main/java/de/mpiwg/itgroup/annotations/old/NS.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreGroups.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreInfo.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreRestlet.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorInfo.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorRestlet.java src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java src/main/resources/de/mpiwg/itgroup/annotations/annotationstore-info.html src/main/webapp/WEB-INF/web.xml
diffstat 16 files changed, 594 insertions(+), 450 deletions(-) [+]
line wrap: on
line diff
--- a/pom.xml	Wed Sep 05 11:30:22 2012 +0200
+++ b/pom.xml	Wed Sep 05 18:05:54 2012 +0200
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.mpiwg.itgroup.annotations</groupId>
 	<artifactId>AnnotationManagerN4J</artifactId>
-	<version>0.2.0-SNAPSHOT</version>
+	<version>0.2.1-SNAPSHOT</version>
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<neo4j-version>1.7.1</neo4j-version>
--- a/src/main/java/de/mpiwg/itgroup/annotations/Actor.java	Wed Sep 05 11:30:22 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/Actor.java	Wed Sep 05 18:05:54 2012 +0200
@@ -4,7 +4,6 @@
 package de.mpiwg.itgroup.annotations;
 
 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
-import de.mpiwg.itgroup.annotations.old.NS;
 
 /**
  * @author casties
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/NS.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,14 @@
+package de.mpiwg.itgroup.annotations;
+
+public class NS {
+    public static final String MPIWG_PERSONS_URL = "http://entities.mpiwg-berlin.mpg.de/persons/";
+    public static final String MPIWG_GROUPS_URL = "http://entities.mpiwg-berlin.mpg.de/groups/";
+    public static final String OAC_NS = "http://www.openannotation.org/ns/";
+    public static final String CNT_NS = "http://www.w3.org/2011/content#";
+    public static final String DCTERMS_NS = "http://www.purl.org/dc/terms/";
+    public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+    public static final String MPIWG_ANNOT_NS = "http://ontologies.mpiwg-berlin.mpg.de/annotations/";
+    public static final String MPIWG_ANNOT_URL = "http://entities.mpiwg-berlin.mpg.de/annotations/";
+    public static final String MPIWG_ANNOT_CTX = "file:///annotations2";    
+
+}
--- a/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Wed Sep 05 11:30:22 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Wed Sep 05 18:05:54 2012 +0200
@@ -74,6 +74,24 @@
     }
 
     /**
+     * Returns List of Groups.
+     * 
+     * @param person
+     * @return
+     */
+    public List<Group> getGroups(String uriQuery) {
+        ArrayList<Group> groups = new ArrayList<Group>();
+        Index<Node> idx = getNodeIndex(NodeTypes.GROUP);
+        if (uriQuery == null) uriQuery = "*";
+        IndexHits<Node> groupNodes = idx.get("uri", uriQuery);
+        for (Node groupNode : groupNodes) {
+            Actor group = createActorFromNode(groupNode);
+            groups.add((Group) group);
+        }
+        return groups;
+    }
+
+    /**
      * Returns List of Groups the person is member of.
      * 
      * @param person
--- a/src/main/java/de/mpiwg/itgroup/annotations/old/AnnotationServerDb.java	Wed Sep 05 11:30:22 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-package de.mpiwg.itgroup.annotations.old;
-
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
-import org.neo4j.kernel.AbstractGraphDatabase;
-import org.neo4j.server.WrappingNeoServerBootstrapper;
-
-public class AnnotationServerDb {
-
-    private static String DB_PATH = "target/neo4j-annotation-db";
-    private static GraphDatabaseService graphDb;
-
-    /**
-     * @param args
-     */
-    public static void main(String[] args) {
-        AnnotationServerDb db = new AnnotationServerDb();
-        db.createDb();
-        // do something
-        AbstractGraphDatabase graphdb = (AbstractGraphDatabase) graphDb;
-        WrappingNeoServerBootstrapper srv;
-        srv = new WrappingNeoServerBootstrapper( graphdb );
-        System.out.println("Starting server...");
-        srv.start();
-        // The server is now running
-        try {
-            Thread.sleep(300*1000);
-        } catch (InterruptedException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        // until we stop it:
-        System.out.println("Stopping server...");
-        srv.stop();        
-        db.shutDown();
-    }
-
-    /**
-     * 
-     */
-    public void createDb() {
-        System.out.println();
-        System.out.println("Starting database "+DB_PATH+" ...");
-        graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
-        registerShutdownHook(graphDb);
-    }
-
-    public void shutDown() {
-        System.out.println();
-        System.out.println("Shutting down database ...");
-        // START SNIPPET: shutdownServer
-        graphDb.shutdown();
-        // END SNIPPET: shutdownServer
-    }
-
-    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
-        // Registers a shutdown hook for the Neo4j instance so that it
-        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
-        // running example before it's completed)
-        Runtime.getRuntime().addShutdownHook(new Thread() {
-            @Override
-            public void run() {
-                graphDb.shutdown();
-            }
-        });
-    }
-}
--- a/src/main/java/de/mpiwg/itgroup/annotations/old/NS.java	Wed Sep 05 11:30:22 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package de.mpiwg.itgroup.annotations.old;
-
-public class NS {
-    public static final String MPIWG_PERSONS_URL = "http://entities.mpiwg-berlin.mpg.de/persons/";
-    public static final String MPIWG_GROUPS_URL = "http://entities.mpiwg-berlin.mpg.de/groups/";
-    public static final String OAC_NS = "http://www.openannotation.org/ns/";
-    public static final String CNT_NS = "http://www.w3.org/2011/content#";
-    public static final String DCTERMS_NS = "http://www.purl.org/dc/terms/";
-    public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-    public static final String MPIWG_ANNOT_NS = "http://ontologies.mpiwg-berlin.mpg.de/annotations/";
-    public static final String MPIWG_ANNOT_URL = "http://entities.mpiwg-berlin.mpg.de/annotations/";
-    public static final String MPIWG_ANNOT_CTX = "file:///annotations2";    
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreGroups.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,63 @@
+/**
+ * 
+ */
+package de.mpiwg.itgroup.annotations.restlet;
+
+import java.util.List;
+
+import javax.servlet.ServletContext;
+
+import org.apache.log4j.Logger;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+import de.mpiwg.itgroup.annotations.Group;
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
+
+/**
+ * @author casties
+ *
+ */
+public class AnnotationStoreGroups extends ServerResource {
+
+    public static Logger logger = Logger.getLogger(AnnotationStoreGroups.class);
+
+    private AnnotationStore store;
+
+    @Get("html")
+    public Representation doGetHTML(Representation entity){
+        Form form = getRequest().getResourceRef().getQueryAsForm();
+        // id from URI /annotations/groups/{id}
+        String id = (String) getRequest().getAttributes().get("id");
+        logger.debug("group-id=" + id);
+        String retString="<html><body>\n<h1>Groups</h1>\n<table>";
+        store = getAnnotationStore();
+        if (id == null) {
+            // list all groups
+            List<Group> groups = store.getGroups("*");
+            for (Group group : groups) {
+                retString += String.format("<tr><td>uri=%s</td></tr>\n", group.getUri());
+            }
+            
+        }
+        retString += "</table>\n</body>\n</html>";
+        
+        logger.debug("sending:");
+        logger.debug(retString);
+        return new StringRepresentation(retString,MediaType.TEXT_HTML);
+    }
+
+    protected AnnotationStore getAnnotationStore() {
+        if (store == null) {
+            ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
+                    .get("org.restlet.ext.servlet.ServletContext");
+            logger.debug("Getting AnnotationStore from Context");
+            store = (AnnotationStore) sc.getAttribute(BaseRestlet.ANNSTORE_KEY);
+        }
+        return store;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreInfo.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,24 @@
+package de.mpiwg.itgroup.annotations.restlet;
+
+import java.io.InputStream;
+
+import org.restlet.data.MediaType;
+import org.restlet.representation.InputRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+
+public class AnnotationStoreInfo extends ServerResource {
+
+	@Get("html")
+	public Representation getHTML(){
+		InputStream is = getClass().getResourceAsStream("/de/mpiwg/itgroup/annotations/annotationstore-info.html");
+		
+		Representation rep = new InputRepresentation(is,MediaType.TEXT_HTML);
+		return rep;
+		
+	}
+	
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreRestlet.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,53 @@
+/**
+ * 
+ */
+package de.mpiwg.itgroup.annotations.restlet;
+
+import org.apache.log4j.Logger;
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+/**
+ * @author casties
+ * 
+ */
+public class AnnotationStoreRestlet extends BaseRestlet {
+
+    public final String version = "AnnotationManagerN4J/AnnotationStore 0.1";
+
+    public static Logger logger = Logger.getLogger(AnnotationStoreRestlet.class);
+
+    public AnnotationStoreRestlet(Context context) {
+        super(context);
+        logger.debug("StoreRestlet!");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.restlet.Application#createInboundRoot()
+     */
+    @Override
+    public Restlet createInboundRoot() {
+        // this.authenticator = createAuthenticator();
+
+        Router router = new Router(getContext());
+
+        router.attach("/groups", AnnotationStoreGroups.class);
+        router.attach("/groups/{id}", AnnotationStoreGroups.class);
+
+        router.attach("/", AnnotationStoreInfo.class);
+        // authenticator.setNext(router);
+        // return authenticator;
+
+        return router;
+    }
+
+    
+    @Override
+    public String getVersion() {
+        return version;
+    }
+
+}
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorInfo.java	Wed Sep 05 11:30:22 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorInfo.java	Wed Sep 05 18:05:54 2012 +0200
@@ -2,43 +2,15 @@
 
 import java.io.InputStream;
 
-import org.apache.log4j.Logger;
-import org.restlet.data.Form;
 import org.restlet.data.MediaType;
 import org.restlet.representation.InputRepresentation;
 import org.restlet.representation.Representation;
 import org.restlet.resource.Get;
-import org.restlet.resource.Options;
 import org.restlet.resource.ServerResource;
 
 
-
-
-
 public class AnnotatorInfo extends ServerResource {
 
-private Logger logger = Logger.getRootLogger();
-	
-	/**
-	 * Erlaubt cross scripting bei Aufruf aus Javascript
-	 * @param entity
-	 */
-	@Options
-	public void doOptions(Representation entity) {
-	    Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
-	    if (responseHeaders == null) {
-	        responseHeaders = new Form();
-	        getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
-	    }
-	    responseHeaders.add("Access-Control-Allow-Origin", "*");
-	    responseHeaders.add("Access-Control-Allow-Methods", "POST,OPTIONS,GET");
-	    responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
-	    responseHeaders.add("Access-Control-Allow-Credentials", "false");
-	    responseHeaders.add("Access-Control-Max-Age", "60");
-	}
-
-
-	
 	@Get("html")
 	public Representation getHTML(){
 		InputStream is = getClass().getResourceAsStream("/de/mpiwg/itgroup/annotations/annotator-info.html");
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Wed Sep 05 11:30:22 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Wed Sep 05 18:05:54 2012 +0200
@@ -37,11 +37,11 @@
 
 import de.mpiwg.itgroup.annotations.Actor;
 import de.mpiwg.itgroup.annotations.Annotation;
+import de.mpiwg.itgroup.annotations.NS;
 import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes;
 import de.mpiwg.itgroup.annotations.Group;
 import de.mpiwg.itgroup.annotations.Person;
 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
-import de.mpiwg.itgroup.annotations.old.NS;
 
 /**
  * Base class for Annotator resource classes.
@@ -64,7 +64,7 @@
             ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
                     .get("org.restlet.ext.servlet.ServletContext");
             logger.debug("Getting AnnotationStore from Context");
-            store = (AnnotationStore) sc.getAttribute(RestServer.ANNSTORE_KEY);
+            store = (AnnotationStore) sc.getAttribute(BaseRestlet.ANNSTORE_KEY);
         }
         return store;
     }
@@ -148,7 +148,7 @@
         String userId = token.getParamAsPrimitive("userId").getAsString();
         String consumerKey = token.getParamAsPrimitive("consumerKey").getAsString();
         // get stored consumer secret for key
-        RestServer restServer = (RestServer) getApplication();
+        BaseRestlet restServer = (BaseRestlet) getApplication();
         String consumerSecret = restServer.getConsumerSecret(consumerKey);
         logger.debug("requested consumer key=" + consumerKey + " secret=" + consumerSecret);
         if (consumerSecret == null) {
@@ -207,7 +207,7 @@
                 // get full name
                 String userName = creator.getName();
                 if (userName == null) {
-                    RestServer restServer = (RestServer) getApplication();
+                    BaseRestlet restServer = (BaseRestlet) getApplication();
                     userName = restServer.getFullNameFromLdap(userId);
                 }
                 userObject.put("name", userName);
@@ -499,7 +499,7 @@
         }
         // try to get full name
         if (creator.getName() == null && username != null) {
-            RestServer restServer = (RestServer) getApplication();
+            BaseRestlet restServer = (BaseRestlet) getApplication();
             String fullName = restServer.getFullNameFromLdap(username);
             creator.setName(fullName);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorRestlet.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,60 @@
+/**
+ * 
+ */
+package de.mpiwg.itgroup.annotations.restlet;
+
+import org.apache.log4j.Logger;
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+/**
+ * @author casties
+ *
+ */
+public class AnnotatorRestlet extends BaseRestlet {
+
+    public final String version = "AnnotationManagerN4J/Annotator 0.2.1";
+
+    public static Logger logger = Logger.getLogger(AnnotatorRestlet.class);
+
+    /**
+     * @param context
+     */
+    public AnnotatorRestlet(Context context) {
+        super(context);
+        logger.debug("AnnotatorRestlet!");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.restlet.Application#createInboundRoot()
+     */
+    @Override
+    public Restlet createInboundRoot() {
+        // this.authenticator = createAuthenticator();
+
+        Router router = new Router(getContext());
+
+        router.attach("/annotations", AnnotatorAnnotations.class);
+        router.attach("/annotations/{id}", AnnotatorAnnotations.class);
+        router.attach("/search", AnnotatorSearch.class);
+        router.attach("/groups", AnnotatorGroups.class);
+
+        router.attach("/", AnnotatorInfo.class);
+        // authenticator.setNext(router);
+        // return authenticator;
+
+        return router;
+    }
+
+    /* (non-Javadoc)
+     * @see de.mpiwg.itgroup.annotations.restlet.RestletImpl#getVersion()
+     */
+    @Override
+    public String getVersion() {
+        return version;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,312 @@
+package de.mpiwg.itgroup.annotations.restlet;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.servlet.ServletContext;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Logger;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.factory.GraphDatabaseFactory;
+import org.neo4j.kernel.AbstractGraphDatabase;
+import org.neo4j.server.WrappingNeoServerBootstrapper;
+import org.restlet.Application;
+import org.restlet.Context;
+
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
+
+public abstract class BaseRestlet extends Application {
+
+    public static Logger logger = Logger.getLogger(BaseRestlet.class);
+
+    /**
+     * Properties holding consumer keys and secrets
+     */
+    protected Properties consumerKeys;
+    public String CONSUMER_KEYS_PATH = "WEB-INF/consumerkeys.property";
+    public static final String CONSUMERKEYS_KEY = "annotationmanager.consumerkeys";
+
+    protected Properties serverConfig;
+    public String CONFIG_PROPS_PATH = "WEB-INF/serverconfig.property";
+    public static final String SERVERCONFIG_KEY = "annotationmanager.serverconfig";
+
+    protected GraphDatabaseService graphDb;
+    public static final String GRAPHDB_KEY = "annotationmanager.graphdb";
+    public static final String GRAPHDB_PATH_KEY = "annotationmanager.graphdb.path";
+    public String graphdbPath = "WEB-INF/neo4j-annotation-db";
+
+    protected WrappingNeoServerBootstrapper srv;
+    public static final String GRAPHDBSRV_KEY = "annotationmanager.graphdb.srv";
+
+    protected AnnotationStore store;
+    public static final String ANNSTORE_KEY = "annotationmanager.store";
+
+    protected String ldapServerUrl;
+    public static final String LDAP_SERVER_KEY = "annotationmanager.ldapserver.url";
+
+    /**
+     * constructor
+     * 
+     * @param context
+     */
+    public BaseRestlet(Context context) {
+        super(context);
+        configure();
+    }
+
+    /**
+     * Configures the restlet.
+     * Reads serverConfig, consumerKeys and graphDb config from config files and starts graphDb.
+     * Uses config from webapp context if already initialized. 
+     */
+    protected void configure() {
+        ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
+                .get("org.restlet.ext.servlet.ServletContext");
+        if (sc != null) {
+            if (sc.getAttribute("annotationserver.log4j.configured") == null) {
+                // TODO: is this the right place to run the log4j configurator?
+                BasicConfigurator.configure();
+                sc.setAttribute("annotationserver.log4j.configured", "done");
+            }
+            logger.info(getVersion() + " starting...");
+
+            /*
+             * read config from webapp
+             */
+            serverConfig = (Properties) sc.getAttribute(SERVERCONFIG_KEY);
+            if (serverConfig == null) {
+                serverConfig = new Properties();
+                InputStream ps = getResourceAsStream(sc, CONFIG_PROPS_PATH);
+                if (ps != null) {
+                    logger.debug("loading config from " + CONFIG_PROPS_PATH);
+                    try {
+                        serverConfig.load(ps);
+                        /*
+                         * read serverconfig options
+                         */
+                        graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
+                        ldapServerUrl = serverConfig.getProperty(LDAP_SERVER_KEY, null);
+                    } catch (IOException e) {
+                        logger.warn("Error loading server config: ", e);
+                    }
+                    logger.debug("config: " + serverConfig);
+                } else {
+                    logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
+                }
+                // store config
+                sc.setAttribute(SERVERCONFIG_KEY, serverConfig);
+            }
+            // look for database service in context
+            graphDb = (GraphDatabaseService) sc.getAttribute(GRAPHDB_KEY);
+            if (graphDb == null) {
+                /*
+                 * open database
+                 */
+                String dbFn = getResourcePath(sc, graphdbPath);
+                if (dbFn != null) {
+                    logger.debug("opening DB " + dbFn);
+                    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(dbFn);
+                    registerShutdownHook(graphDb);
+                    // store in context
+                    sc.setAttribute(GRAPHDB_KEY, graphDb);
+                    // AnnotationStore
+                    store = new AnnotationStore(graphDb);
+                    sc.setAttribute(ANNSTORE_KEY, store);
+                    // admin server
+                    srv = new WrappingNeoServerBootstrapper((AbstractGraphDatabase) graphDb);
+                    logger.debug("Starting DB admin server...");
+                    // store in context
+                    sc.setAttribute(GRAPHDBSRV_KEY, srv);
+                    srv.start();
+                } else {
+                    logger.error("Unable to get resource " + dbFn);
+                }
+            }
+            /*
+             * read consumerKeys from webapp
+             */
+            consumerKeys = (Properties) sc.getAttribute(CONSUMERKEYS_KEY);
+            if (consumerKeys == null) {
+                consumerKeys = new Properties();
+                InputStream ps = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
+                if (ps != null) {
+                    logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
+                    try {
+                        consumerKeys.load(ps);
+                    } catch (IOException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                    logger.debug("consumer keys: " + consumerKeys);
+                } else {
+                    logger.error("Unable to get resource " + CONSUMER_KEYS_PATH);
+                }
+                // store config
+                sc.setAttribute(CONSUMERKEYS_KEY, consumerKeys);
+            }
+        } else {
+            logger.error("Unable to get ServletContext!");
+        }
+    }
+
+    public abstract String getVersion();
+
+    /**
+     * returns consumer secret for consumer key. returns null if consumer key
+     * doesn't exist.
+     * 
+     * @param consumerKey
+     * @return
+     */
+    public String getConsumerSecret(String consumerKey) {
+        return consumerKeys.getProperty(consumerKey);
+    }
+
+    /**
+     * Hole den vollen Benutzernamen aus dem LDAP
+     * 
+     * @param creator
+     * @return
+     */
+    public String getFullNameFromLdap(String creator) {
+        String retString = creator; // falls nichts gefunden wird einfach den
+                                    // creator zurueckgeben
+        if (ldapServerUrl == null) {
+            return retString;
+        }
+        Hashtable<String, String> env = new Hashtable<String, String>();
+        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
+        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
+        env.put(javax.naming.Context.PROVIDER_URL, ldapServerUrl);
+
+        DirContext dctx;
+        try {
+            dctx = new InitialDirContext(env);
+        } catch (NamingException e) {
+            logger.error("Error in getFullNameFromLDAP!", e);
+            return retString;
+        }
+
+        String base = "ou=people";
+
+        SearchControls sc = new SearchControls();
+        String[] attributeFilter = { "cn", "mail" };
+        sc.setReturningAttributes(attributeFilter);
+        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+        String filter = "(uid=" + creator + ")";
+
+        try {
+            NamingEnumeration<SearchResult> results = dctx.search(base, filter, sc);
+            while (results.hasMore()) {
+                SearchResult sr = (SearchResult) results.next();
+                javax.naming.directory.Attributes attrs = sr.getAttributes();
+
+                Attribute attr = attrs.get("cn");
+                retString = (String) attr.get();
+            }
+        } catch (NamingException e) {
+            logger.error("Error in getFullNameFromLDAP!", e);
+        }
+
+        try {
+            dctx.close();
+        } catch (NamingException e) {
+            logger.error("Error in getFullNameFromLDAP!", e);
+        }
+        return retString;
+    }
+
+    /**
+     * returns resource from path (in webapp) as InputStream.
+     * 
+     * @param sc
+     * @param path
+     * @return
+     */
+    protected InputStream getResourceAsStream(ServletContext sc, String path) {
+        InputStream ps = sc.getResourceAsStream(path);
+        if (ps == null) {
+            // try as file
+            File pf = new File(sc.getRealPath(path));
+            if (pf != null) {
+                logger.debug("trying file for: " + pf);
+                try {
+                    ps = new FileInputStream(pf);
+                } catch (FileNotFoundException e) {
+                    logger.error(e);
+                }
+            }
+        }
+        return ps;
+    }
+
+    /**
+     * get a real file name for a web app file pathname.
+     * 
+     * If filename starts with "/" its treated as absolute else the path is
+     * appended to the base directory of the web-app.
+     * 
+     * @param filename
+     * @param sc
+     * @return
+     */
+    public static String getResourcePath(ServletContext sc, String filename) {
+        File f = new File(filename);
+        // is the filename absolute?
+        if (!f.isAbsolute()) {
+            // relative path -> use getRealPath to resolve in webapp
+            filename = sc.getRealPath(filename);
+        }
+        return filename;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.restlet.Application#stop()
+     */
+    @Override
+    public synchronized void stop() throws Exception {
+        /*
+         * trying to clean up databases, not sure if this is the right way...
+         */
+        if (srv != null) {
+            logger.debug("Stopping DB admin server...");
+            srv.stop();
+            srv = null;
+        }
+        if (graphDb != null) {
+            logger.debug("Stopping DB...");
+            graphDb.shutdown();
+            graphDb = null;
+        }
+        super.stop();
+    }
+
+    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
+        // Registers a shutdown hook for the Neo4j instance so that it
+        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
+        // running example before it's completed)
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                graphDb.shutdown();
+            }
+        });
+    }
+
+}
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java	Wed Sep 05 11:30:22 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-package de.mpiwg.itgroup.annotations.restlet;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.servlet.ServletContext;
-
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Logger;
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
-import org.neo4j.kernel.AbstractGraphDatabase;
-import org.neo4j.server.WrappingNeoServerBootstrapper;
-import org.restlet.Application;
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
-
-public class RestServer extends Application {
-
-    public static Logger logger = Logger.getLogger(RestServer.class);
-
-    /**
-     * Properties holding consumer keys and secrets
-     */
-    private Properties consumerKeys;
-    public String CONSUMER_KEYS_PATH = "WEB-INF/consumerkeys.property";
-
-    private Properties serverConfig;
-    public String CONFIG_PROPS_PATH = "WEB-INF/serverconfig.property";
-
-    private GraphDatabaseService graphDb;
-    public static final String GRAPHDB_KEY = "annotationmanager.graphdb";
-    public static final String GRAPHDB_PATH_KEY = "annotationmanager.graphdb.path";
-    public String graphdbPath = "WEB-INF/neo4j-annotation-db";
-
-    private WrappingNeoServerBootstrapper srv;
-    public static final String GRAPHDBSRV_KEY = "annotationmanager.graphdb.srv";
-    
-    private AnnotationStore store;
-    public static final String ANNSTORE_KEY = "annotationmanager.store";
-
-    private String ldapServerUrl;
-    public static final String LDAP_SERVER_KEY = "annotationmanager.ldapserver.url";
-
-    /**
-     * constructor
-     * 
-     * @param parentContext
-     */
-    public RestServer(Context parentContext) {
-        super(parentContext);
-        // TODO: is this the right place to run the log4j configurator?
-        BasicConfigurator.configure();
-
-        ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
-                .get("org.restlet.ext.servlet.ServletContext");
-        if (sc != null) {
-            /*
-             * read config from webapp
-             */
-            serverConfig = new Properties();
-            InputStream ps1 = getResourceAsStream(sc, CONFIG_PROPS_PATH);
-            if (ps1 != null) {
-                logger.debug("loading config from " + CONFIG_PROPS_PATH);
-                try {
-                    serverConfig.load(ps1);
-                    /*
-                     * read serverconfig options
-                     */
-                    graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
-                    ldapServerUrl =  serverConfig.getProperty(LDAP_SERVER_KEY, null);
-                } catch (IOException e) {
-                    logger.warn("Error loading server config: ", e);
-                }
-                logger.debug("config: " + serverConfig);
-            } else {
-                logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
-            }
-            // look for database service in context
-            graphDb = (GraphDatabaseService) sc.getAttribute(GRAPHDB_KEY);
-            if (graphDb == null) {
-                /*
-                 * open database
-                 */
-                String dbFn = getResourcePath(sc, graphdbPath);
-                if (dbFn != null) {
-                    logger.debug("opening DB " + dbFn);
-                    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(dbFn);
-                    registerShutdownHook(graphDb);
-                    // store in context
-                    sc.setAttribute(GRAPHDB_KEY, graphDb);
-                    // AnnotationStore
-                    store = new AnnotationStore(graphDb);
-                    sc.setAttribute(ANNSTORE_KEY, store);
-                    // admin server
-                    srv = new WrappingNeoServerBootstrapper((AbstractGraphDatabase) graphDb);
-                    logger.debug("Starting DB admin server...");
-                    // store in context
-                    sc.setAttribute(GRAPHDBSRV_KEY, srv);
-                    srv.start();
-                } else {
-                    logger.error("Unable to get resource " + dbFn);
-                }
-            }
-            /*
-             * read consumerKeys from webapp
-             */
-            consumerKeys = new Properties();
-            InputStream ps2 = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
-            if (ps2 != null) {
-                logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
-                try {
-                    consumerKeys.load(ps2);
-                } catch (IOException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
-                }
-                logger.debug("consumer keys: " + consumerKeys);
-            } else {
-                logger.error("Unable to get resource " + CONSUMER_KEYS_PATH);
-            }
-        } else {
-            logger.error("Unable to get ServletContext!");
-        }
-
-    }
-
-    /**
-     * returns consumer secret for consumer key. returns null if consumer key
-     * doesn't exist.
-     * 
-     * @param consumerKey
-     * @return
-     */
-    public String getConsumerSecret(String consumerKey) {
-        return consumerKeys.getProperty(consumerKey);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.restlet.Application#createInboundRoot()
-     */
-    @Override
-    public Restlet createInboundRoot() {
-        // this.authenticator = createAuthenticator();
-
-        Router router = new Router(getContext());
-
-        router.attach("/annotator/annotations", AnnotatorAnnotations.class);
-        router.attach("/annotator/annotations/{id}", AnnotatorAnnotations.class);
-        router.attach("/annotator/search", AnnotatorSearch.class);
-        router.attach("/annotator/groups", AnnotatorGroups.class);
-
-        // router.attach("",redirector); router.attach("/annotator",
-        // ExtendedAnnotationInput.class);
-
-        router.attach("/", AnnotatorInfo.class);
-        // authenticator.setNext(router);
-        // return authenticator;
-
-        return router;
-    }
-
-    /**
-     * Hole den vollen Benutzernamen aus dem LDAP
-     * 
-     * @param creator
-     * @return
-     */
-    public String getFullNameFromLdap(String creator) {
-        String retString = creator; // falls nichts gefunden wird einfach den
-                                    // creator zurueckgeben
-        if (ldapServerUrl == null) {
-        	return retString;
-        }
-        Hashtable<String, String> env = new Hashtable<String, String>();
-        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
-        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
-
-        env.put(javax.naming.Context.PROVIDER_URL, ldapServerUrl);
-
-        DirContext dctx;
-        try {
-            dctx = new InitialDirContext(env);
-        } catch (NamingException e1) {
-            // TODO Auto-generated catch block
-            e1.printStackTrace();
-            return retString;
-        }
-
-        String base = "ou=people";
-
-        SearchControls sc = new SearchControls();
-        String[] attributeFilter = { "cn", "mail" };
-        sc.setReturningAttributes(attributeFilter);
-        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
-
-        String filter = "(uid=" + creator + ")";
-
-        try {
-            NamingEnumeration<SearchResult> results = dctx.search(base, filter, sc);
-            while (results.hasMore()) {
-                SearchResult sr = (SearchResult) results.next();
-                javax.naming.directory.Attributes attrs = sr.getAttributes();
-
-                Attribute attr = attrs.get("cn");
-                retString = (String) attr.get();
-            }
-        } catch (NamingException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-
-        try {
-            dctx.close();
-        } catch (NamingException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        return retString;
-    }
-
-    /**
-     * returns resource from path (in webapp) as InputStream.
-     * 
-     * @param sc
-     * @param path
-     * @return
-     */
-    protected InputStream getResourceAsStream(ServletContext sc, String path) {
-        InputStream ps = sc.getResourceAsStream(path);
-        if (ps == null) {
-            // try as file
-            File pf = new File(sc.getRealPath(path));
-            if (pf != null) {
-                logger.debug("trying file for: " + pf);
-                try {
-                    ps = new FileInputStream(pf);
-                } catch (FileNotFoundException e) {
-                    logger.error(e);
-                }
-            }
-        }
-        return ps;
-    }
-
-    /**
-     * get a real file name for a web app file pathname.
-     * 
-     * If filename starts with "/" its treated as absolute else the path is
-     * appended to the base directory of the web-app.
-     * 
-     * @param filename
-     * @param sc
-     * @return
-     */
-    public static String getResourcePath(ServletContext sc, String filename) {
-        File f = new File(filename);
-        // is the filename absolute?
-        if (!f.isAbsolute()) {
-            // relative path -> use getRealPath to resolve in webapp
-            filename = sc.getRealPath(filename);
-        }
-        return filename;
-    }
-
-    /* (non-Javadoc)
-     * @see org.restlet.Application#stop()
-     */
-    @Override
-    public synchronized void stop() throws Exception {
-        /*
-         * trying to clean up databases, nur sure if this is the right way...
-         */
-        if (srv != null) {
-            logger.debug("Stopping DB admin server...");
-            srv.stop();
-            srv = null;
-        }
-        if (graphDb != null) {
-            logger.debug("Stopping DB...");
-            graphDb.shutdown();
-            graphDb = null;
-        }
-        super.stop();
-    }
-
-    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
-        // Registers a shutdown hook for the Neo4j instance so that it
-        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
-        // running example before it's completed)
-        Runtime.getRuntime().addShutdownHook(new Thread() {
-            @Override
-            public void run() {
-                graphDb.shutdown();
-            }
-        });
-    }
-   
-    
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/resources/de/mpiwg/itgroup/annotations/annotationstore-info.html	Wed Sep 05 18:05:54 2012 +0200
@@ -0,0 +1,6 @@
+<html>
+<body>
+<h2>Annotation manager</h2>
+<p><a href="annotations">Annotation store overview</a></p>
+</body>
+</html>
\ No newline at end of file
--- a/src/main/webapp/WEB-INF/web.xml	Wed Sep 05 11:30:22 2012 +0200
+++ b/src/main/webapp/WEB-INF/web.xml	Wed Sep 05 18:05:54 2012 +0200
@@ -4,21 +4,42 @@
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
-    <display-name>AnnotationManager-Restlet</display-name>
-    <!-- Application classname -->
-    <context-param>
-        <param-name>org.restlet.application</param-name>
-        <param-value>de.mpiwg.itgroup.annotations.restlet.RestServer</param-value>
-    </context-param>
-    <!-- Restletadapter -->
-    <servlet>
-        <servlet-name>RestletServlet</servlet-name>
-        <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
-    </servlet>
-    <!-- Catchallrequests -->
-    <servlet-mapping>
-        <servlet-name>RestletServlet</servlet-name>
-        <!-- <url-pattern>/annotator/*</url-pattern> -->
-        <url-pattern>/*</url-pattern>
-    </servlet-mapping>
+	<display-name>AnnotationManager-Restlet</display-name>
+	<!-- Restletadapter -->
+	<servlet>
+		<servlet-name>AnnotatorRestlet</servlet-name>
+		<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
+		<!-- Application classname -->
+		<init-param>
+			<param-name>org.restlet.application</param-name>
+			<param-value>de.mpiwg.itgroup.annotations.restlet.AnnotatorRestlet</param-value>
+		</init-param>
+        <!-- Load this servlet at server startup time -->
+        <load-on-startup>1</load-on-startup>
+	</servlet>
+	<!-- Restletadapter -->
+	<servlet>
+		<servlet-name>AnnotationStoreRestlet</servlet-name>
+		<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
+		<!-- Application classname -->
+		<init-param>
+			<param-name>org.restlet.application</param-name>
+			<param-value>de.mpiwg.itgroup.annotations.restlet.AnnotationStoreRestlet</param-value>
+		</init-param>
+        <!-- Load this servlet at server startup time -->
+        <load-on-startup>
+            10
+        </load-on-startup>
+	</servlet>
+	<!-- Catchallrequests -->
+	<servlet-mapping>
+		<servlet-name>AnnotatorRestlet</servlet-name>
+		<url-pattern>/annotator/*</url-pattern>
+		<!-- <url-pattern>/*</url-pattern> -->
+	</servlet-mapping>
+	<servlet-mapping>
+		<servlet-name>AnnotationStoreRestlet</servlet-name>
+		<url-pattern>/annotations/*</url-pattern>
+		<!-- <url-pattern>/*</url-pattern> -->
+	</servlet-mapping>
 </web-app>
\ No newline at end of file