source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 80:4724fc7b4733

Last change on this file since 80:4724fc7b4733 was 80:4724fc7b4733, checked in by casties, 10 years ago

add slashes to paths for getRealPath to work with Tomcat 8.

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