source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 70:2b1e6df5e21a

Last change on this file since 70:2b1e6df5e21a was 70:2b1e6df5e21a, checked in by casties, 10 years ago

added lgpl_v3 license information.

File size: 14.7 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;
33
34import javax.naming.NamingEnumeration;
35import javax.naming.NamingException;
36import javax.naming.directory.Attribute;
37import javax.naming.directory.DirContext;
38import javax.naming.directory.InitialDirContext;
39import javax.naming.directory.SearchControls;
40import javax.naming.directory.SearchResult;
41import javax.servlet.ServletContext;
42
43import org.apache.log4j.BasicConfigurator;
44import org.apache.log4j.Logger;
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(BaseRestlet.class);
59
60    /**
61     * Properties holding consumer keys and secrets.
62     */
63    protected Properties consumerKeys;
64    public String CONSUMER_KEYS_PATH = "WEB-INF/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 = "WEB-INF/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 = "WEB-INF/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     * constructor
131     *
132     * @param context
133     */
134    public BaseRestlet(Context context) {
135        super(context);
136        configure();
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     */
144    protected void configure() {
145        ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
146                .get("org.restlet.ext.servlet.ServletContext");
147        if (sc != null) {
148            if (sc.getAttribute("annotationserver.log4j.configured") == null) {
149                // TODO: is this the right place to run the log4j configurator?
150                BasicConfigurator.configure();
151                sc.setAttribute("annotationserver.log4j.configured", "done");
152            }
153            logger.info(getVersion() + " starting...");
154
155            /*
156             * read config from webapp
157             */
158            serverConfig = (Properties) sc.getAttribute(SERVERCONFIG_KEY);
159            if (serverConfig == null) {
160                serverConfig = new Properties();
161                InputStream ps = getResourceAsStream(sc, CONFIG_PROPS_PATH);
162                if (ps != null) {
163                    logger.debug("loading config from " + CONFIG_PROPS_PATH);
164                    try {
165                        serverConfig.load(ps);
166                        /*
167                         * read serverconfig options
168                         */
169                        graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
170                        ldapServerUrl = serverConfig.getProperty(LDAP_SERVER_KEY, null);
171                        /*
172                         * uri prefixes
173                         */
174                        if (serverConfig.containsKey(PERSONS_URI_KEY)) {
175                            BaseRestlet.PERSONS_URI_PREFIX = serverConfig.getProperty(PERSONS_URI_KEY);
176                        }
177                        if (serverConfig.containsKey(GROUPS_URI_KEY)) {
178                            BaseRestlet.GROUPS_URI_PREFIX = serverConfig.getProperty(GROUPS_URI_KEY);
179                        }
180                        if (serverConfig.containsKey(TAGS_URI_KEY)) {
181                            BaseRestlet.TAGS_URI_PREFIX = serverConfig.getProperty(TAGS_URI_KEY);
182                        }
183                        if (serverConfig.containsKey(ANNOTATIONS_URI_KEY)) {
184                            AnnotationStore.ANNOTATION_URI_PREFIX = serverConfig.getProperty(ANNOTATIONS_URI_KEY);
185                        }
186                    } catch (IOException e) {
187                        logger.warn("Error loading server config: ", e);
188                    }
189                    logger.debug("config: " + serverConfig);
190                } else {
191                    logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
192                }
193                // store config
194                sc.setAttribute(SERVERCONFIG_KEY, serverConfig);
195            }
196            // look for database service in context
197            graphDb = (GraphDatabaseService) sc.getAttribute(GRAPHDB_KEY);
198            if (graphDb == null) {
199                /*
200                 * open database
201                 */
202                String dbFn = getResourcePath(sc, graphdbPath);
203                if (dbFn != null) {
204                    logger.debug("opening DB " + dbFn);
205                    GraphDatabaseBuilder graphDbBuilder = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(dbFn);
206                    graphDbBuilder.setConfig(GraphDatabaseSettings.allow_store_upgrade, "true");
207                    graphDb = graphDbBuilder.newGraphDatabase();
208                    registerShutdownHook(graphDb);
209                    // store in context
210                    sc.setAttribute(GRAPHDB_KEY, graphDb);
211                    // AnnotationStore
212                    store = new AnnotationStore(graphDb);
213                    sc.setAttribute(ANNSTORE_KEY, store);
214                    // admin server
215                    srv = new WrappingNeoServerBootstrapper((GraphDatabaseAPI) graphDb);
216                    logger.debug("Starting DB admin server...");
217                    // store in context
218                    sc.setAttribute(GRAPHDBSRV_KEY, srv);
219                    srv.start();
220                } else {
221                    logger.error("Unable to get resource " + dbFn);
222                }
223            } else {
224                // get existing AnnotationStore
225                store = (AnnotationStore) sc.getAttribute(ANNSTORE_KEY);
226            }
227            /*
228             * read consumerKeys from webapp
229             */
230            consumerKeys = (Properties) sc.getAttribute(CONSUMERKEYS_KEY);
231            if (consumerKeys == null) {
232                consumerKeys = new Properties();
233                InputStream ps = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
234                if (ps != null) {
235                    logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
236                    try {
237                        consumerKeys.load(ps);
238                    } catch (IOException e) {
239                        // TODO Auto-generated catch block
240                        e.printStackTrace();
241                    }
242                    logger.debug("consumer keys: " + consumerKeys);
243                } else {
244                    logger.error("Unable to get resource " + CONSUMER_KEYS_PATH);
245                }
246                // store config
247                sc.setAttribute(CONSUMERKEYS_KEY, consumerKeys);
248            }
249        } else {
250            logger.error("Unable to get ServletContext!");
251        }
252    }
253
254    public abstract String getVersion();
255
256    /**
257     * @return the authorizationMode
258     */
259    public boolean isAuthorizationMode() {
260        return authorizationMode;
261    }
262
263    /**
264     * @return the store
265     */
266    public AnnotationStore getAnnotationStore() {
267        return store;
268    }
269
270    /**
271     * returns consumer secret for consumer key. returns null if consumer key
272     * doesn't exist.
273     *
274     * @param consumerKey
275     * @return
276     */
277    public String getConsumerSecret(String consumerKey) {
278        return consumerKeys.getProperty(consumerKey);
279    }
280
281    /**
282     * Hole den vollen Benutzernamen aus dem LDAP
283     *
284     * @param creator
285     * @return
286     */
287    public String getFullNameFromLdap(String creator) {
288        String retString = creator; // falls nichts gefunden wird einfach den
289                                    // creator zurueckgeben
290        if (ldapServerUrl == null) {
291            return retString;
292        }
293        Hashtable<String, String> env = new Hashtable<String, String>();
294        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
295        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
296        env.put(javax.naming.Context.PROVIDER_URL, ldapServerUrl);
297
298        DirContext dctx;
299        try {
300            dctx = new InitialDirContext(env);
301        } catch (NamingException e) {
302            logger.error("Error in getFullNameFromLDAP!", e);
303            return retString;
304        }
305
306        String base = "ou=people";
307
308        SearchControls sc = new SearchControls();
309        String[] attributeFilter = { "cn", "mail" };
310        sc.setReturningAttributes(attributeFilter);
311        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
312
313        String filter = "(uid=" + creator + ")";
314
315        try {
316            NamingEnumeration<SearchResult> results = dctx.search(base, filter, sc);
317            while (results.hasMore()) {
318                SearchResult sr = (SearchResult) results.next();
319                javax.naming.directory.Attributes attrs = sr.getAttributes();
320
321                Attribute attr = attrs.get("cn");
322                retString = (String) attr.get();
323            }
324        } catch (NamingException e) {
325            logger.error("Error in getFullNameFromLDAP!", e);
326        }
327
328        try {
329            dctx.close();
330        } catch (NamingException e) {
331            logger.error("Error in getFullNameFromLDAP!", e);
332        }
333        return retString;
334    }
335
336    /**
337     * returns resource from path (in webapp) as InputStream.
338     *
339     * @param sc
340     * @param path
341     * @return
342     */
343    protected InputStream getResourceAsStream(ServletContext sc, String path) {
344        InputStream ps = sc.getResourceAsStream(path);
345        if (ps == null) {
346            // try as file
347            File pf = new File(sc.getRealPath(path));
348            if (pf != null) {
349                logger.debug("trying file for: " + pf);
350                try {
351                    ps = new FileInputStream(pf);
352                } catch (FileNotFoundException e) {
353                    logger.error(e);
354                }
355            }
356        }
357        return ps;
358    }
359
360    /**
361     * get a real file name for a web app file pathname.
362     *
363     * If filename starts with "/" its treated as absolute else the path is
364     * appended to the base directory of the web-app.
365     *
366     * @param filename
367     * @param sc
368     * @return
369     */
370    public static String getResourcePath(ServletContext sc, String filename) {
371        File f = new File(filename);
372        // is the filename absolute?
373        if (!f.isAbsolute()) {
374            // relative path -> use getRealPath to resolve in webapp
375            filename = sc.getRealPath(filename);
376        }
377        return filename;
378    }
379
380    /*
381     * (non-Javadoc)
382     *
383     * @see org.restlet.Application#stop()
384     */
385    @Override
386    public synchronized void stop() throws Exception {
387        /*
388         * trying to clean up databases, not sure if this is the right way...
389         */
390        if (srv != null) {
391            logger.debug("Stopping DB admin server...");
392            srv.stop();
393            srv = null;
394        }
395        if (graphDb != null) {
396            logger.debug("Stopping DB...");
397            graphDb.shutdown();
398            graphDb = null;
399        }
400        super.stop();
401    }
402
403    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
404        // Registers a shutdown hook for the Neo4j instance so that it
405        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
406        // running example before it's completed)
407        Runtime.getRuntime().addShutdownHook(new Thread() {
408            @Override
409            public void run() {
410                graphDb.shutdown();
411            }
412        });
413    }
414
415}
Note: See TracBrowser for help on using the repository browser.