1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.isenshi.util.extlib;
17
18 import java.lang.reflect.Method;
19 import java.util.Collection;
20 import java.util.Hashtable;
21 import java.util.Map;
22 import java.util.Properties;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25
26 import javax.naming.InitialContext;
27 import javax.naming.NamingException;
28
29 import org.aopalliance.intercept.MethodInterceptor;
30 import org.aopalliance.intercept.MethodInvocation;
31 import org.apache.commons.collections.map.ReferenceMap;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.ldap.server.configuration.SyncConfiguration;
35 import org.seasar.tuigwaa.security.DirectoryService;
36
37
38 /***
39 * @author someda
40 */
41 public class ApacheDSSyncInterceptor implements MethodInterceptor {
42
43 private Hashtable environment;
44 private Properties props;
45
46 private Log log = LogFactory.getLog(getClass());
47
48 private Map roleCacheMap;
49 private Map userCacheMap;
50
51 private Pattern GET_METHOD_PATTERN = Pattern.compile("get(User|Role)(s)?");
52
53 private boolean embeded = true;
54
55 public ApacheDSSyncInterceptor(Hashtable environment, Properties props){
56
57 this.environment = new Hashtable();
58
59
60 this.environment.putAll(environment);
61 this.props = props;
62 init();
63 }
64
65 public Object invoke(MethodInvocation invocation) throws Throwable {
66
67 Object ret = null;
68 boolean success = false;
69
70 Object[] args = invocation.getArguments();
71 Method method = invocation.getMethod();
72 String methodName = method.getName();
73 Class returnType = method.getReturnType();
74
75 Matcher m = GET_METHOD_PATTERN.matcher(methodName);
76 if(m.find()){
77
78 boolean isUser = "user".equalsIgnoreCase(m.group(1));
79 boolean isCollection = Collection.class.isAssignableFrom(returnType);
80
81 if(!isCollection){
82 ret = getCache(invocation,args,isUser);
83 }else{
84 ret = invokeMethod(invocation);
85 }
86
87 }else{
88
89 ret = invokeMethod(invocation);
90 success = true;
91 refresh();
92 }
93
94
95 if(success){
96 syncConfiguration();
97 }
98 return ret;
99 }
100
101 private Object getCache(MethodInvocation invocation, Object[] args, boolean isUser) throws Throwable{
102
103 Object ret = null;
104 Object key = args[0];
105 if(isUser){
106 ret = userCacheMap.get(key);
107 }else{
108 ret = roleCacheMap.get(key);
109 }
110
111 if(ret == null){
112 log.info("cache miss for " + key.toString() + " load from directory.");
113 ret= invokeMethod(invocation);
114 if(isUser){
115 userCacheMap.put(key,ret);
116 }else{
117 roleCacheMap.put(key,ret);
118 }
119 }
120 return ret;
121 }
122
123 private Object invokeMethod(MethodInvocation invocation) throws Throwable{
124 return invocation.proceed();
125 }
126
127 private void init(){
128 String value = props.getProperty(DirectoryService.EMBEDED);
129 if(value != null && !value.equals("")){
130 embeded = Boolean.valueOf(value).booleanValue();
131 }
132 if(embeded)
133 environment.putAll(new SyncConfiguration().toJndiEnvironment());
134
135 refresh();
136 }
137
138 private void refresh(){
139 log.info("refreshing cache.");
140 roleCacheMap = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
141 userCacheMap = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
142 }
143
144 private void syncConfiguration(){
145 if(embeded){
146 try{
147 new InitialContext(environment);
148 log.info("completed to sync directory service information.");
149 }catch(NamingException ne){
150 log.error("failed to sync directory service information.");
151 throw new RuntimeException(ne);
152 }
153 }
154 }
155
156 }