1 17 package org.alfresco.repo.policy; 18 19 import java.lang.reflect.InvocationHandler ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 import java.util.Stack ; 26 27 import org.alfresco.util.ParameterCheck; 28 29 30 39 public class JavaBehaviour implements Behaviour 40 { 41 private Object instance; 43 44 private String method; 46 47 private Map <Class , Object > proxies = new HashMap <Class , Object >(); 49 50 private StackThreadLocal disabled = new StackThreadLocal(); 52 53 54 60 public JavaBehaviour(Object instance, String method) 61 { 62 ParameterCheck.mandatory("Instance", instance); 63 ParameterCheck.mandatory("Method", method); 64 this.instance = instance; 65 this.method = method; 66 } 67 68 69 72 @SuppressWarnings ("unchecked") 73 public synchronized <T> T getInterface(Class <T> policy) 74 { 75 ParameterCheck.mandatory("Policy class", policy); 76 Object proxy = proxies.get(policy); 77 if (proxy == null) 78 { 79 InvocationHandler handler = getInvocationHandler(instance, method, policy); 80 proxy = Proxy.newProxyInstance(policy.getClassLoader(), new Class []{policy}, handler); 81 proxies.put(policy, proxy); 82 } 83 return (T)proxy; 84 } 85 86 89 public void disable() 90 { 91 Stack <Integer > stack = disabled.get(); 92 stack.push(hashCode()); 93 } 94 95 98 public void enable() 99 { 100 Stack <Integer > stack = disabled.get(); 101 if (stack.peek().equals(hashCode()) == false) 102 { 103 throw new PolicyException("Cannot enable " + this.toString() + " at this time - mismatched with disable calls"); 104 } 105 stack.pop(); 106 } 107 108 111 public boolean isEnabled() 112 { 113 Stack <Integer > stack = disabled.get(); 114 return stack.search(hashCode()) == -1; 115 } 116 117 @Override 118 public String toString() 119 { 120 return "Java method[class=" + instance.getClass().getName() + ", method=" + method + "]"; 121 } 122 123 132 private <T> InvocationHandler getInvocationHandler(Object instance, String method, Class <T> policyIF) 133 { 134 Method [] policyIFMethods = policyIF.getMethods(); 135 if (policyIFMethods.length != 1) 136 { 137 throw new PolicyException("Policy interface " + policyIF.getCanonicalName() + " must have only one method"); 138 } 139 140 try 141 { 142 Class instanceClass = instance.getClass(); 143 Method delegateMethod = instanceClass.getMethod(method, (Class [])policyIFMethods[0].getParameterTypes()); 144 return new JavaMethodInvocationHandler(this, delegateMethod); 145 } 146 catch (NoSuchMethodException e) 147 { 148 throw new PolicyException("Method " + method + " not found or accessible on " + instance.getClass(), e); 149 } 150 } 151 152 153 158 private class StackThreadLocal extends ThreadLocal <Stack <Integer >> 159 { 160 @Override 161 protected Stack <Integer > initialValue() 162 { 163 return new Stack <Integer >(); 164 } 165 } 166 167 168 173 private static class JavaMethodInvocationHandler implements InvocationHandler 174 { 175 private JavaBehaviour behaviour; 176 private Method delegateMethod; 177 178 184 private JavaMethodInvocationHandler(JavaBehaviour behaviour, Method delegateMethod) 185 { 186 this.behaviour = behaviour; 187 this.delegateMethod = delegateMethod; 188 } 189 190 193 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable 194 { 195 if (method.getName().equals("toString")) 197 { 198 return toString(); 199 } 200 else if (method.getName().equals("hashCode")) 201 { 202 return hashCode(); 203 } 204 else if (method.getName().equals("equals")) 205 { 206 if (Proxy.isProxyClass(args[0].getClass())) 207 { 208 return equals(Proxy.getInvocationHandler(args[0])); 209 } 210 return false; 211 } 212 213 if (behaviour.isEnabled()) 215 { 216 try 217 { 218 behaviour.disable(); 219 return delegateMethod.invoke(behaviour.instance, args); 220 } 221 catch (InvocationTargetException e) 222 { 223 throw e.getTargetException(); 224 } 225 finally 226 { 227 behaviour.enable(); 228 } 229 } 230 return null; 231 } 232 233 @Override 234 public boolean equals(Object obj) 235 { 236 if (obj == this) 237 { 238 return true; 239 } 240 else if (obj == null || !(obj instanceof JavaMethodInvocationHandler)) 241 { 242 return false; 243 } 244 JavaMethodInvocationHandler other = (JavaMethodInvocationHandler)obj; 245 return behaviour.instance.equals(other.behaviour.instance) && delegateMethod.equals(other.delegateMethod); 246 } 247 248 @Override 249 public int hashCode() 250 { 251 return 37 * behaviour.instance.hashCode() + delegateMethod.hashCode(); 252 } 253 254 @Override 255 public String toString() 256 { 257 return "JavaBehaviour[instance=" + behaviour.instance.hashCode() + ", method=" + delegateMethod.toString() + "]"; 258 } 259 } 260 261 } 262 | Popular Tags |