source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 71:326369d4bc4d

Last change on this file since 71:326369d4bc4d was 71:326369d4bc4d, checked in by casties, 10 years ago

trying restlet 2.1. doesn't work yet.

File size: 15.3 KB
Line 
1package de.mpiwg.itgroup.annotations.restlet;
2
3/*
4 * #%L
5 * AnnotationManager
6 * %%
7 * Copyright (C) 2012 - 2014 MPIWG Berlin
8 * %%
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Lesser Public License for more details.
18 *
19 * You should have received a copy of the GNU General Lesser Public
20 * License along with this program.  If not, see
21 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22 * #L%
23 * Author: Robert Casties (casties@mpiwg-berlin.mpg.de)
24 */
25
26import java.io.File;
27import java.io.FileInputStream;
28import java.io.FileNotFoundException;
29import java.io.IOException;
30import java.io.InputStream;
31import java.util.Hashtable;
32import java.util.Properties;
33import java.util.concurrent.ConcurrentMap;
34
35import javax.naming.NamingEnumeration;
36import javax.naming.NamingException;
37import javax.naming.directory.Attribute;
38import javax.naming.directory.DirContext;
39import javax.naming.directory.InitialDirContext;
40import javax.naming.directory.SearchControls;
41import javax.naming.directory.SearchResult;
42import javax.servlet.ServletContext;
43
44import org.apache.log4j.BasicConfigurator;
45import org.apache.log4j.Logger;
46import org.neo4j.graphdb.GraphDatabaseService;
47import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
48import org.neo4j.graphdb.factory.GraphDatabaseFactory;
49import org.neo4j.graphdb.factory.GraphDatabaseSettings;
50import org.neo4j.kernel.GraphDatabaseAPI;
51import org.neo4j.server.WrappingNeoServerBootstrapper;
52import org.restlet.Application;
53import org.restlet.Context;
54import org.restlet.Restlet;
55import org.restlet.data.LocalReference;
56
57import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
58
59public abstract class BaseRestlet extends Application {
60
61    public static Logger logger = Logger.getLogger(BaseRestlet.class);
62
63    /**
64     * Properties holding consumer keys and secrets.
65     */
66    protected Properties consumerKeys;
67    public String CONSUMER_KEYS_PATH = "consumerkeys.property";
68    public static final String CONSUMERKEYS_KEY = "annotationmanager.consumerkeys";
69
70    /**
71     * Properties holding server config.
72     */
73    protected Properties serverConfig;
74    public String CONFIG_PROPS_PATH = "serverconfig.property";
75    public static final String SERVERCONFIG_KEY = "annotationmanager.serverconfig";
76
77    /**
78     * database instance;
79     */
80    protected GraphDatabaseService graphDb;
81    public static final String GRAPHDB_KEY = "annotationmanager.graphdb";
82    public static final String GRAPHDB_PATH_KEY = "annotationmanager.graphdb.path";
83    public String graphdbPath = "neo4j-annotation-db";
84
85    /**
86     * database interface server instance.
87     */
88    protected WrappingNeoServerBootstrapper srv;
89    public static final String GRAPHDBSRV_KEY = "annotationmanager.graphdb.srv";
90
91    /**
92     * annotation store instance.
93     */
94    protected AnnotationStore store;
95    public static final String ANNSTORE_KEY = "annotationmanager.store";
96
97    /**
98     * LDAP server URI (for looking up full user names).
99     */
100    protected String ldapServerUrl;
101    public static final String LDAP_SERVER_KEY = "annotationmanager.ldapserver.url";
102
103    public static final String ADMIN_USER_KEY = "annotationmanager.admin.user";
104    public static final String ADMIN_PASSWORD_KEY = "annotationmanager.admin.password";
105
106    /**
107     * run in authorization mode i.e. with tokens.
108     */
109    protected boolean authorizationMode = false;
110    public static final String AUTHORIZATION_MODE_KEY = "annotationmanager.authorization";
111   
112    /**
113     * prefix to create uris for tags in store.
114     */
115    public static String TAGS_URI_PREFIX = "";
116    public static final String TAGS_URI_KEY = "annotationmanager.uris.tags";
117
118    /**
119     * prefix to create uris for persons in store.
120     */
121    public static String PERSONS_URI_PREFIX = "";
122    public static final String PERSONS_URI_KEY = "annotationmanager.uris.persons";
123
124    /**
125     * prefix to create uris for groups in store.
126     */
127    public static String GROUPS_URI_PREFIX = ""; 
128    public static final String GROUPS_URI_KEY = "annotationmanager.uris.groups";
129
130    public static final String ANNOTATIONS_URI_KEY = "annotationmanager.uris.annotations";
131
132    /**
133     * constructor
134     *
135     * @param context
136     */
137    public BaseRestlet(Context context) {
138        super(context);
139        configure(context);
140    }
141
142    /**
143     * Configures the restlet.
144     * Reads serverConfig, consumerKeys and graphDb config from config files and starts graphDb.
145     * Uses config from webapp context if already initialized.
146     * @param context
147     */
148    protected void configure(Context context) {
149        Context ctx = Context.getCurrent();
150        ConcurrentMap<String, Object> attrs = ctx.getAttributes();
151        ServletContext sc = null;
152        if (context != null) {
153            Restlet a = context.getServerDispatcher();
154            Context b = a.getContext();
155            ConcurrentMap<String, Object> c = b.getAttributes();
156            sc = (ServletContext) context.getServerDispatcher().getContext().getAttributes()
157                .get("org.restlet.ext.servlet.ServletContext");
158        }
159        if (attrs != null) {
160            if (attrs.get("annotationserver.log4j.configured") == null) {
161                // TODO: is this the right place to run the log4j configurator?
162                BasicConfigurator.configure();
163                attrs.put("annotationserver.log4j.configured", "done");
164            }
165            logger.info(getVersion() + " starting...");
166
167            /*
168             * read config from webapp
169             */
170            serverConfig = (Properties) attrs.get(SERVERCONFIG_KEY);
171            if (serverConfig == null) {
172                serverConfig = new Properties();
173                InputStream ps = getResourceAsStream(sc, CONFIG_PROPS_PATH);
174                if (ps != null) {
175                    logger.debug("loading config from " + CONFIG_PROPS_PATH);
176                    try {
177                        serverConfig.load(ps);
178                        /*
179                         * read serverconfig options
180                         */
181                        graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
182                        ldapServerUrl = serverConfig.getProperty(LDAP_SERVER_KEY, null);
183                        /*
184                         * uri prefixes
185                         */
186                        if (serverConfig.containsKey(PERSONS_URI_KEY)) {
187                            BaseRestlet.PERSONS_URI_PREFIX = serverConfig.getProperty(PERSONS_URI_KEY);
188                        }
189                        if (serverConfig.containsKey(GROUPS_URI_KEY)) {
190                            BaseRestlet.GROUPS_URI_PREFIX = serverConfig.getProperty(GROUPS_URI_KEY);
191                        }
192                        if (serverConfig.containsKey(TAGS_URI_KEY)) {
193                            BaseRestlet.TAGS_URI_PREFIX = serverConfig.getProperty(TAGS_URI_KEY);
194                        }
195                        if (serverConfig.containsKey(ANNOTATIONS_URI_KEY)) {
196                            AnnotationStore.ANNOTATION_URI_PREFIX = serverConfig.getProperty(ANNOTATIONS_URI_KEY);
197                        }
198                    } catch (IOException e) {
199                        logger.warn("Error loading server config: ", e);
200                    }
201                    logger.debug("config: " + serverConfig);
202                } else {
203                    logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
204                }
205                // store config
206                attrs.put(SERVERCONFIG_KEY, serverConfig);
207            }
208            // look for database service in context
209            graphDb = (GraphDatabaseService) attrs.get(GRAPHDB_KEY);
210            if (graphDb == null) {
211                /*
212                 * open database
213                 */
214                String dbFn = getResourcePath(sc, graphdbPath);
215                if (dbFn != null) {
216                    logger.debug("opening DB " + dbFn);
217                    GraphDatabaseBuilder graphDbBuilder = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(dbFn);
218                    graphDbBuilder.setConfig(GraphDatabaseSettings.allow_store_upgrade, "true");
219                    graphDb = graphDbBuilder.newGraphDatabase();
220                    registerShutdownHook(graphDb);
221                    // store in context
222                    attrs.put(GRAPHDB_KEY, graphDb);
223                    // AnnotationStore
224                    store = new AnnotationStore(graphDb);
225                    attrs.put(ANNSTORE_KEY, store);
226                    // admin server
227                    srv = new WrappingNeoServerBootstrapper((GraphDatabaseAPI) graphDb);
228                    logger.debug("Starting DB admin server...");
229                    // store in context
230                    attrs.put(GRAPHDBSRV_KEY, srv);
231                    srv.start();
232                } else {
233                    logger.error("Unable to get resource " + dbFn);
234                }
235            } else {
236                // get existing AnnotationStore
237                store = (AnnotationStore) attrs.get(ANNSTORE_KEY);
238            }
239            /*
240             * read consumerKeys from webapp
241             */
242            consumerKeys = (Properties) attrs.get(CONSUMERKEYS_KEY);
243            if (consumerKeys == null) {
244                consumerKeys = new Properties();
245                InputStream ps = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
246                if (ps != null) {
247                    logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
248                    try {
249                        consumerKeys.load(ps);
250                    } catch (IOException e) {
251                        // TODO Auto-generated catch block
252                        e.printStackTrace();
253                    }
254                    logger.debug("consumer keys: " + consumerKeys);
255                } else {
256                    logger.error("Unable to get resource " + CONSUMER_KEYS_PATH);
257                }
258                // store config
259                attrs.put(CONSUMERKEYS_KEY, consumerKeys);
260            }
261        } else {
262            logger.error("Unable to get ServletContext!");
263        }
264    }
265
266    public abstract String getVersion();
267
268    /**
269     * @return the authorizationMode
270     */
271    public boolean isAuthorizationMode() {
272        return authorizationMode;
273    }
274
275    /**
276     * @return the store
277     */
278    public AnnotationStore getAnnotationStore() {
279        return store;
280    }
281
282    /**
283     * returns consumer secret for consumer key. returns null if consumer key
284     * doesn't exist.
285     *
286     * @param consumerKey
287     * @return
288     */
289    public String getConsumerSecret(String consumerKey) {
290        return consumerKeys.getProperty(consumerKey);
291    }
292
293    /**
294     * Hole den vollen Benutzernamen aus dem LDAP
295     *
296     * @param creator
297     * @return
298     */
299    public String getFullNameFromLdap(String creator) {
300        String retString = creator; // falls nichts gefunden wird einfach den
301                                    // creator zurueckgeben
302        if (ldapServerUrl == null) {
303            return retString;
304        }
305        Hashtable<String, String> env = new Hashtable<String, String>();
306        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
307        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
308        env.put(javax.naming.Context.PROVIDER_URL, ldapServerUrl);
309
310        DirContext dctx;
311        try {
312            dctx = new InitialDirContext(env);
313        } catch (NamingException e) {
314            logger.error("Error in getFullNameFromLDAP!", e);
315            return retString;
316        }
317
318        String base = "ou=people";
319
320        SearchControls sc = new SearchControls();
321        String[] attributeFilter = { "cn", "mail" };
322        sc.setReturningAttributes(attributeFilter);
323        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
324
325        String filter = "(uid=" + creator + ")";
326
327        try {
328            NamingEnumeration<SearchResult> results = dctx.search(base, filter, sc);
329            while (results.hasMore()) {
330                SearchResult sr = (SearchResult) results.next();
331                javax.naming.directory.Attributes attrs = sr.getAttributes();
332
333                Attribute attr = attrs.get("cn");
334                retString = (String) attr.get();
335            }
336        } catch (NamingException e) {
337            logger.error("Error in getFullNameFromLDAP!", e);
338        }
339
340        try {
341            dctx.close();
342        } catch (NamingException e) {
343            logger.error("Error in getFullNameFromLDAP!", e);
344        }
345        return retString;
346    }
347
348    /**
349     * returns resource from path (in webapp) as InputStream.
350     *
351     * @param sc
352     * @param path
353     * @return
354     */
355    protected InputStream getResourceAsStream(ServletContext sc, String path) {
356        InputStream ps = null;
357        if (sc == null) {
358            ps = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
359        } else {
360            ps = sc.getResourceAsStream(path);
361            if (ps == null) {
362                // try as file
363                File pf = new File(sc.getRealPath(path));
364                if (pf != null) {
365                    logger.debug("trying file for: " + pf);
366                    try {
367                        ps = new FileInputStream(pf);
368                    } catch (FileNotFoundException e) {
369                        logger.error(e);
370                    }
371                }
372            }
373        }
374        return ps;
375    }
376
377    /**
378     * get a real file name for a web app file pathname.
379     *
380     * If filename starts with "/" its treated as absolute else the path is
381     * appended to the base directory of the web-app.
382     *
383     * @param filename
384     * @param sc
385     * @return
386     */
387    public static String getResourcePath(ServletContext sc, String filename) {
388        File f = new File(filename);
389        // is the filename absolute?
390        if (!f.isAbsolute() && sc != null) {
391            // relative path -> use getRealPath to resolve in webapp
392            filename = sc.getRealPath(filename);
393        }
394        return filename;
395    }
396
397    /*
398     * (non-Javadoc)
399     *
400     * @see org.restlet.Application#stop()
401     */
402    @Override
403    public synchronized void stop() throws Exception {
404        /*
405         * trying to clean up databases, not sure if this is the right way...
406         */
407        if (srv != null) {
408            logger.debug("Stopping DB admin server...");
409            srv.stop();
410            srv = null;
411        }
412        if (graphDb != null) {
413            logger.debug("Stopping DB...");
414            graphDb.shutdown();
415            graphDb = null;
416        }
417        super.stop();
418    }
419
420    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
421        // Registers a shutdown hook for the Neo4j instance so that it
422        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
423        // running example before it's completed)
424        Runtime.getRuntime().addShutdownHook(new Thread() {
425            @Override
426            public void run() {
427                graphDb.shutdown();
428            }
429        });
430    }
431
432}
Note: See TracBrowser for help on using the repository browser.