df65be3284cb9e05f5293ab035950e4422be6e17
[moon.git] /
1 /*
2  * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.aaa.store;
10
11 import java.io.File;
12 import java.lang.management.ManagementFactory;
13 import java.util.Dictionary;
14 import java.util.Hashtable;
15 import java.util.concurrent.locks.ReentrantLock;
16 import javax.management.MBeanServer;
17 import net.sf.ehcache.Cache;
18 import net.sf.ehcache.CacheManager;
19 import net.sf.ehcache.Element;
20 import net.sf.ehcache.config.CacheConfiguration;
21 import net.sf.ehcache.management.ManagementService;
22 import org.apache.felix.dm.Component;
23 import org.opendaylight.aaa.api.Authentication;
24 import org.opendaylight.aaa.api.TokenStore;
25 import org.osgi.service.cm.ConfigurationException;
26 import org.osgi.service.cm.ManagedService;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * A default token store for STS.
32  *
33  * @author liemmn
34  *
35  */
36 public class DefaultTokenStore implements TokenStore, ManagedService {
37     private static final Logger LOG = LoggerFactory.getLogger(DefaultTokenStore.class);
38     private static final String TOKEN_STORE_CONFIG_ERR = "Token store configuration error";
39
40     private static final String TOKEN_CACHE_MANAGER = "org.opendaylight.aaa";
41     private static final String TOKEN_CACHE = "tokens";
42     private static final String EHCACHE_XML = "etc/ehcache.xml";
43
44     static final String MAX_CACHED_MEMORY = "maxCachedTokensInMemory";
45     static final String MAX_CACHED_DISK = "maxCachedTokensOnDisk";
46     static final String SECS_TO_LIVE = "secondsToLive";
47     static final String SECS_TO_IDLE = "secondsToIdle";
48
49     // Defaults (needed only for non-Karaf deployments)
50     static final Dictionary<String, String> defaults = new Hashtable<>();
51     static {
52         defaults.put(MAX_CACHED_MEMORY, Long.toString(10000));
53         defaults.put(MAX_CACHED_DISK, Long.toString(1000000));
54         defaults.put(SECS_TO_IDLE, Long.toString(3600));
55         defaults.put(SECS_TO_LIVE, Long.toString(3600));
56     }
57
58     // Token cache lock
59     private static final ReentrantLock cacheLock = new ReentrantLock();
60
61     // Token cache
62     private Cache tokens;
63
64     // This should be a singleton
65     DefaultTokenStore() {
66     }
67
68     // Called by DM when all required dependencies are satisfied.
69     void init(Component c) {
70         File ehcache = new File(EHCACHE_XML);
71         CacheManager cm;
72         if (ehcache.exists()) {
73             cm = CacheManager.create(ehcache.getAbsolutePath());
74             tokens = cm.getCache(TOKEN_CACHE);
75             LOG.info("Initialized token store with custom cache config");
76         } else {
77             cm = CacheManager.getInstance();
78             tokens = new Cache(
79                     new CacheConfiguration(TOKEN_CACHE,
80                             Integer.parseInt(defaults.get(MAX_CACHED_MEMORY))).maxEntriesLocalDisk(
81                             Integer.parseInt(defaults.get(MAX_CACHED_DISK)))
82                                                                               .timeToLiveSeconds(
83                                                                                       Long.parseLong(defaults.get(SECS_TO_LIVE)))
84                                                                               .timeToIdleSeconds(
85                                                                                       Long.parseLong(defaults.get(SECS_TO_IDLE))));
86             cm.addCache(tokens);
87             LOG.info("Initialized token store with default cache config");
88         }
89         cm.setName(TOKEN_CACHE_MANAGER);
90
91         // JMX for cache management
92         MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
93         ManagementService.registerMBeans(cm, mBeanServer, false, false, false, true);
94     }
95
96     // Called on shutdown
97     void destroy() {
98         LOG.info("Shutting down token store...");
99         CacheManager.getInstance().shutdown();
100     }
101
102     @Override
103     public Authentication get(String token) {
104         Element elem = tokens.get(token);
105         return (Authentication) ((elem != null) ? elem.getObjectValue() : null);
106     }
107
108     @Override
109     public void put(String token, Authentication auth) {
110         tokens.put(new Element(token, auth));
111     }
112
113     @Override
114     public boolean delete(String token) {
115         return tokens.remove(token);
116     }
117
118     @Override
119     public long tokenExpiration() {
120         return tokens.getCacheConfiguration().getTimeToLiveSeconds();
121     }
122
123     @Override
124     public void updated(@SuppressWarnings("rawtypes") Dictionary props)
125             throws ConfigurationException {
126         LOG.info("Updating token store configuration...");
127         if (props == null) {
128             // Someone deleted the configuration, use defaults
129             props = defaults;
130         }
131         reconfig(props);
132     }
133
134     // Refresh cache configuration...
135     private void reconfig(@SuppressWarnings("rawtypes") Dictionary props)
136             throws ConfigurationException {
137         cacheLock.lock();
138         try {
139             long secsToIdle = Long.parseLong(props.get(SECS_TO_IDLE).toString());
140             long secsToLive = Long.parseLong(props.get(SECS_TO_LIVE).toString());
141             int maxMem = Integer.parseInt(props.get(MAX_CACHED_MEMORY).toString());
142             int maxDisk = Integer.parseInt(props.get(MAX_CACHED_DISK).toString());
143             CacheConfiguration config = tokens.getCacheConfiguration();
144             config.setTimeToIdleSeconds(secsToIdle);
145             config.setTimeToLiveSeconds(secsToLive);
146             config.maxEntriesLocalHeap(maxMem);
147             config.maxEntriesLocalDisk(maxDisk);
148         } catch (Throwable t) {
149             throw new ConfigurationException(null, TOKEN_STORE_CONFIG_ERR, t);
150         } finally {
151             cacheLock.unlock();
152         }
153     }
154 }