[jboss-cvs] JBossCache/src/org/jboss/cache/pojo/util ...
Ben Wang
bwang at jboss.com
Sat Jan 13 10:55:00 EST 2007
User: bwang
Date: 07/01/13 10:55:00
Added: src/org/jboss/cache/pojo/util ObjectUtil.java
AopUtil.java CacheApiUtil.java Null.java
MethodCall.java
Log:
JBCACHE-922 Merged src-50 and tests-50 into src and tests, respectively.
Revision Changes Path
1.1 date: 2007/01/13 15:55:00; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/util/ObjectUtil.java
Index: ObjectUtil.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.aop.Advised;
import org.jboss.cache.CacheException;
import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.CachedType;
import org.jboss.cache.pojo.PojoCacheException;
import org.jboss.cache.pojo.impl.PojoCacheImpl;
import org.jboss.cache.pojo.memory.FieldPersistentReference;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Unitlity methods for pojo object.
*
* @author Ben Wang
*/
public final class ObjectUtil
{
private static final Log log = LogFactory.getLog(ObjectUtil.class.getName());
/**
* Static methos to check if <code>thisObject</code> is reachable from <code>originalObject</code>.
*
* @param cache
* @param originalObject
* @param thisObject
* @return
* @throws CacheException
*/
public static boolean isReachable(PojoCacheImpl cache, Object originalObject, Object thisObject)
throws CacheException
{
HashSet objSet = new HashSet();
return isReachableInner(cache, originalObject, thisObject, objSet);
}
private static boolean isReachableInner(PojoCacheImpl cache, Object originalObject,
Object thisObject, Set objSet)
throws CacheException
{
// Currently we don't support recursive Collection
if (!(originalObject instanceof Advised))
throw new PojoCacheException("ObjectUtil.isReachable(): originalObject is not Advised.");
if (log.isTraceEnabled())
{
log.trace("isReachable(): current object: " + originalObject + " this object: " + thisObject);
}
if (originalObject.equals(thisObject))
{
if (log.isTraceEnabled())
{
log.trace("isReachable(): object found reachable.");
}
return true;
}
if (!objSet.contains(originalObject))
{
objSet.add(originalObject);
} else
{ // We have been here before so let's return.
return false;
}
CachedType type = cache.getCachedType(originalObject.getClass());
for (Iterator i = type.getFields().iterator(); i.hasNext();)
{
Field field = (Field) (((FieldPersistentReference) i.next())).get();
Object value = null;
try
{
value = field.get(originalObject); // Reflection may not work here.
}
catch (IllegalAccessException e)
{
throw new CacheException("field access failed", e);
}
CachedType fieldType = cache.getCachedType(field.getType());
if (fieldType.isImmediate())
{
} else
{
if (value instanceof Map)
{
Set set = ((Map) value).keySet();
for (Iterator it = set.iterator(); it.hasNext();)
{
if (isReachableInner(cache, it.next(), thisObject, objSet))
return true;
}
continue;
} else if (value instanceof Collection)
{
for (Iterator it = ((Collection) value).iterator(); it.hasNext();)
{
if (isReachableInner(cache, it.next(), thisObject, objSet))
return true;
}
continue;
}
if (!(value instanceof Advised))
continue; // TODO We don't care about Collection now.
if (isReachableInner(cache, value, thisObject, objSet))
return true;
}
}
return false;
}
public static String getIndirectFqn(Fqn fqn)
{
// TODO Need to generate a unique id here
// Let's strip off the line separator and use underscoe instead.
return getIndirectFqn(fqn.toString());
}
public static String getIndirectFqn(String fqn)
{
// TODO Need to generate a unique id here
// Let's strip off the line separator and use underscoe instead.
return fqn.replace('/', '_');
}
}
1.1 date: 2007/01/13 15:55:00; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/util/AopUtil.java
Index: AopUtil.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.aop.Advised;
import org.jboss.aop.InstanceAdvisor;
import org.jboss.aop.advice.Interceptor;
import org.jboss.cache.Fqn;
import org.jboss.cache.Cache;
import org.jboss.cache.Region;
import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
import org.jboss.cache.pojo.InternalConstant;
import org.jboss.cache.pojo.InvocationContext;
import org.jboss.util.id.GUID;
import java.io.Serializable;
/**
* Unitlity methods for put, get and remove Collection classes object.
*
* @author Ben Wang
*/
public final class AopUtil
{
static final Log log = LogFactory.getLog(AopUtil.class.getName());
public static final String SEPARATOR = "/";
/**
* Find cache interceptor with exact fqn.
*
* @param advisor
* @param fqn
* @return Interceptor
*/
static public Interceptor findCacheInterceptor(InstanceAdvisor advisor, Fqn fqn)
{
org.jboss.aop.advice.Interceptor[] interceptors = advisor.getInterceptors();
// Step Check for cross references
for (int i = 0; i < interceptors.length; i++)
{
Interceptor interceptor = interceptors[i];
if (interceptor instanceof CacheFieldInterceptor)
{
CacheFieldInterceptor inter = (CacheFieldInterceptor) interceptor;
if (inter != null && inter.getFqn().equals(fqn))
{
return interceptor;
}
}
}
return null;
}
/**
* Find existing cache interceptor. Since there is supposedly only one cache interceptor per
* pojo, this call should suffice. In addition, in cases of cross or circular reference,
* fqn can be different anyway.
*
* @param advisor
* @return Interceptor
*/
static public Interceptor findCacheInterceptor(InstanceAdvisor advisor)
{
// TODO we assume there is only one interceptor now.
Interceptor[] interceptors = advisor.getInterceptors();
// Step Check for cross references
for (int i = 0; i < interceptors.length; i++)
{
Interceptor interceptor = interceptors[i];
if (interceptor instanceof CacheFieldInterceptor)
{
return interceptor;
}
}
return null;
}
/**
* Find existing Collection interceptor. Since there is supposedly only one Collection interceptor per
* instance, this call should suffice. In addition, in cases of cross or circular reference,
* fqn can be different anyway.
*
* @param advisor
* @return Interceptor
*/
static public Interceptor findCollectionInterceptor(InstanceAdvisor advisor)
{
// TODO we assume there is only one interceptor now.
Interceptor[] interceptors = advisor.getInterceptors();
// Step Check for cross references
for (int i = 0; i < interceptors.length; i++)
{
Interceptor interceptor = interceptors[i];
if (interceptor instanceof BaseInterceptor)
{
return interceptor;
}
}
return null;
}
/**
* Check whether the object type is valid. An object type is valid if it is either: aspectized,
* Serializable, or primitive type. Otherwise a runtime exception is thrown.
*
* @param obj
*/
public static void checkObjectType(Object obj)
{
if (obj == null) return;
if (! (obj instanceof Advised))
{
boolean allowedType = (obj instanceof Serializable) || (obj.getClass().isArray() && obj.getClass().getComponentType().isPrimitive());
if (!allowedType)
{
throw new IllegalArgumentException("PojoCache.putObject(): Object type is neither " +
" aspectized nor Serializable nor an array of primitives. Object class name is " + obj.getClass().getName());
}
}
}
public static Fqn constructFqn(Fqn baseFqn, Object relative)
{
// TODO Don't know why. But this will fail the CachedSetAopTest clear() method since look up is always
// Null at the last index. But why?
// TODO also see JBCACHE-282
return new Fqn(baseFqn, relative.toString());
// String tmp = baseFqn.toString() +"/" + relative.toString();
// return Fqn.fromString(tmp);
// Fqn fqn = new Fqn((String)relative);
// return new Fqn(baseFqn, fqn);
}
public static Fqn createInternalFqn(Fqn fqn, Cache cache)
{
boolean createIfAbsent = false;
Region region = cache.getRegion(fqn, createIfAbsent);
// Use guid that is cluster-wide unique.
GUID guid = new GUID();
if(region == null)
{
return new Fqn(InternalConstant.JBOSS_INTERNAL, Fqn.fromString(guid.toString()));
} else
{
// Create it under region first.
return new Fqn(region.getFqn(), InternalConstant.JBOSS_INTERNAL_STRING, guid.toString());
}
}
}
1.1 date: 2007/01/13 15:55:00; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/util/CacheApiUtil.java
Index: CacheApiUtil.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.util;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.config.Option;
import java.util.Set;
/**
* Utility for the 2.0 Cache API
*
* @author Ben Wang
* @version $Id: CacheApiUtil.java,v 1.1 2007/01/13 15:55:00 bwang Exp $
*/
public class CacheApiUtil
{
public static Node XgetDataNode(CacheSPI cache, Fqn fqn)
{
// cache.getInvocationContext().getOptionOverrides().setBypassInterceptorChain(true);
Node node = cache.getRoot().getChild(fqn);
if (node == null) return null;
// cache.getInvocationContext().getOptionOverrides().setBypassInterceptorChain(false);
return node;
}
public static Set<Node> getNodeChildren(CacheSPI cache, Fqn fqn)
{
Node n = cache.getRoot().getChild(fqn);
if (n == null) return null;
if (cache.getCacheLoaderManager() != null)
{
// We have cache loader, we can't get it directly from the local get.
return n.getChildren();
}
else
{
Option option = cache.getInvocationContext().getOptionOverrides();
// WIll run into some race error in LocalTest for Set.
// option.setBypassInterceptorChain(true);
return n.getChildren();
}
}
public static boolean exists(CacheSPI cache, Fqn fqn, Object key)
{
if (cache.getCacheLoaderManager() != null)
{
// Has cache loader
return (cache.get(fqn, key) != null);
}
NodeSPI node = cache.getRoot().getChildDirect(fqn);
return node != null && node.getKeysDirect().contains(key);
}
}
1.1 date: 2007/01/13 15:55:00; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/util/Null.java
Index: Null.java
===================================================================
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.util;
import java.io.Serializable;
/**
* Represent null values (based on org.jboss.util.Null)
*
* @author Scott Marlow
*/
public final class Null implements Serializable
{
static final long serialVersionUID = -402153636437493134L;
/**
* singleton instance of Null.
*/
private static final Null NULL_OBJECT_MARKER = new Null();
// String representation of Null
private static final String NULL_AS_STRING_REPRESENTATION = "jboss.cache._NULL_";
/**
* Do not allow public construction.
*/
private Null()
{
}
/**
* Represents null as a special Null object marker.
*
* @param aObject
* @return if aObject is null, return Null.NULL_OBJECT_MARKER otherwise return aObject.
*/
public final static Object toNullObject(Object aObject)
{
if (aObject == null)
{
return NULL_OBJECT_MARKER;
} else
{
return aObject;
}
}
/**
* Represents null key as a special string value.
*
* @param aObject
* @return if aObject is null, return Null.NULL_AS_STRING_REPRESENTATION otherwise return aObject.
*/
public final static Object toNullKeyObject(Object aObject)
{
if (aObject == null)
{
return NULL_AS_STRING_REPRESENTATION;
} else
{
return aObject;
}
}
/**
* If the passed object represents null (instance of Null.NULL_OBJECT_MARKER), will replace with null value.
*
* @param aObject
* @return null if aObject is instance of Null.NULL_OBJECT_MARKER, otherwise return aObject.
*/
public final static Object toNullValue(Object aObject)
{
if (NULL_OBJECT_MARKER.equals(aObject))
{
return null;
} else
{
return aObject;
}
}
/**
* Converts Null string representation back to null value.
*
* @param aObject
* @return null if aObject represents a null, otherwise return aObject.
*/
public final static Object toNullKeyValue(Object aObject)
{
if (NULL_AS_STRING_REPRESENTATION.equals(aObject))
{
return null;
} else
{
return aObject;
}
}
/**
* Return a string representation of null value.
*
* @return Null.NULL_AS_STRING_REPRESENTATION;
*/
public String toString()
{
return NULL_AS_STRING_REPRESENTATION;
}
/**
* Hashcode of unknown (null) value will be zero.
*
* @return Zero.
*/
public int hashCode()
{
return 0;
}
/**
* Check if the given object is a Null instance or <tt>null</tt>.
*
* @param obj Object to test.
* @return True if the given object is a Null instance or <tt>null</tt>.
*/
public boolean equals(final Object obj)
{
if (obj == this) return true;
return (obj == null || obj.getClass() == getClass() || NULL_AS_STRING_REPRESENTATION.equals(obj));
}
}
1.1 date: 2007/01/13 15:55:00; author: bwang; state: Exp;JBossCache/src/org/jboss/cache/pojo/util/MethodCall.java
Index: MethodCall.java
===================================================================
package org.jboss.cache.pojo.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A special MethodCall object to wrap around the rollback method call. No Serializable is required.
*
* @author Ben Wang
* @version $Revision: 1.1 $
*/
public class MethodCall
{
/**
* The name of the method, case sensitive.
*/
protected String method_name = null;
/**
* The arguments of the method.
*/
protected Object[] args = null;
/**
* The class types, e.g., new Class[]{String.class, int.class}.
*/
protected Class[] types = null;
/**
* The signature, e.g., new String[]{String.class.getLastElementAsString(), int.class.getLastElementAsString()}.
*/
protected String[] signature = null;
/**
* The Method of the call.
*/
protected Method method = null;
/*
* The target object to invoke upon.
*/
protected Object target = null;
protected static final Log log = LogFactory.getLog(MethodCall.class);
public MethodCall(Method method, Object[] arguments, Object target)
{
init(method);
if (arguments != null) args = arguments;
this.target = target;
}
private void init(Method method)
{
this.method = method;
method_name = method.getName();
}
public String getName()
{
return method_name;
}
public void setName(String n)
{
method_name = n;
}
public Object[] getArgs()
{
return args;
}
public void setArgs(Object[] args)
{
if (args != null)
this.args = args;
}
public Method getMethod()
{
return method;
}
public void setMethod(Method m)
{
init(m);
}
Method findMethod(Class target_class) throws Exception
{
int len = args != null ? args.length : 0;
Method m;
Method[] methods = getAllMethods(target_class);
for (int i = 0; i < methods.length; i++)
{
m = methods[i];
if (m.getName().equals(method_name))
{
if (m.getParameterTypes().length == len)
return m;
}
}
return null;
}
Method[] getAllMethods(Class target)
{
Class superclass = target;
List methods = new ArrayList();
int size = 0;
while (superclass != null)
{
Method[] m = superclass.getDeclaredMethods();
methods.add(m);
size += m.length;
superclass = superclass.getSuperclass();
}
Method[] result = new Method[size];
int index = 0;
for (Iterator i = methods.iterator(); i.hasNext();)
{
Method[] m = (Method[]) i.next();
System.arraycopy(m, 0, result, index, m.length);
index += m.length;
}
return result;
}
/**
* Returns the first method that matches the specified name and parameter types. The overriding
* methods have priority. The method is chosen from all the methods of the current class and all
* its superclasses and superinterfaces.
*
* @return the matching method or null if no mathching method has been found.
*/
Method getMethod(Class target, String methodName, Class[] types)
{
if (types == null)
{
types = new Class[0];
}
Method[] methods = getAllMethods(target);
methods:
for (int i = 0; i < methods.length; i++)
{
Method m = methods[i];
if (!methodName.equals(m.getName()))
{
continue;
}
Class[] parameters = m.getParameterTypes();
if (types.length != parameters.length)
{
continue;
}
for (int j = 0; j < types.length; j++)
{
if (!types[j].equals(parameters[j]))
{
continue methods;
}
}
return m;
}
return null;
}
public Object invoke() throws Throwable
{
return this.invoke(this.target);
}
/**
* Invokes the method with the supplied arguments against the target object.
* If a method lookup is provided, it will be used. Otherwise, the default
* method lookup will be used.
*
* @param target - the object that you want to invoke the method on
* @return an object
*/
protected Object invoke(Object target) throws Throwable
{
Class cl;
Method meth = null;
Object retval = null;
if (method_name == null || target == null)
{
if (log.isErrorEnabled()) log.error("method name or target is null");
return null;
}
cl = target.getClass();
try
{
if (this.method != null)
meth = this.method;
if (meth != null)
{
retval = meth.invoke(target, args);
}
else
{
throw new NoSuchMethodException(method_name);
}
return retval;
}
catch (InvocationTargetException inv_ex)
{
throw inv_ex.getTargetException();
}
catch (NoSuchMethodException no)
{
StringBuffer sb = new StringBuffer();
sb.append("found no method called ").append(method_name).append(" in class ");
sb.append(cl.getName()).append(" with (");
if (args != null)
{
for (int i = 0; i < args.length; i++)
{
if (i > 0)
sb.append(", ");
sb.append((args[i] != null) ? args[i].getClass().getName() : "null");
}
}
sb.append(") formal parameters");
log.error(sb.toString());
throw no;
}
catch (Throwable e)
{
// e.printStackTrace(System.err);
if (log.isErrorEnabled()) log.error("exception in invoke()", e);
throw e;
}
}
public Object invoke(Object target, Object[] args) throws Throwable
{
if (args != null)
this.args = args;
return invoke(target);
}
Class[] getTypesFromString(Class cl, String[] signature) throws Exception
{
String name;
Class parameter;
Class[] mytypes = new Class[signature.length];
for (int i = 0; i < signature.length; i++)
{
name = signature[i];
if ("long".equals(name))
parameter = long.class;
else if ("int".equals(name))
parameter = int.class;
else if ("short".equals(name))
parameter = short.class;
else if ("char".equals(name))
parameter = char.class;
else if ("byte".equals(name))
parameter = byte.class;
else if ("float".equals(name))
parameter = float.class;
else if ("double".equals(name))
parameter = double.class;
else if ("boolean".equals(name))
parameter = boolean.class;
else
parameter = Class.forName(name, false, cl.getClassLoader());
mytypes[i] = parameter;
}
return mytypes;
}
public String toString()
{
StringBuffer ret = new StringBuffer();
boolean first = true;
if (method_name != null)
ret.append(method_name);
ret.append('(');
if (args != null)
{
for (int i = 0; i < args.length; i++)
{
if (first)
first = false;
else
ret.append(", ");
ret.append(args[i]);
}
}
ret.append(')');
return ret.toString();
}
public String toStringDetails()
{
StringBuffer ret = new StringBuffer();
ret.append("MethodCall ");
if (method_name != null)
ret.append("name=").append(method_name);
ret.append(", number of args=").append((args != null ? args.length : 0)).append(')');
if (args != null)
{
ret.append("\nArgs:");
for (int i = 0; i < args.length; i++)
{
ret.append("\n[").append(args[i]).append(" (").
append((args[i] != null ? args[i].getClass().getName() : "null")).append(")]");
}
}
return ret.toString();
}
}
More information about the jboss-cvs-commits
mailing list