View Javadoc
1   package org.apache.fulcrum.yaafi.framework.interceptor;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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 Map<String, Object> 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 = Long.valueOf(++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<String, Object>();
101     }
102 
103     /**
104      * @return Returns the context for the given request.
105      */
106     public final Map<String, Object> 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, Integer.valueOf(++currInvocationDepth));
203         }
204         else
205         {
206             this.getThreadContext().put(INVOCATIONDEPTH_KEY, Integer.valueOf(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, Integer.valueOf(--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 }