View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
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  		// copy environemt values to local environment object
59  		// because this interceptor overides configuration.
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  			// invocation.proceed and refresh cache
89  			ret = invokeMethod(invocation);
90  			success = true;
91  			refresh();		
92  		}
93  		
94  		// sync file if required
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 }