blob: e300624681ea1472c9c689d4ff752c5a91131689 [file] [log] [blame]
package org.apache.fulcrum.yaafi.framework.interceptor;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorage;
import org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorageImpl;
import org.apache.fulcrum.yaafi.framework.util.ToStringBuilder;
import org.apache.fulcrum.yaafi.framework.util.Validate;
/**
* Contains context information for the interceptors being invoked. The
* class contains a request context which allows to store data from within an
* interceptor. It also provides access to a ThreadLocalStorage to associate
* data with the current thread.
*
* @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
*/
public class AvalonInterceptorContextImpl implements AvalonInterceptorContext
{
/** key for looking up the transaction id */
private static final String TRANSACTIONID_KEY =
"$org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext#transactionId";
/** key for looking up the service invocation depth */
private static final String INVOCATIONDEPTH_KEY =
"$org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext#invocationDepth";
/** the name of the service being intercepted */
private String serviceName;
/** the shorthand of the service being intercepted */
private String serviceShorthand;
/** the real service implementation */
private Object serviceDelegate;
/** the method being invoked */
private Method method;
/** the arguments for the method invocation */
private Object[] args;
/** context information associated with the current invocation */
private Map<String, Object> requestContext;
/** context information associated with the current thread */
private static ThreadLocalStorageImpl tls = new ThreadLocalStorageImpl();
/** works as invocation counter */
private static volatile long invocationCounter = 0L;
/** the associated transaction id */
private Long invocationId;
/**
* Constructor.
*
* @param serviceName the name of the service being intercepted
* @param serviceShorthand the shorthand of the service being intercepted
* @param serviceDelegate the real service implementation
* @param method the method being invoked
* @param args the list of arguments for the method invocation
*/
public AvalonInterceptorContextImpl(
String serviceName, String serviceShorthand, Object serviceDelegate, Method method, Object[] args )
{
Validate.notEmpty(serviceName,"serviceName");
Validate.notEmpty(serviceShorthand,"serviceShorthand");
Validate.notNull(serviceDelegate,"serviceDelegate");
Validate.notNull(method,"method");
this.invocationId = Long.valueOf(++AvalonInterceptorContextImpl.invocationCounter);
this.serviceName = serviceName;
this.serviceShorthand = serviceShorthand;
this.serviceDelegate = serviceDelegate;
this.method = method;
this.args = args;
this.requestContext = new HashMap<String, Object>();
}
/**
* @return Returns the context for the given request.
*/
public final Map<String, Object> getRequestContext()
{
return requestContext;
}
/**
* @return Returns the serviceDelegate.
*/
public final Object getServiceDelegate()
{
return serviceDelegate;
}
/**
* @return Returns the serviceName.
*/
public final String getServiceName()
{
return serviceName;
}
/**
* @return Returns the serviceShorthand.
*/
public String getServiceShorthand()
{
return serviceShorthand;
}
/**
* @return Returns the args.
*/
public final Object [] getArgs()
{
return args;
}
/**
* @return Returns the method.
*/
public final Method getMethod()
{
return method;
}
/**
* @return Returns the ThreadLocalStorage
*/
public final ThreadLocalStorage getThreadContext()
{
return AvalonInterceptorContextImpl.tls;
}
/**
* @return is a transaction id defined for the current thread
*/
public boolean hasTransactionId()
{
return ( this.getTransactionId() != null ? true : false );
}
/**
* @return get the transaction id defined for the current thread
*/
public Object getTransactionId()
{
return this.getThreadContext().get(TRANSACTIONID_KEY);
}
/**
* Set the transaction id for the current thread.
* @param transactionId the transaction id
*/
public void setTransactionId( Object transactionId )
{
this.getThreadContext().put(TRANSACTIONID_KEY,transactionId);
}
/**
* Clears the transaction id for the current thread.
*/
public void clearTransactionId()
{
this.setTransactionId(null);
}
/**
* Increment the current service invocation depth
*/
public void incrementInvocationDepth()
{
Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
if( invocationDepth != null )
{
int currInvocationDepth = invocationDepth.intValue();
this.getThreadContext().put(INVOCATIONDEPTH_KEY, Integer.valueOf(++currInvocationDepth));
}
else
{
this.getThreadContext().put(INVOCATIONDEPTH_KEY, Integer.valueOf(0));
}
}
/**
* Decrement the current service invocation depth
*/
public void decrementInvocationDepth()
{
Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
if( invocationDepth != null )
{
int currInvocationDepth = invocationDepth.intValue();
this.getThreadContext().put(INVOCATIONDEPTH_KEY, Integer.valueOf(--currInvocationDepth));
}
}
/**
* Get the current service invocation depth
* @return the current service invocation depth
*/
public int getInvocationDepth()
{
Integer invocationDepth = (Integer) this.getThreadContext().get(INVOCATIONDEPTH_KEY);
if( invocationDepth != null )
{
return invocationDepth.intValue();
}
else
{
return 0;
}
}
/**
* @return Returns the invocationId.
*/
public final Long getInvocationId()
{
return invocationId;
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
ToStringBuilder toStringBuilder = new ToStringBuilder(this);
toStringBuilder.append("serviceShorthand",this.serviceShorthand);
toStringBuilder.append("serviceName",this.serviceName);
toStringBuilder.append("serviceDelegate",this.serviceDelegate);
toStringBuilder.append("method",this.method.getName());
toStringBuilder.append("args",this.args.length);
toStringBuilder.append("transactionId",this.getTransactionId());
toStringBuilder.append("invocationId",this.invocationId);
toStringBuilder.append("invocationDepth",this.getInvocationDepth());
toStringBuilder.append("requestContext",this.requestContext);
return toStringBuilder.toString();
}
}