Package org.jboss.cache.interceptors

Source Code of org.jboss.cache.interceptors.MarshalledValueInterceptor

package org.jboss.cache.interceptors;

import org.jboss.cache.InvocationContext;
import org.jboss.cache.marshall.MarshalledValue;
import org.jboss.cache.marshall.MarshalledValueHelper;
import org.jboss.cache.marshall.MarshalledValueMap;
import org.jboss.cache.marshall.MethodCall;
import org.jboss.cache.marshall.MethodDeclarations;

import java.io.NotSerializableException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* Interceptor that handles the wrapping and unwrapping of cached data using {@link org.jboss.cache.marshall.MarshalledValue}s.
* Known "excluded" types are not wrapped/unwrapped, which at this time include {@link String}, Java primitives
* and their Object wrappers, as well as arrays of excluded types.
* <p/>
* The {@link org.jboss.cache.marshall.MarshalledValue} wrapper handles lazy deserialization from byte array representations.
*
* @author Manik Surtani (<a href="mailto:manik@jboss.org">manik@jboss.org</a>)
* @see org.jboss.cache.marshall.MarshalledValue
* @since 2.1.0
*/
public class MarshalledValueInterceptor extends Interceptor
{
   @Override
   public Object invoke(InvocationContext context) throws Throwable
   {
      MethodCall call = context.getMethodCall();
      boolean isAPICall = false;
      int id = call.getMethodId();
      Set<MarshalledValue> marshalledValues = null;

      // needs to work for *all* API method calls.
      if (MethodDeclarations.isAPIMethodCall(id) && id != MethodDeclarations.getNodeMethodLocal_id && id != MethodDeclarations.removeNodeMethodLocal_id)
      {
         marshalledValues = new HashSet<MarshalledValue>();
         isAPICall = true;
         if (trace) log.trace("Is API method; wrapping any args that need to be wrapped");
         // check arguments for any user-defined objects that may need to be wrapped.
         Object[] args = call.getArgs();
         Object[] replacementArgs = new Object[args.length];
         int counter = -1;

         for (Object o : args)
         {
            counter++;
            if (o == null || MarshalledValueHelper.isTypeExcluded(o.getClass()) || isInternalCollection(counter, id))
            {
               replacementArgs[counter] = o;
            }
            else if (needToReplaceMap(counter, id))
            {
               if (trace) log.trace("Wrapping map contents of argument " + counter);
               replacementArgs[counter] = wrapMap((Map) o, marshalledValues, context);
            }
            else
            {
               if (trace) log.trace("Wrapping argument " + counter + " which contains type " + o.getClass());
               replacementArgs[counter] = createAndAddMarshalledValue(o, marshalledValues, context);
            }
         }
         call.setArgs(replacementArgs);
      }

      Object retVal = nextInterceptor(context);

      if (isAPICall)
      {
         if (trace) log.trace("Compacting MarshalledValues created");
         for (MarshalledValue mv : marshalledValues) mv.compact(false, false);

         if (retVal instanceof MarshalledValue)
         {
            if (trace) log.trace("Return value is a MarshalledValue.  Unwrapping.");
            retVal = ((MarshalledValue) retVal).get();
         }
         else if (retVal instanceof Map && call.getMethodId() == MethodDeclarations.getDataMapMethodLocal_id)
         {
            if (trace) log.trace("Return value is a Map and we're retrieving data.  Wrapping as a MarshalledValueMap.");
            Map retValMap = (Map) retVal;
            if (!retValMap.isEmpty()) retVal = new MarshalledValueMap(retValMap);
         }
      }

      return retVal;
   }

   /**
    * prepare methods include Maps and Lists in args.  These should not be mistaken for needing wrapping as MarshalledValues.
    */
   protected boolean isInternalCollection(int argSubscript, int methodId)
   {
      return (methodId == MethodDeclarations.prepareMethod_id && argSubscript == 1) || (methodId == MethodDeclarations.optimisticPrepareMethod_id && (argSubscript == 1 || argSubscript == 2));
   }

   /**
    * put(Map) contents should not be wrapped since the map will need to be iterated over.  The contents of the Map, however, should be wrapped.
    */
   protected boolean needToReplaceMap(int argSubscript, int methodId)
   {
      return ((methodId == MethodDeclarations.putDataEraseMethodLocal_id || methodId == MethodDeclarations.putDataMethodLocal_id) &&
            argSubscript == 2);
   }

   @SuppressWarnings("unchecked")
   protected Map wrapMap(Map<Object, Object> m, Set<MarshalledValue> marshalledValues, InvocationContext ctx) throws NotSerializableException
   {
      Map copy = new HashMap();
      for (Map.Entry me : m.entrySet())
      {
         Object key = me.getKey();
         Object value = me.getValue();
         copy.put((key == null || MarshalledValueHelper.isTypeExcluded(key.getClass())) ? key : createAndAddMarshalledValue(key, marshalledValues, ctx),
               (value == null || MarshalledValueHelper.isTypeExcluded(value.getClass())) ? value : createAndAddMarshalledValue(value, marshalledValues, ctx));
      }
      return copy;
   }

   protected MarshalledValue createAndAddMarshalledValue(Object toWrap, Set<MarshalledValue> marshalledValues, InvocationContext ctx) throws NotSerializableException
   {
      MarshalledValue mv = new MarshalledValue(toWrap);
      marshalledValues.add(mv);
      if (!ctx.isOriginLocal()) mv.setEqualityPreferenceForInstance(false);
      return mv;
   }
}
TOP

Related Classes of org.jboss.cache.interceptors.MarshalledValueInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.