source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java @ 58:f5c0e6df7e88

Last change on this file since 58:f5c0e6df7e88 was 58:f5c0e6df7e88, checked in by casties, 11 years ago

made uri prefixes in store configurable.

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