source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 72:4c2cea836bc0

Last change on this file since 72:4c2cea836bc0 was 72:4c2cea836bc0, checked in by casties, 10 years ago

restlet 2.1 works now. (it's the start() method, stupid!)

File size: 15.6 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    /* (non-Javadoc)
134     * @see org.restlet.Application#start()
135     */
136    @Override
137    public synchronized void start() throws Exception {
138        configure(getContext());
139        super.start();
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        ConcurrentMap<String, Object> attrs = context.getAttributes();
150        ServletContext sc = (ServletContext) attrs.get("org.restlet.ext.servlet.ServletContext");
151        if (sc != null) {
152            if (sc.getAttribute("annotationserver.log4j.configured") == null) {
153                // TODO: is this the right place to run the log4j configurator?
154                BasicConfigurator.configure();
155                sc.setAttribute("annotationserver.log4j.configured", "done");
156            }
157            logger.info(getVersion() + " starting...");
158
159            /*
160             * read config from webapp
161             */
162            serverConfig = (Properties) sc.getAttribute(SERVERCONFIG_KEY);
163            if (serverConfig == null) {
164                serverConfig = new Properties();
165                InputStream ps = getResourceAsStream(sc, CONFIG_PROPS_PATH);
166                if (ps != null) {
167                    logger.debug("loading config from " + CONFIG_PROPS_PATH);
168                    try {
169                        serverConfig.load(ps);
170                        /*
171                         * read serverconfig options
172                         */
173                        graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
174                        ldapServerUrl = serverConfig.getProperty(LDAP_SERVER_KEY, null);
175                        /*
176                         * uri prefixes
177                         */
178                        if (serverConfig.containsKey(PERSONS_URI_KEY)) {
179                            BaseRestlet.PERSONS_URI_PREFIX = serverConfig.getProperty(PERSONS_URI_KEY);
180                        }
181                        if (serverConfig.containsKey(GROUPS_URI_KEY)) {
182                            BaseRestlet.GROUPS_URI_PREFIX = serverConfig.getProperty(GROUPS_URI_KEY);
183                        }
184                        if (serverConfig.containsKey(TAGS_URI_KEY)) {
185                            BaseRestlet.TAGS_URI_PREFIX = serverConfig.getProperty(TAGS_URI_KEY);
186                        }
187                        if (serverConfig.containsKey(ANNOTATIONS_URI_KEY)) {
188                            AnnotationStore.ANNOTATION_URI_PREFIX = serverConfig.getProperty(ANNOTATIONS_URI_KEY);
189                        }
190                    } catch (IOException e) {
191                        logger.warn("Error loading server config: ", e);
192                    }
193                    logger.debug("config: " + serverConfig);
194                } else {
195                    logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
196                }
197                // store config
198                sc.setAttribute(SERVERCONFIG_KEY, serverConfig);
199            }
200            // look for database service in context
201            graphDb = (GraphDatabaseService) sc.getAttribute(GRAPHDB_KEY);
202            if (graphDb == null) {
203                /*
204                 * open database
205                 */
206                String dbFn = getResourcePath(sc, graphdbPath);
207                if (dbFn != null) {
208                    logger.debug("opening DB " + dbFn);
209                    GraphDatabaseBuilder graphDbBuilder = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(dbFn);
210                    graphDbBuilder.setConfig(GraphDatabaseSettings.allow_store_upgrade, "true");
211                    graphDb = graphDbBuilder.newGraphDatabase();
212                    registerShutdownHook(graphDb);
213                    // store in context
214                    sc.setAttribute(GRAPHDB_KEY, graphDb);
215                    // AnnotationStore
216                    store = new AnnotationStore(graphDb);
217                    sc.setAttribute(ANNSTORE_KEY, store);
218                    // admin server
219                    srv = new WrappingNeoServerBootstrapper((GraphDatabaseAPI) graphDb);
220                    logger.debug("Starting DB admin server...");
221                    // store in context
222                    sc.setAttribute(GRAPHDBSRV_KEY, srv);
223                    srv.start();
224                } else {
225                    logger.error("Unable to get resource " + dbFn);
226                }
227            } else {
228                // get existing AnnotationStore
229                store = (AnnotationStore) sc.getAttribute(ANNSTORE_KEY);
230            }
231            /*
232             * read consumerKeys from webapp
233             */
234            consumerKeys = (Properties) sc.getAttribute(CONSUMERKEYS_KEY);
235            if (consumerKeys == null) {
236                consumerKeys = new Properties();
237                InputStream ps = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
238                if (ps != null) {
239                    logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
240                    try {
241                        consumerKeys.load(ps);
242                    } catch (IOException e) {
243                        // TODO Auto-generated catch block
244                        e.printStackTrace();
245                    }
246                    logger.debug("consumer keys: " + consumerKeys);
247                } else {
248                    logger.error("Unable to get resource " + CONSUMER_KEYS_PATH);
249                }
250                // store config
251                sc.setAttribute(CONSUMERKEYS_KEY, consumerKeys);
252            }
253        } else {
254            logger.error("Unable to get ServletContext!");
255        }
256    }
257
258    public abstract String getVersion();
259
260    /**
261     * @return the authorizationMode
262     */
263    public boolean isAuthorizationMode() {
264        return authorizationMode;
265    }
266
267    /**
268     * @return the store
269     */
270    public AnnotationStore getAnnotationStore() {
271        return store;
272    }
273
274    /**
275     * returns consumer secret for consumer key. returns null if consumer key
276     * doesn't exist.
277     *
278     * @param consumerKey
279     * @return
280     */
281    public String getConsumerSecret(String consumerKey) {
282        return consumerKeys.getProperty(consumerKey);
283    }
284
285    /**
286     * Hole den vollen Benutzernamen aus dem LDAP
287     *
288     * @param creator
289     * @return
290     */
291    public String getFullNameFromLdap(String creator) {
292        String retString = creator; // falls nichts gefunden wird einfach den
293                                    // creator zurueckgeben
294        if (ldapServerUrl == null) {
295            return retString;
296        }
297        Hashtable<String, String> env = new Hashtable<String, String>();
298        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
299        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
300        env.put(javax.naming.Context.PROVIDER_URL, ldapServerUrl);
301
302        DirContext dctx;
303        try {
304            dctx = new InitialDirContext(env);
305        } catch (NamingException e) {
306            logger.error("Error in getFullNameFromLDAP!", e);
307            return retString;
308        }
309
310        String base = "ou=people";
311
312        SearchControls sc = new SearchControls();
313        String[] attributeFilter = { "cn", "mail" };
314        sc.setReturningAttributes(attributeFilter);
315        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
316
317        String filter = "(uid=" + creator + ")";
318
319        try {
320            NamingEnumeration<SearchResult> results = dctx.search(base, filter, sc);
321            while (results.hasMore()) {
322                SearchResult sr = (SearchResult) results.next();
323                javax.naming.directory.Attributes attrs = sr.getAttributes();
324
325                Attribute attr = attrs.get("cn");
326                retString = (String) attr.get();
327            }
328        } catch (NamingException e) {
329            logger.error("Error in getFullNameFromLDAP!", e);
330        }
331
332        try {
333            dctx.close();
334        } catch (NamingException e) {
335            logger.error("Error in getFullNameFromLDAP!", e);
336        }
337        return retString;
338    }
339
340    /**
341     * returns resource from path (in webapp) as InputStream.
342     *
343     * @param sc
344     * @param path
345     * @return
346     */
347    protected InputStream getResourceAsStream(ServletContext sc, String path) {
348        InputStream ps = null;
349        if (sc == null) {
350            // no servlet context -> use class loader
351            ps = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
352            /* Request request = new Request(Method.GET, "riap://component/ping");
353               Response response = getContext().getClientDispatcher().handle(request);
354               Representation repr = response.getEntity(); */
355        } else {
356            // try path in webapp first
357            ps = sc.getResourceAsStream(path);
358            if (ps == null) {
359                // try as file
360                File pf = new File(sc.getRealPath(path));
361                if (pf.canRead()) {
362                    logger.debug("trying file for: " + pf);
363                    try {
364                        ps = new FileInputStream(pf);
365                    } catch (FileNotFoundException e) {
366                        logger.error(e);
367                    }
368                } else {
369                    // use class loader
370                    ps = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);                   
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.