[jboss-cvs] jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper ...

Shane Bryzak sbryzak at redhat.com
Tue Feb 27 17:15:24 EST 2007


  User: sbryzak2
  Date: 07/02/27 17:15:24

  Added:       src/remoting/org/jboss/seam/remoting/wrapper             
                        BagWrapper.java BaseWrapper.java BeanWrapper.java
                        BooleanWrapper.java ConversionException.java
                        ConversionScore.java DateWrapper.java
                        MapWrapper.java NullWrapper.java NumberWrapper.java
                        StringWrapper.java Wrapper.java WrapperFactory.java
  Log:
  JBSEAM-915
  
  Revision  Changes    Path
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/BagWrapper.java
  
  Index: BagWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Array;
  import java.lang.reflect.ParameterizedType;
  import java.lang.reflect.Type;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashSet;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Queue;
  import java.util.Set;
  
  import org.dom4j.Element;
  import org.hibernate.collection.PersistentCollection;
  
  /**
   * Wrapper for collections, arrays, etc.
   *
   * @author Shane Bryzak
   */
  public class BagWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] BAG_TAG_OPEN = "<bag>".getBytes();
    private static final byte[] BAG_TAG_CLOSE = "</bag>".getBytes();
  
    private static final byte[] ELEMENT_TAG_OPEN = "<element>".getBytes();
    private static final byte[] ELEMENT_TAG_CLOSE = "</element>".getBytes();
  
    public void marshal(OutputStream out) throws IOException
    {
      out.write(BAG_TAG_OPEN);
  
      // Fix to prevent uninitialized lazy loading in Hibernate
      if (value instanceof PersistentCollection)
      {
        if (!((PersistentCollection) value).wasInitialized())
        {
          out.write(BAG_TAG_CLOSE);
          return;
        }
      }
  
      Collection vals = null;
  
      // If the value is an array, convert it to a Collection
      if (value.getClass().isArray())
      {
        vals = new ArrayList();
        for (int i = 0; i < Array.getLength(value); i++)
          vals.add(Array.get(value, i));
      }
      else if (Collection.class.isAssignableFrom(value.getClass()))
        vals = (Collection) value;
      else
        throw new RuntimeException(String.format(
          "Can not marshal object as bag: [%s]", value));
  
      for (Object val : vals)
      {
        out.write(ELEMENT_TAG_OPEN);
        context.createWrapperFromObject(val, path).marshal(out);
        out.write(ELEMENT_TAG_CLOSE);
      }
  
      out.write(BAG_TAG_CLOSE);
    }
  
    @SuppressWarnings("unchecked")
    public Object convert(Type type)
        throws ConversionException
    {
      // First convert the elements in the bag to a List of Wrappers
      List<Wrapper> vals = new ArrayList<Wrapper>();
  
      for (Element e : (List<Element>) element.elements("element"))
        vals.add(context.createWrapperFromElement((Element) e.elements().get(0)));
  
      if (type instanceof Class && ((Class) type).isArray())
      {
        Class arrayType = ((Class) type).getComponentType();
        value = Array.newInstance(arrayType, vals.size()); // Fix this
        for (int i = 0; i < vals.size(); i++)
          Array.set(value, i, vals.get(i).convert(arrayType));
      }
      else if (type instanceof Class && Collection.class.isAssignableFrom((Class) type))
      {
        try {
          value = getConcreteClass( (Class) type).newInstance();
        }
        catch (Exception ex) {
          throw new ConversionException(String.format(
              "Could not create instance of target type [%s].", type));
        }
        for (Wrapper w : vals)
          ((Collection) value).add(w.convert(Object.class));
      }
      else if (type instanceof ParameterizedType &&
               Collection.class.isAssignableFrom((Class) ((ParameterizedType) type).getRawType()))
      {
        Class rawType = (Class) ((ParameterizedType) type).getRawType();
        Class genType = Object.class;
  
        for (Type t : ((ParameterizedType) type).getActualTypeArguments())
        {
          if (t instanceof Class) // Take the first Class we find
          {
            genType = (Class) t;
            break;
          }
        }
  
        try {
          value = getConcreteClass(rawType).newInstance();
        }
        catch (Exception ex) {
          throw new ConversionException(String.format(
              "Could not create instance of target type [%s].", rawType));
        }
  
        for (Wrapper w : vals)
          ((Collection) value).add(w.convert(genType));
      }
  
      return value;
    }
  
    private Class getConcreteClass(Class c)
    {
      if (c.isInterface())
      {
        // Support Set, Queue and (by default, and as a last resort) List
        if (Set.class.isAssignableFrom(c))
          return HashSet.class;
        else if (Queue.class.isAssignableFrom(c))
          return LinkedList.class;
        else
          return ArrayList.class;
      }
      else
        return c;
    }
  
    /**
     *
     * @param cls Class
     * @return ConversionScore
     */
    public ConversionScore conversionScore(Class cls)
    {
      // There's no such thing as an exact match for a bag, so we'll just look for
      // a compatible match
  
      if (cls.isArray())
        return ConversionScore.compatible;
  
      if (cls.equals(Object.class))
        return ConversionScore.compatible;
  
      if (Collection.class.isAssignableFrom(cls))
        return ConversionScore.compatible;
  
      return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/BaseWrapper.java
  
  Index: BaseWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  
  import org.dom4j.Element;
  import org.jboss.seam.remoting.CallContext;
  
  /**
   * Base class for all Wrapper implementations.
   *
   * @author Shane Bryzak
   */
  public abstract class BaseWrapper implements Wrapper
  {
    /**
     * The path of this object within the result object graph
     */
    protected String path;
  
    /**
     * The call context
     */
    protected CallContext context;
  
    /**
     * The DOM4J element containing the value
     */
    protected Element element;
  
    /**
     * The wrapped value
     */
    protected Object value;
  
    /**
     * Sets the path.
     *
     * @param path String
     */
    public void setPath(String path)
    {
      this.path = path;
    }
  
    /**
     * Sets the wrapped value
     *
     * @param value Object
     */
    public void setValue(Object value)
    {
      this.value = value;
    }
  
    /**
     * Returns the wrapped value
     *
     * @return Object
     */
    public Object getValue()
    {
      return value;
    }
  
    /**
     * Sets the call context
     */
    public void setCallContext(CallContext context)
    {
      this.context = context;
    }
  
    /**
     * Extracts a value from a DOM4J Element
     *
     * @param element Element
     */
    public void setElement(Element element)
    {
      this.element = element;
    }
  
    /**
     * Default implementation does nothing
     */
    public void unmarshal() {}
  
    /**
     * Default implementation does nothing
     *
     * @param out OutputStream
     * @throws IOException
     */
    public void serialize(OutputStream out) throws IOException { }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/BeanWrapper.java
  
  Index: BeanWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Field;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Type;
  import java.util.List;
  
  import org.dom4j.Element;
  import org.jboss.seam.Component;
  import org.jboss.seam.Seam;
  import org.jboss.seam.remoting.InterfaceGenerator;
  import org.jboss.seam.util.Reflections;
  
  /**
   * @author Shane Bryzak
   */
  public class BeanWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] REF_START_TAG_OPEN = "<ref id=\"".getBytes();
    private static final byte[] REF_START_TAG_END = "\"/>".getBytes();
  
    private static final byte[] BEAN_START_TAG_OPEN = "<bean type=\"".getBytes();
    private static final byte[] BEAN_START_TAG_CLOSE = "\">".getBytes();
    private static final byte[] BEAN_CLOSE_TAG = "</bean>".getBytes();
  
    private static final byte[] MEMBER_START_TAG_OPEN = "<member name=\"".getBytes();
    private static final byte[] MEMBER_START_TAG_CLOSE = "\">".getBytes();
    private static final byte[] MEMBER_CLOSE_TAG = "</member>".getBytes();
  
    @Override
    public void setElement(Element element)
    {
      super.setElement(element);
  
      String beanType = element.attributeValue("type");
  
      Component component = Component.forName(beanType);
  
      if (component != null)
      {
        value = component.newInstance();
      }
      else
      {
        try {
          value = Reflections.classForName(beanType).newInstance();
        }
        catch (Exception ex) {
          throw new RuntimeException("Could not unmarshal bean element: " + element.getText(), ex);
        }
      }
    }
  
    @Override
    public void unmarshal()
    {
      List members = element.elements("member");
  
      for (Element member : (List<Element>) members)
      {
        String name = member.attributeValue("name");
  
        Wrapper w = context.createWrapperFromElement((Element) member.elementIterator().next());
  
        Class cls = value.getClass();
  
        // We're going to try a combination of ways to set the property value here
        Method method = null;
        Field field = null;
                
        // First try to find the best matching method
        String setter = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
        
        ConversionScore score = ConversionScore.nomatch;
        for (Method m : cls.getMethods())
        {
           if (setter.equals(m.getName()) && m.getParameterTypes().length == 1)
           {
              ConversionScore s = w.conversionScore(m.getParameterTypes()[0]);
              if (s.getScore() > score.getScore())
              {
                 method = m;
                 score = s;
              }
           }
        }    
        
        // If we can't find a method, look for a matching field name
        if (method == null)
        {
           while (field == null && !cls.equals(Object.class))
           {
             try
             {
               // First check the declared fields
               field = cls.getDeclaredField(name);
             }
             catch (NoSuchFieldException ex)
             {
               // Couldn't find the field.. try the superclass
               cls = cls.getSuperclass();
             }
           }
  
           if (field == null)
           {
             throw new RuntimeException(String.format(
               "Error while unmarshalling - property [%s] not found in class [%s]",
               name, value.getClass().getName()));
           }      
        }
        
        // Now convert the field value to the correct target type
        Object fieldValue = null;
        try {
          fieldValue = w.convert(method != null ? method.getGenericParameterTypes()[0] : 
             field.getGenericType());
        }
        catch (ConversionException ex) {
          throw new RuntimeException("Could not convert value while unmarshaling", ex);
        }
  
        // If we have a setter method, invoke it
        if (method != null)
        {
           try
           {
              method.invoke(value, fieldValue);
           }
           catch (Exception e)
           {
              throw new RuntimeException(String.format(
                       "Could not invoke setter method [%s]", method.getName()));
           }
        }
        else
        {
           // Otherwise try to set the field value directly
           boolean accessible = field.isAccessible();
           try
           {
             if (!accessible)
               field.setAccessible(true);
             field.set(value, fieldValue);
           }
           catch (Exception ex)
           {
             throw new RuntimeException("Could not set field value.", ex);
           }
           finally
           {
             field.setAccessible(accessible);
           }
        }
      }
    }
  
    public Object convert(Type type)
        throws ConversionException
    {
      if (type instanceof Class && ((Class) type).isAssignableFrom(value.getClass()))
        return value;
      else
        throw new ConversionException(String.format(
          "Value [%s] cannot be converted to type [%s].", value, type));
    }
  
    public void marshal(OutputStream out)
      throws IOException
    {
      context.addOutRef(this);
  
      out.write(REF_START_TAG_OPEN);
      out.write(Integer.toString(context.getOutRefs().indexOf(this)).getBytes());
      out.write(REF_START_TAG_END);
    }
  
    @Override
    public void serialize(OutputStream out)
        throws IOException
    {
      serialize(out, null);
    }
  
    public void serialize(OutputStream out, List<String> constraints)
      throws IOException
    {
      out.write(BEAN_START_TAG_OPEN);
  
      Class cls = value.getClass();
  
      /** @todo This is a hack to get the "real" class - find out if there is
                an API method in CGLIB that can be used instead */
      if (cls.getName().contains("EnhancerByCGLIB"))
        cls = cls.getSuperclass();
  
      String componentName = Seam.getComponentName(cls);
  
      if (componentName != null)
        out.write(componentName.getBytes());
      else
        out.write(cls.getName().getBytes());
  
      out.write(BEAN_START_TAG_CLOSE);
  
      for (String propertyName : InterfaceGenerator.getAccessibleProperties(cls))
      {
        String fieldPath = path != null && path.length() > 0 ? String.format("%s.%s", path, propertyName) : propertyName;
  
        // Also exclude fields listed using wildcard notation: [componentName].fieldName
        String wildCard = String.format("[%s].%s", componentName != null ? componentName : cls.getName(), propertyName);
  
        if (constraints == null || (!constraints.contains(fieldPath) && !constraints.contains(wildCard)))
        {
          out.write(MEMBER_START_TAG_OPEN);
          out.write(propertyName.getBytes());
          out.write(MEMBER_START_TAG_CLOSE);
  
          Field f = null;
          try
          {
            f = cls.getField(propertyName);
          }
          catch (NoSuchFieldException ex) { }
  
          boolean accessible = false;
          try
          {
            // Temporarily set the field's accessibility so we can read it
            if (f != null)
            {
              accessible = f.isAccessible();
              f.setAccessible(true);
              context.createWrapperFromObject(f.get(value),
                  fieldPath).marshal(out);
            }
            else
            {
              Method accessor = null;
              try
              {
                accessor = cls.getMethod(String.format("get%s%s",
                    Character.toUpperCase(propertyName.charAt(0)),
                    propertyName.substring(1)));
              }
              catch (NoSuchMethodException ex)
              {
                try
                {
                  accessor = cls.getMethod(String.format("is%s%s",
                      Character.toUpperCase(propertyName.charAt(0)),
                      propertyName.substring(1)));
                }
                catch (NoSuchMethodException ex2)
                {
                  // uh oh... continue with the next one
                  continue;
                }
              }
  
              try
              {
                context.createWrapperFromObject(accessor.invoke(value), fieldPath).
                    marshal(out);
              }
              catch (InvocationTargetException ex)
              {
                throw new RuntimeException(String.format(
                    "Failed to read property [%s] for object [%s]",
                    propertyName, value));
              }
            }
          }
          catch (IllegalAccessException ex)
          {
            throw new RuntimeException("Error reading value from field.");
          }
          finally
          {
            if (f != null)
              f.setAccessible(accessible);
          }
  
          out.write(MEMBER_CLOSE_TAG);
        }
      }
  
      out.write(BEAN_CLOSE_TAG);
    }
  
    public ConversionScore conversionScore(Class cls) {
      if (cls.equals(value.getClass()))
        return ConversionScore.exact;
      else if (cls.isAssignableFrom(value.getClass()) || cls.equals(Object.class))
        return ConversionScore.compatible;
      else
        return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/BooleanWrapper.java
  
  Index: BooleanWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Type;
  
  /**
   * @author Shane Bryzak
   */
  public class BooleanWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] BOOL_TAG_OPEN = "<bool>".getBytes();
    private static final byte[] BOOL_TAG_CLOSE = "</bool>".getBytes();
  
    public void marshal(OutputStream out) throws IOException
    {
      out.write(BOOL_TAG_OPEN);
      out.write(((Boolean) value).toString().getBytes());
      out.write(BOOL_TAG_CLOSE);
    }
  
    public Object convert(Type type)
      throws ConversionException
    {
      if (type.equals(Boolean.class) || type.equals(Object.class))
        value = Boolean.valueOf(element.getStringValue());
      else if (type.equals(Boolean.TYPE))
        value = Boolean.parseBoolean(element.getStringValue());
      else
        throw new ConversionException(String.format(
          "Parameter [%s] cannot be converted to type [%s].",
          element.getStringValue(), type));
  
      return value;
    }
  
    public ConversionScore conversionScore(Class cls)
    {
      if (cls.equals(Boolean.class) || cls.equals(Boolean.TYPE))
        return ConversionScore.exact;
      else if (cls.equals(Object.class))
        return ConversionScore.compatible;
      else
        return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/ConversionException.java
  
  Index: ConversionException.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  /**
   * Thrown for an invalid conversion.
   * 
   * @author Shane Bryzak
   */
  public class ConversionException extends Exception
  {
     private static final long serialVersionUID = 5584559762846984501L;
  
     public ConversionException(String message)
     {
        super(message);
     }
  
     public ConversionException(String message, Throwable cause)
     {
        super(message, cause);
     }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/ConversionScore.java
  
  Index: ConversionScore.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  /**
   *
   * @author Shane Bryzak
   */
  public enum ConversionScore
  {
    nomatch(0),
    compatible(1),
    exact(2);
  
    private int score;
  
    ConversionScore(int score)
    {
      this.score = score;
    }
  
    public int getScore()
    {
      return score;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/DateWrapper.java
  
  Index: DateWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Type;
  import java.text.DateFormat;
  import java.text.ParseException;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  
  /**
   * Handles date conversions
   *
   * @author Shane Bryzak
   */
  public class DateWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] DATE_TAG_OPEN = "<date>".getBytes();
    private static final byte[] DATE_TAG_CLOSE = "</date>".getBytes();
    private static final DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
  
    public void marshal(OutputStream out) throws IOException
    {
      out.write(DATE_TAG_OPEN);
      out.write(df.format(value).getBytes());
      out.write(DATE_TAG_CLOSE);
    }
  
    public Object convert(Type type)
        throws ConversionException
    {
      if ((type instanceof Class && Date.class.isAssignableFrom((Class) type)) ||
          type.equals(Object.class))
      {
        try {
          value = df.parse(element.getStringValue());
        }
        catch (ParseException ex) {
          throw new ConversionException(String.format(
              "Date value [%s] is not in a valid format.", element.getStringValue()));
        }
      }
      else
        throw new ConversionException(String.format(
          "Value [%s] cannot be converted to type [%s].", element.getStringValue(),
          type));
  
      return value;
    }
  
    public ConversionScore conversionScore(Class cls)
    {
      if (Date.class.isAssignableFrom(cls))
        return ConversionScore.exact;
      else if (cls.equals(Object.class))
        return ConversionScore.compatible;
      else
        return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/MapWrapper.java
  
  Index: MapWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.ParameterizedType;
  import java.lang.reflect.Type;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.dom4j.Element;
  
  /**
   * @author Shane Bryzak
   */
  public class MapWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] MAP_TAG_OPEN = "<map>".getBytes();
    private static final byte[] MAP_TAG_CLOSE = "</map>".getBytes();
  
    private static final byte[] ELEMENT_TAG_OPEN = "<element>".getBytes();
    private static final byte[] ELEMENT_TAG_CLOSE = "</element>".getBytes();
  
    private static final byte[] KEY_TAG_OPEN = "<k>".getBytes();
    private static final byte[] KEY_TAG_CLOSE = "</k>".getBytes();
  
    private static final byte[] VALUE_TAG_OPEN = "<v>".getBytes();
    private static final byte[] VALUE_TAG_CLOSE = "</v>".getBytes();
  
    public void marshal(OutputStream out) throws IOException
    {
      out.write(MAP_TAG_OPEN);
  
      Map m = (Map) this.value;
  
      for (Object key : m.keySet())
      {
        out.write(ELEMENT_TAG_OPEN);
  
        out.write(KEY_TAG_OPEN);
        context.createWrapperFromObject(key, String.format("%s[key]", path)).marshal(out);
        out.write(KEY_TAG_CLOSE);
  
        out.write(VALUE_TAG_OPEN);
        context.createWrapperFromObject(m.get(key), String.format("%s[value]", path)).marshal(out);
        out.write(VALUE_TAG_CLOSE);
  
        out.write(ELEMENT_TAG_CLOSE);
      }
  
      out.write(MAP_TAG_CLOSE);
    }
  
    public Object convert(Type type)
        throws ConversionException
    {
      Class typeClass = null;
      Type keyType = null;
      Type valueType = null;
  
      // Either the type should be a generified Map
      if (type instanceof ParameterizedType &&
          Map.class.isAssignableFrom((Class) ((ParameterizedType) type).getRawType()))
      {
        typeClass = (Class) ((ParameterizedType) type).getRawType();
  
        for (Type t : ((ParameterizedType) type).getActualTypeArguments())
        {
          if (keyType == null)
            keyType = t;
          else
          {
            valueType = t;
            break;
          }
        }
      }
      // Or a non-generified Map
      else if (type instanceof Class && Map.class.isAssignableFrom((Class) type))
      {
        if (!((Class) type).isInterface())
          typeClass = (Class) type;
        keyType = Object.class;
        valueType = Object.class;
      }
      // If it's neither, throw an exception
      else
        throw new ConversionException(String.format(
          "Cannot convert value to type [%s]", type));
  
      // If we don't have a concrete type, default to creating a HashMap
      if (typeClass == null || typeClass.isInterface())
        value = new HashMap();
      else
      {
        try {
          // Otherwise create an instance of the concrete type
          value = ( (Class) type).newInstance();
        }
        catch (Exception ex) {
          throw new ConversionException(String.format(
              "Could not create value of type [%s]", type));
        }
      }
  
      for (Element e : (List<Element>) element.elements("element"))
      {
        Element keyElement = (Element) e.element("k").elementIterator().next();
        Element valueElement = (Element) e.element("v").elementIterator().next();
  
        ((Map) value).put(
          context.createWrapperFromElement(keyElement).convert(keyType),
          context.createWrapperFromElement(valueElement).convert(valueType));
      }
  
      return value;
    }
  
    public ConversionScore conversionScore(Class cls)
    {
      if (Map.class.isAssignableFrom(cls))
        return ConversionScore.exact;
  
      if (cls.equals(Object.class))
        return ConversionScore.compatible;
  
      return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/NullWrapper.java
  
  Index: NullWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Type;
  
  /**
   * @author Shane Bryzak
   */
  public class NullWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] NULL_WRAPPER_TAG = "<null/>".getBytes();
  
    public void marshal(OutputStream out) throws IOException
    {
      out.write(NULL_WRAPPER_TAG);
    }
  
    public Object convert(Type type)
        throws ConversionException
    {
      return null;
    }
  
    public ConversionScore conversionScore(Class cls)
    {
      return ConversionScore.compatible;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/NumberWrapper.java
  
  Index: NumberWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Type;
  
  /**
   * Int wrapper class.
   *
   * @author Shane Bryzak
   */
  public class NumberWrapper extends BaseWrapper implements Wrapper
  {
    private static final byte[] NUMBER_TAG_OPEN = "<number>".getBytes();
    private static final byte[] NUMBER_TAG_CLOSE = "</number>".getBytes();
  
    public Object convert(Type type)
        throws ConversionException
    {
      String val = element.getStringValue().trim();
  
      if (type.equals(Short.class))
        value = !"".equals(val) ? Short.valueOf(val) : null;
      else if (type.equals(Short.TYPE))
        value = Short.parseShort(val);
      else if (type.equals(Integer.class))
        value = !"".equals(val) ? Integer.valueOf(val) : null;
      else if (type.equals(Integer.TYPE))
        value = Integer.parseInt(val);
      else if (type.equals(Long.class) || type.equals(Object.class))
        value = !"".equals(val) ? Long.valueOf(val) : null;
      else if (type.equals(Long.TYPE))
        value = Long.parseLong(val);
      else if (type.equals(Float.class))
        value = !"".equals(val) ? Float.valueOf(val) : null;
      else if (type.equals(Float.TYPE))
        value = Float.parseFloat(val);
      else if (type.equals(Double.class))
        value = !"".equals(val) ? Double.valueOf(val) : null;
      else if (type.equals(Double.TYPE))
        value = Double.parseDouble(val);
      else if (type.equals(Byte.class))
        value = !"".equals(val) ? Byte.valueOf(val) : null;
      else if (type.equals(Byte.TYPE))
        value = Byte.parseByte(val);
  
      else if (type.equals(String.class))
        value = val;
      else
        throw new ConversionException(String.format(
          "Value [%s] cannot be converted to type [%s].", element.getStringValue(),
          type));
  
      return value;
    }
  
    /**
     *
     * @param out OutputStream
     * @throws IOException
     */
    public void marshal(OutputStream out)
      throws IOException
    {
      out.write(NUMBER_TAG_OPEN);
      out.write(value.toString().getBytes());
      out.write(NUMBER_TAG_CLOSE);
    }
  
    /**
     * Allow conversions to either Integer or String.
     *
     * @param cls Class
     * @return ConversionScore
     */
    public ConversionScore conversionScore(Class cls)
    {
      if (cls.equals(Integer.class) || cls.equals(Integer.TYPE))
        return ConversionScore.exact;
  
      if (cls.equals(String.class) || cls.equals(Object.class))
        return ConversionScore.compatible;
  
      return ConversionScore.nomatch;
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/StringWrapper.java
  
  Index: StringWrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.lang.reflect.Type;
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.net.URLDecoder;
  import java.net.URLEncoder;
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * String wrapper class.
   *
   * @author Shane Bryzak
   */
  public class StringWrapper extends BaseWrapper implements Wrapper
  {
    private interface StringConverter {
      Object convert(String value);
    }
  
    private static final Map<Class,StringConverter> converters = new HashMap<Class,StringConverter>();
  
    static {
      converters.put(String.class, new StringConverter() {
        public Object convert(String value) { return value; }
      });
      converters.put(Object.class, new StringConverter() {
        public Object convert(String value) { return value; }
      });
      converters.put(StringBuilder.class, new StringConverter() {
        public Object convert(String value) { return new StringBuilder(value); }
      });
      converters.put(StringBuffer.class, new StringConverter() {
        public Object convert(String value) { return new StringBuffer(value); }
      });
      converters.put(Integer.class, new StringConverter() {
        public Object convert(String value) { return Integer.valueOf(value); }
      });
      converters.put(Integer.TYPE, new StringConverter() {
        public Object convert(String value) { return Integer.parseInt(value); }
      });
      converters.put(Long.class, new StringConverter() {
        public Object convert(String value) { return Long.valueOf(value); }
      });
      converters.put(Long.TYPE, new StringConverter() {
        public Object convert(String value) { return Long.parseLong(value); }
      });
      converters.put(Short.class, new StringConverter() {
        public Object convert(String value) { return Short.valueOf(value); }
      });
      converters.put(Short.TYPE, new StringConverter() {
        public Object convert(String value) { return Short.parseShort(value); }
      });
      converters.put(Boolean.class, new StringConverter() {
        public Object convert(String value) { return Boolean.valueOf(value); }
      });
      converters.put(Boolean.TYPE, new StringConverter() {
        public Object convert(String value) { return Boolean.parseBoolean(value); }
      });
      converters.put(Double.class, new StringConverter() {
        public Object convert(String value) { return Double.valueOf(value); }
      });
      converters.put(Double.TYPE, new StringConverter() {
        public Object convert(String value) { return Double.parseDouble(value); }
      });
      converters.put(Float.class, new StringConverter() {
        public Object convert(String value) { return Float.valueOf(value); }
      });
      converters.put(Float.TYPE, new StringConverter() {
        public Object convert(String value) { return Float.parseFloat(value); }
      });
      converters.put(Character.class, new StringConverter() {
        public Object convert(String value) { return Character.valueOf(value.charAt(0)); }
      });
      converters.put(Character.TYPE, new StringConverter() {
        public Object convert(String value) { return value.charAt(0); }
      });
      converters.put(Byte.class, new StringConverter() {
        public Object convert(String value) { return Byte.valueOf(value); }
      });
      converters.put(Byte.TYPE, new StringConverter() {
        public Object convert(String value) { return Byte.parseByte(value); }
      });
      converters.put(BigInteger.class, new StringConverter() {
        public Object convert(String value) { return new BigInteger(value); }
      });
      converters.put(BigDecimal.class, new StringConverter() {
        public Object convert(String value) { return new BigDecimal(value); }
      });
    }
  
    public static final String DEFAULT_ENCODING = "UTF-8";
  
    private static final byte[] STRING_TAG_OPEN = "<str>".getBytes();
    private static final byte[] STRING_TAG_CLOSE = "</str>".getBytes();
  
    private static final Class[] COMPATIBLE_CLASSES = {
        Integer.class, Integer.TYPE, Long.class, Long.TYPE,
        Short.class, Short.TYPE, Boolean.class, Boolean.TYPE,
        Double.class, Double.TYPE, Float.class, Float.TYPE,
        Character.class, Character.TYPE, Byte.class, Byte.TYPE,
        BigInteger.class, BigDecimal.class, Object.class};
  
    public Object convert(Type type)
        throws ConversionException
    {
      String elementValue = null;
      try {
        elementValue = URLDecoder.decode(element.getStringValue(),
                                                DEFAULT_ENCODING);
      }
      catch (UnsupportedEncodingException ex) {
        throw new ConversionException("Error converting value - encoding not supported.");
      }
  
      try
      {
        if (converters.containsKey(type))
          value = converters.get(type).convert(elementValue);
        else if (type instanceof Class && ( (Class) type).isEnum())
          value = Enum.valueOf( (Class) type, elementValue);
        else
          // Should never reach this line - calcConverstionScore should guarantee this.
          throw new ConversionException(String.format(
              "Value [%s] cannot be converted to type [%s].", elementValue, type));
  
        return value;
      }
      catch (Exception ex)
      {
        if (ex instanceof ConversionException)
          throw (ConversionException) ex;
        else
          throw new ConversionException(String.format("Could not convert value [%s] to type [%s].",
                                      elementValue, type.toString()), ex);
      }
    }
  
    public ConversionScore conversionScore(Class cls)
    {
      if (cls.equals(String.class) ||
          StringBuffer.class.isAssignableFrom(cls))
        return ConversionScore.exact;
  
      for (Class c : COMPATIBLE_CLASSES)
      {
        if (cls.equals(c))
          return ConversionScore.compatible;
      }
  
      if (cls.isEnum()) {
        try
        {
          String elementValue = URLDecoder.decode(element.getStringValue(),
                                                    DEFAULT_ENCODING);
          Enum.valueOf(cls, elementValue);
          return ConversionScore.compatible;
        }
        catch (IllegalArgumentException ex) { }
        catch (UnsupportedEncodingException ex) { }
      }
  
      return ConversionScore.nomatch;
    }
  
    public void marshal(OutputStream out)
      throws IOException
    {
      out.write(STRING_TAG_OPEN);
      out.write(URLEncoder.encode(value.toString(), DEFAULT_ENCODING).replace("+", "%20").getBytes());
      out.write(STRING_TAG_CLOSE);
    }
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/Wrapper.java
  
  Index: Wrapper.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.reflect.Type;
  
  import org.dom4j.Element;
  import org.jboss.seam.remoting.CallContext;
  
  /**
   * Acts as a wrapper around parameter values passed within an AJAX call.
   *
   * @author Shane Bryzak
   */
  public interface Wrapper
  {
    /**
     * Sets the path of the wrapped object within the resulting object graph
     *
     * @param path String
     */
    public void setPath(String path);
  
    public void setCallContext(CallContext context);
  
    /**
     * Extracts a value from a DOM4J Element
     *
     * @param element Element
     */
    public void setElement(Element element);
  
    /**
     *
     * @param value Object
     */
    public void setValue(Object value);
  
    /**
     *
     * @return Object
     */
    public Object getValue();
  
    /**
     *
     */
    public void unmarshal();
  
    /**
     * Convert the wrapped parameter value to the specified target class.
     *
     */
    public Object convert(Type type) throws ConversionException;
  
    public void marshal(OutputStream out) throws IOException;
  
    public void serialize(OutputStream out) throws IOException;
  
    /**
     * Returns a score indicating whether this parameter value can be converted
     * to the specified type.  This helper method is used to determine which
     * (possibly overloaded) method of a component can/should be called.
     *
     * 0 - Cannot be converted
     * 1 - Can be converted to this type
     * 2 - Param is this exact type
     *
     */
    public ConversionScore conversionScore(Class cls);
  }
  
  
  
  1.1      date: 2007/02/27 22:15:24;  author: sbryzak2;  state: Exp;jboss-seam/src/remoting/org/jboss/seam/remoting/wrapper/WrapperFactory.java
  
  Index: WrapperFactory.java
  ===================================================================
  package org.jboss.seam.remoting.wrapper;
  
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   *
   * @author Shane Bryzak
   */
  public class WrapperFactory
  {
    /**
     * Singleton instance.
     */
    private static final WrapperFactory factory = new WrapperFactory();
  
    /**
     * A registry of wrapper types
     */
    private Map<String,Class> wrapperRegistry = new HashMap<String,Class>();
  
    private Map<Class,Class> classRegistry = new HashMap<Class,Class>();
  
    /**
     * Private constructor
     */
    private WrapperFactory()
    {
      // Register the defaults
      registerWrapper("str", StringWrapper.class);
      registerWrapper("bool", BooleanWrapper.class);
      registerWrapper("bean", BeanWrapper.class);
      registerWrapper("number", NumberWrapper.class);
      registerWrapper("null", NullWrapper.class);
      registerWrapper("bag", BagWrapper.class);
      registerWrapper("map", MapWrapper.class);
      registerWrapper("date", DateWrapper.class);
  
      // String types
      registerWrapperClass(String.class, StringWrapper.class);
      registerWrapperClass(StringBuilder.class, StringWrapper.class);
      registerWrapperClass(StringBuffer.class, StringWrapper.class);
      registerWrapperClass(Character.class, StringWrapper.class);
  
      // Big numbers are handled by StringWrapper
      registerWrapperClass(BigDecimal.class, StringWrapper.class);
      registerWrapperClass(BigInteger.class, StringWrapper.class);
  
      // Number types
      registerWrapperClass(Integer.class, NumberWrapper.class);
      registerWrapperClass(Long.class, NumberWrapper.class);
      registerWrapperClass(Short.class, NumberWrapper.class);
      registerWrapperClass(Double.class, NumberWrapper.class);
      registerWrapperClass(Float.class, NumberWrapper.class);
      registerWrapperClass(Byte.class, NumberWrapper.class);
    }
  
    public void registerWrapper(String type, Class wrapperClass)
    {
      wrapperRegistry.put(type, wrapperClass);
    }
  
    public void registerWrapperClass(Class cls, Class wrapperClass)
    {
      classRegistry.put(cls, wrapperClass);
    }
  
    public static WrapperFactory getInstance()
    {
      return factory;
    }
  
    public Wrapper createWrapper(String type)
    {
      Class wrapperClass = wrapperRegistry.get(type);
  
      if (wrapperClass != null)
      {
        try {
          Wrapper wrapper = (Wrapper) wrapperClass.newInstance();
          return wrapper;
        }
        catch (Exception ex) { }
      }
  
      throw new RuntimeException(String.format("Failed to create wrapper for type: %s",
                                 type));
    }
  
    public Wrapper getWrapperForObject(Object obj)
    {
      if (obj == null)
        return new NullWrapper();
  
      Wrapper w = null;
  
      if (Map.class.isAssignableFrom(obj.getClass()))
        w = new MapWrapper();
      else if (obj.getClass().isArray() || Collection.class.isAssignableFrom(obj.getClass()))
        w = new BagWrapper();
      else if (obj.getClass().equals(Boolean.class) || obj.getClass().equals(Boolean.TYPE))
        w = new BooleanWrapper();
      else if (obj.getClass().isEnum())
        w = new StringWrapper();
      else if (Date.class.isAssignableFrom(obj.getClass()))
        w = new DateWrapper();
      else if (classRegistry.containsKey(obj.getClass()))
      {
        try
        {
          w = (Wrapper) classRegistry.get(obj.getClass()).newInstance();
        }
        catch (Exception ex)
        {
          throw new RuntimeException("Failed to create wrapper instance.");
        }
      }
      else
        w = new BeanWrapper();
  
      w.setValue(obj);
      return w;
    }
  }
  
  
  



More information about the jboss-cvs-commits mailing list