source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 74:e5ff09208c28

Last change on this file since 74:e5ff09208c28 was 74:e5ff09208c28, checked in by casties, 10 years ago

search files in webapp in WEB-INF folder.

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