Package org.jboss.errai.bus.server.io

Source Code of org.jboss.errai.bus.server.io.TypeDemarshallHelper

/*
* Copyright 2010 JBoss, a divison Red Hat, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.errai.bus.server.io;

import org.jboss.errai.common.client.protocols.SerializationParts;
import org.jboss.errai.common.client.types.DecodingContext;
import org.jboss.errai.common.client.types.UHashMap;
import org.jboss.errai.common.client.types.UnsatisfiedForwardLookup;
import org.mvel2.ConversionHandler;
import org.mvel2.MVEL;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static org.mvel2.DataConversion.addConversionHandler;

public class TypeDemarshallHelper {
  static {
    addConversionHandler(java.sql.Date.class, new ConversionHandler() {
      public Object convertFrom(Object o) {
        if (o instanceof String) o = Long.parseLong((String) o);

        return new java.sql.Date(((Number) o).longValue());
      }

      public boolean canConvertFrom(Class aClass) {
        return Number.class.isAssignableFrom(aClass);
      }
    });

    addConversionHandler(java.util.Date.class, new ConversionHandler() {
      public Object convertFrom(Object o) {
        if (o instanceof String) o = Long.parseLong((String) o);
        return new java.util.Date(((Number) o).longValue());
      }

      public boolean canConvertFrom(Class aClass) {
        return Number.class.isAssignableFrom(aClass);
      }
    });
  }

  private static final Map<Class, Map<String, Serializable>> MVELDencodingCache = new ConcurrentHashMap<Class, Map<String, Serializable>>();


  public static Object demarshallAll(Object o, DecodingContext ctx) throws Exception {
    try {
      if (o instanceof String) {
        return o;

      }
      else if (o instanceof Collection) {
        ArrayList newList = new ArrayList(((Collection) o).size());
        Object dep;
        for (Object o2 : ((Collection) o)) {
          if ((dep = demarshallAll(o2, ctx)) instanceof UnsatisfiedForwardLookup) {
            ctx.addUnsatisfiedDependency(o, (UnsatisfiedForwardLookup) dep);
          }
          else {
            newList.add(dep);
          }
        }

        if (ctx.hasUnsatisfiedDependency(o)) {
          ctx.swapDepReference(o, newList);
        }

        return newList;
      }
      else if (o instanceof Map) {
        Map<?, ?> oMap = (Map) o;
        if (oMap.containsKey(SerializationParts.ENCODED_TYPE)) {
          String objId = (String) oMap.get(SerializationParts.OBJECT_ID);
          boolean ref = false;
          if (objId != null) {
            if (objId.charAt(0) == '$') {
              ref = true;
              objId = objId.substring(1);
            }

            if (ctx.hasObject(objId)) {
              return ctx.getObject(objId);
            }
            else if (ref) {
              return new UnsatisfiedForwardLookup(objId);
            }
          }

          Class clazz = Thread.currentThread().getContextClassLoader().loadClass((String) oMap.get(SerializationParts.ENCODED_TYPE));
          if (clazz.isEnum()) {
            return Enum.valueOf(clazz, (String) oMap.get("EnumStringValue"));
          }
          else if (java.util.Date.class.isAssignableFrom(clazz)) {
            return new java.util.Date((Long) oMap.get("Value"));
          }
          else if (java.sql.Date.class.isAssignableFrom(clazz)) {
            return new java.sql.Date((Long) oMap.get("Value"));
          }

          Object newInstance = clazz.newInstance();
          if (objId != null) ctx.putObject(objId, newInstance);

          if (ctx.hasUnsatisfiedDependency(o)) {
            ctx.swapDepReference(o, newInstance);
          }

          Map<String, Serializable> s = MVELDencodingCache.get(clazz);

          if (s == null) {
            synchronized (MVELDencodingCache) {
              s = MVELDencodingCache.get(newInstance.getClass());
              if (s == null) {
                s = new UHashMap<String, Serializable>();
                for (String key : (Set<String>) oMap.keySet()) {
                  if (SerializationParts.ENCODED_TYPE.equals(key) || SerializationParts.OBJECT_ID.equals(key))
                    continue;
                  s.put(key, compileSetExpression(key));
                }
              }
              MVELDencodingCache.put(newInstance.getClass(), s);
            }
          }

          Object v;
          for (Map.Entry<?, ?> entry : oMap.entrySet()) {
            if (SerializationParts.ENCODED_TYPE.equals(entry.getKey()) || SerializationParts.OBJECT_ID.equals(entry.getKey()))
              continue;
            final Serializable cachedSetExpr = s.get(entry.getKey());
            if (cachedSetExpr != null) {
              try {
                if ((v = demarshallAll(entry.getValue(), ctx)) instanceof UnsatisfiedForwardLookup) {
                  ((UnsatisfiedForwardLookup) v).setPath((String) entry.getKey());
                  ctx.addUnsatisfiedDependency(newInstance, (UnsatisfiedForwardLookup) v);
                }
                else {
                  MVEL.executeSetExpression(cachedSetExpr, newInstance, v);
                }
              }
              catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
              }
            }
            else {
              try {
                if ((v = demarshallAll(entry.getValue(), ctx)) instanceof UnsatisfiedForwardLookup) {
                  ((UnsatisfiedForwardLookup) v).setPath((String) entry.getKey());
                  ctx.addUnsatisfiedDependency(newInstance, (UnsatisfiedForwardLookup) v);
                }
                else {
                  setProperty(newInstance, String.valueOf(entry.getKey()), v);
                }
              }
              catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
              }
            }
          }


          return newInstance;
        }
      }
      return o;
    }
    catch (Exception e) {
      throw new RuntimeException("error demarshalling encoded object:\n" + o, e);
    }
  }

  @SuppressWarnings({"unchecked"})
  public static void resolveDependencies(DecodingContext ctx) {
    for (Map.Entry<Object, List<UnsatisfiedForwardLookup>> entry : ctx.getUnsatisfiedDependencies().entrySet()) {
      Iterator<UnsatisfiedForwardLookup> iter = entry.getValue().iterator();

      if (entry.getKey() instanceof Collection) {
        while (iter.hasNext()) {
          ((Collection<Object>) entry.getKey()).add(ctx.getObject(iter.next().getId()));
        }
      }
      else if (entry.getKey() instanceof Map && !((Map) entry.getKey()).containsKey(SerializationParts.ENCODED_TYPE)) {
        UnsatisfiedForwardLookup u1 = iter.next();
        if (!iter.hasNext()) {
          if (u1.getKey() != null) {
            if (u1.getKey() instanceof UnsatisfiedForwardLookup) {
              ((Map<Object, Object>) entry.getKey()).put(ctx.getObject(((UnsatisfiedForwardLookup) u1.getKey()).getId()), ctx.getObject(u1.getId()));
            }
            else {
              ((Map<Object, Object>) entry.getKey()).put(u1.getKey(), ctx.getObject(u1.getId()));
            }
          }
          else if (u1.getVal() != null) {
            ((Map<Object, Object>) entry.getKey()).put(ctx.getObject(u1.getId()), u1.getVal());
          }
          else {
            throw new RuntimeException("error resolving dependencies in payload (Map Element): " + u1.getId());
          }
        }
        else {
          UnsatisfiedForwardLookup u2 = iter.next();
          ((Map<Object, Object>) entry.getKey()).put(ctx.getObject(u1.getId()), ctx.getObject(u2.getId()));
        }

      }
      else {
        UnsatisfiedForwardLookup ufl;
        while (iter.hasNext()) {
          if ((ufl = iter.next()).getPath() == null) {
            throw new RuntimeException("cannot satisfy dependency in object graph (path unresolvable):" + ufl.getId());
          }
          else {
            setProperty(entry.getKey(), ufl.getPath(), ctx.getObject(ufl.getId()));

          }

        }
      }

      if (entry.getKey() instanceof UHashMap)
        ((UHashMap) entry.getKey()).normalHashMode();
    }
  }


  public static Serializable compileSetExpression(String s) {
    return MVEL.compileSetExpression(ensureSafe(s));
  }

  public static void setProperty(Object i, String s, Object v) {
    MVEL.setProperty(i, ensureSafe(s), v);
  }

  public static String ensureSafe(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (!Character.isJavaIdentifierPart(s.charAt(i))) {
        throw new RuntimeException("illegal character in property");
      }
    }
    return s;
  }
}
TOP

Related Classes of org.jboss.errai.bus.server.io.TypeDemarshallHelper

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.