[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