diff src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 18:aafa3884b2c4

new AnnotationStore restlet for HTML-UI. reorganisation of classes.
author casties
date Wed, 05 Sep 2012 18:05:54 +0200
parents
children f0f55ab768c9
line wrap: on
line diff
--- /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();
+            }
+        });
+    }
+
+}