KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > policy > JavaBehaviour


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.policy;
18
19 import java.lang.reflect.InvocationHandler JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Proxy JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Stack JavaDoc;
26
27 import org.alfresco.util.ParameterCheck;
28
29
30 /**
31  * Java based Behaviour.
32  *
33  * A behavior acts like a delegate (a method pointer). The pointer is
34  * represented by an instance object and method name.
35  *
36  * @author David Caruana
37  *
38  */

39 public class JavaBehaviour implements Behaviour
40 {
41     // The object instance holding the method
42
private Object JavaDoc instance;
43     
44     // The method name
45
private String JavaDoc method;
46     
47     // Cache of interface proxies (by interface class)
48
private Map JavaDoc<Class JavaDoc, Object JavaDoc> proxies = new HashMap JavaDoc<Class JavaDoc, Object JavaDoc>();
49     
50     // Enable / Disable invocation of behaviour
51
private StackThreadLocal disabled = new StackThreadLocal();
52
53     
54     /**
55      * Construct.
56      *
57      * @param instance the object instance holding the method
58      * @param method the method name
59      */

60     public JavaBehaviour(Object JavaDoc instance, String JavaDoc method)
61     {
62         ParameterCheck.mandatory("Instance", instance);
63         ParameterCheck.mandatory("Method", method);
64         this.instance = instance;
65         this.method = method;
66     }
67
68
69     /* (non-Javadoc)
70      * @see org.alfresco.repo.policy.Behaviour#getInterface(java.lang.Class)
71      */

72     @SuppressWarnings JavaDoc("unchecked")
73     public synchronized <T> T getInterface(Class JavaDoc<T> policy)
74     {
75         ParameterCheck.mandatory("Policy class", policy);
76         Object JavaDoc proxy = proxies.get(policy);
77         if (proxy == null)
78         {
79             InvocationHandler JavaDoc handler = getInvocationHandler(instance, method, policy);
80             proxy = Proxy.newProxyInstance(policy.getClassLoader(), new Class JavaDoc[]{policy}, handler);
81             proxies.put(policy, proxy);
82         }
83         return (T)proxy;
84     }
85
86     /* (non-Javadoc)
87      * @see org.alfresco.repo.policy.Behaviour#disable()
88      */

89     public void disable()
90     {
91         Stack JavaDoc<Integer JavaDoc> stack = disabled.get();
92         stack.push(hashCode());
93     }
94
95     /* (non-Javadoc)
96      * @see org.alfresco.repo.policy.Behaviour#enable()
97      */

98     public void enable()
99     {
100         Stack JavaDoc<Integer JavaDoc> 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     /* (non-Javadoc)
109      * @see org.alfresco.repo.policy.Behaviour#isEnabled()
110      */

111     public boolean isEnabled()
112     {
113         Stack JavaDoc<Integer JavaDoc> stack = disabled.get();
114         return stack.search(hashCode()) == -1;
115     }
116     
117     @Override JavaDoc
118     public String JavaDoc toString()
119     {
120         return "Java method[class=" + instance.getClass().getName() + ", method=" + method + "]";
121     }
122
123     /**
124      * Gets the Invocation Handler.
125      *
126      * @param <T> the policy interface class
127      * @param instance the object instance
128      * @param method the method name
129      * @param policyIF the policy interface class
130      * @return the invocation handler
131      */

132     private <T> InvocationHandler JavaDoc getInvocationHandler(Object JavaDoc instance, String JavaDoc method, Class JavaDoc<T> policyIF)
133     {
134         Method JavaDoc[] 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 JavaDoc instanceClass = instance.getClass();
143             Method JavaDoc delegateMethod = instanceClass.getMethod(method, (Class JavaDoc[])policyIFMethods[0].getParameterTypes());
144             return new JavaMethodInvocationHandler(this, delegateMethod);
145         }
146         catch (NoSuchMethodException JavaDoc e)
147         {
148             throw new PolicyException("Method " + method + " not found or accessible on " + instance.getClass(), e);
149         }
150     }
151     
152
153     /**
154      * Stack specific Thread Local
155      *
156      * @author David Caruana
157      */

158     private class StackThreadLocal extends ThreadLocal JavaDoc<Stack JavaDoc<Integer JavaDoc>>
159     {
160         @Override JavaDoc
161         protected Stack JavaDoc<Integer JavaDoc> initialValue()
162         {
163             return new Stack JavaDoc<Integer JavaDoc>();
164         }
165     }
166     
167     
168     /**
169      * Java Method Invocation Handler
170      *
171      * @author David Caruana
172      */

173     private static class JavaMethodInvocationHandler implements InvocationHandler JavaDoc
174     {
175         private JavaBehaviour behaviour;
176         private Method JavaDoc delegateMethod;
177         
178         /**
179          * Constuct.
180          *
181          * @param instance the object instance holding the method
182          * @param delegateMethod the method to invoke
183          */

184         private JavaMethodInvocationHandler(JavaBehaviour behaviour, Method JavaDoc delegateMethod)
185         {
186             this.behaviour = behaviour;
187             this.delegateMethod = delegateMethod;
188         }
189
190         /* (non-Javadoc)
191          * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
192          */

193         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
194         {
195             // Handle Object level methods
196
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             // Delegate to designated method pointer
214
if (behaviour.isEnabled())
215             {
216                 try
217                 {
218                     behaviour.disable();
219                     return delegateMethod.invoke(behaviour.instance, args);
220                 }
221                 catch (InvocationTargetException JavaDoc e)
222                 {
223                     throw e.getTargetException();
224                 }
225                 finally
226                 {
227                     behaviour.enable();
228                 }
229             }
230             return null;
231         }
232
233         @Override JavaDoc
234         public boolean equals(Object JavaDoc 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 JavaDoc
249         public int hashCode()
250         {
251             return 37 * behaviour.instance.hashCode() + delegateMethod.hashCode();
252         }
253
254         @Override JavaDoc
255         public String JavaDoc toString()
256         {
257             return "JavaBehaviour[instance=" + behaviour.instance.hashCode() + ", method=" + delegateMethod.toString() + "]";
258         }
259     }
260     
261 }
262
Popular Tags