1 package org.apache.fulcrum.yaafi.framework.interceptor;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Method;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorage;
27 import org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorageImpl;
28 import org.apache.fulcrum.yaafi.framework.util.ToStringBuilder;
29 import org.apache.fulcrum.yaafi.framework.util.Validate;
30
31 /**
32 * Contains context information for the interceptors being invoked. The
33 * class contains a request context which allows to store data from within an
34 * interceptor. It also provides access to a ThreadLocalStorage to associate
35 * data with the current thread.
36 *
37 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
38 */
39
40 public class AvalonInterceptorContextImpl implements AvalonInterceptorContext
41 {
42 /** key for looking up the transaction id */
43 private static final String TRANSACTIONID_KEY =
44 "$org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext#transactionId";
45
46 /** key for looking up the service invocation depth */
47 private static final String INVOCATIONDEPTH_KEY =
48 "$org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext#invocationDepth";
49
50 /** the name of the service being intercepted */
51 private String serviceName;
52
53 /** the shorthand of the service being intercepted */
54 private String serviceShorthand;
55
56 /** the real service implementation */
57 private Object serviceDelegate;
58
59 /** the method being invoked */
60 private Method method;
61
62 /** the arguments for the method invocation */
63 private Object[] args;
64
65 /** context information associated with the current invocation */
66 private HashMap requestContext;
67
68 /** context information associated with the current thread */
69 private static ThreadLocalStorageImpl tls = new ThreadLocalStorageImpl();
70
71 /** works as invocation counter */
72 private static volatile long invocationCounter = 0L;
73
74 /** the associated transaction id */
75 private Long invocationId;
76
77 /**
78 * Constructor.
79 *
80 * @param serviceName the name of the service being intercepted
81 * @param serviceShorthand the shorthand of the service being intercepted
82 * @param serviceDelegate the real service implementation
83 * @param method the method being invoked
84 * @param args the list of arguments for the method invocation
85 */
86 public AvalonInterceptorContextImpl(
87 String serviceName, String serviceShorthand, Object serviceDelegate, Method method, Object[] args )
88 {
89 Validate.notEmpty(serviceName,"serviceName");
90 Validate.notEmpty(serviceShorthand,"serviceShorthand");
91 Validate.notNull(serviceDelegate,"serviceDelegate");
92 Validate.notNull(method,"method");
93
94 this.invocationId = new Long(++AvalonInterceptorContextImpl.invocationCounter);
95 this.serviceName = serviceName;
96 this.serviceShorthand = serviceShorthand;
97 this.serviceDelegate = serviceDelegate;
98 this.method = method;
99 this.args = args;
100 this.requestContext = new HashMap();
101 }
102
103 /**
104 * @return Returns the context for the given request.
105 */
106 public final Map getRequestContext()
107 {
108 return requestContext;
109 }
110
111 /**
112 * @return Returns the serviceDelegate.
113 */
114 public final Object getServiceDelegate()
115 {
116 return serviceDelegate;
117 }
118
119 /**
120 * @return Returns the serviceName.
121 */
122 public final String getServiceName()
123 {
124 return serviceName;
125 }
126
127 /**
128 * @return Returns the serviceShorthand.
129 */
130 public String getServiceShorthand()
131 {
132 return serviceShorthand;
133 }
134
135 /**
136 * @return Returns the args.
137 */
138 public final Object [] getArgs()
139 {
140 return args;
141 }
142
143 /**
144 * @return Returns the method.
145 */
146 public final Method getMethod()
147 {
148 return method;
149 }
150
151 /**
152 * @return Returns the ThreadLocalStorage
153 */
154 public final ThreadLocalStorage getThreadContext()
155 {
156 return AvalonInterceptorContextImpl.tls;
157 }
158
159 /**
160 * @return is a transaction id defined for the current thread
161 */
162 public boolean hasTransactionId()
163 {
164 return ( this.getTransactionId() != null ? true : false );
165 }
166
167 /**
168 * @return get the transaction id defined for the current thread
169 */
170 public Object getTransactionId()
171 {
172 return this.getThreadContext().get(TRANSACTIONID_KEY);
173 }
174
175 /**
176 * Set the transaction id for the current thread.
177 * @param transactionId the transaction id
178 */
179 public void setTransactionId( Object transactionId )
180 {
181 this.getThreadContext().put(TRANSACTIONID_KEY,transactionId);
182 }
183
184 /**
185 * Clears the transaction id for the current thread.
186 */
187 public void clearTransactionId()
188 {
189 this.setTransactionId(null);
190 }
191
192 /**
193 * Increment the current service invocation depth
194 */
195 public void incrementInvocationDepth()
196 {
197 Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
198
199 if( invocationDepth != null )
200 {
201 int currInvocationDepth = invocationDepth.intValue();
202 this.getThreadContext().put(INVOCATIONDEPTH_KEY, new Integer(++currInvocationDepth));
203 }
204 else
205 {
206 this.getThreadContext().put(INVOCATIONDEPTH_KEY, new Integer(0));
207 }
208 }
209
210 /**
211 * Decrement the current service invocation depth
212 */
213 public void decrementInvocationDepth()
214 {
215 Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
216
217 if( invocationDepth != null )
218 {
219 int currInvocationDepth = invocationDepth.intValue();
220 this.getThreadContext().put(INVOCATIONDEPTH_KEY, new Integer(--currInvocationDepth));
221 }
222 }
223
224 /**
225 * Get the current service invocation depth
226 * @return the current service invocation depth
227 */
228 public int getInvocationDepth()
229 {
230 Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
231
232 if( invocationDepth != null )
233 {
234 return invocationDepth.intValue();
235 }
236 else
237 {
238 return 0;
239 }
240 }
241
242 /**
243 * @return Returns the invocationId.
244 */
245 public final Long getInvocationId()
246 {
247 return invocationId;
248 }
249
250 /**
251 * @see java.lang.Object#toString()
252 */
253 public String toString()
254 {
255 ToStringBuilder toStringBuilder = new ToStringBuilder(this);
256
257 toStringBuilder.append("serviceShorthand",this.serviceShorthand);
258 toStringBuilder.append("serviceName",this.serviceName);
259 toStringBuilder.append("serviceDelegate",this.serviceDelegate);
260 toStringBuilder.append("method",this.method.getName());
261 toStringBuilder.append("args",this.args.length);
262 toStringBuilder.append("transactionId",this.getTransactionId());
263 toStringBuilder.append("invocationId",this.invocationId);
264 toStringBuilder.append("invocationDepth",this.getInvocationDepth());
265 toStringBuilder.append("requestContext",this.requestContext);
266
267 return toStringBuilder.toString();
268 }
269 }