Exemple #1
0
 // TODO need to fix
 public MetaData<?, ?> readMetaData(IoBuffer buffer) {
   MetaData<?, ?> retMeta = new MetaData<String, Object>();
   Input input = new Input(buffer);
   String metaType = Deserializer.deserialize(input, String.class);
   log.debug("Metadata type: {}", metaType);
   Map<String, ?> m = Deserializer.deserialize(input, Map.class);
   retMeta.putAll(m);
   return retMeta;
 }
 /**
  * Read remoting headers.
  *
  * @param in Input data as byte buffer
  * @return header map
  */
 @SuppressWarnings("unchecked")
 protected Map<String, Object> readHeaders(IoBuffer in) {
   int version = in.getUnsignedShort(); // skip the version
   int count = in.getUnsignedShort();
   log.debug("Read headers - version: {} count: {}", version, count);
   if (count == 0) {
     // No headers present
     return Collections.EMPTY_MAP;
   }
   Input input;
   if (version == 3) {
     input = new org.red5.io.amf3.Input(in);
   } else {
     input = new org.red5.io.amf.Input(in);
   }
   Map<String, Object> result = new HashMap<String, Object>();
   for (int i = 0; i < count; i++) {
     String name = input.getString();
     boolean required = in.get() == 0x01;
     int size = in.getInt();
     Object value = Deserializer.deserialize(input, Object.class);
     log.debug(
         "Header: {} Required: {} Size: {} Value: {}", new Object[] {name, required, size, value});
     result.put(name, value);
   }
   return result;
 }
Exemple #3
0
  /**
   * Creates recordset page from Input object
   *
   * @param input Input object to use as source for data that has to be deserialized
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public RecordSetPage(Input input) {
    Deserializer deserizalizer = new Deserializer();
    Map mapResult = deserizalizer.deserialize(input, Map.class);

    cursor = (Integer) mapResult.get("Cursor");
    data = (List<List<Object>>) mapResult.get("Page");
  }
  /**
   * Decode calls.
   *
   * @param in Input data as byte buffer
   * @return List of pending calls
   */
  protected List<RemotingCall> decodeCalls(IoBuffer in) {
    log.debug("Decode calls");
    // in.getInt();
    List<RemotingCall> calls = new LinkedList<RemotingCall>();
    org.red5.io.amf.Input input;
    int count = in.getUnsignedShort();
    log.debug("Calls: {}", count);
    int limit = in.limit();
    // Loop over all the body elements
    for (int i = 0; i < count; i++) {
      in.limit(limit);

      String serviceString = org.red5.io.amf.Input.getString(in);
      String clientCallback = org.red5.io.amf.Input.getString(in);
      log.debug("callback: {}", clientCallback);

      Object[] args = null;
      boolean isAMF3 = false;

      @SuppressWarnings("unused")
      int length = in.getInt();
      // Set the limit and deserialize
      // NOTE: disabled because the FP sends wrong values here
      /*
       * if (length != -1) in.limit(in.position()+length);
       */
      byte type = in.get();
      if (type == AMF.TYPE_ARRAY) {
        int elements = in.getInt();
        List<Object> values = new ArrayList<Object>();
        RefStorage refStorage = null;
        for (int j = 0; j < elements; j++) {
          byte amf3Check = in.get();
          in.position(in.position() - 1);
          isAMF3 = (amf3Check == AMF.TYPE_AMF3_OBJECT);
          if (isAMF3) {
            if (refStorage == null) {
              input = new org.red5.io.amf3.Input(in);
            } else {
              input = new org.red5.io.amf3.Input(in, refStorage);
            }
          } else {
            input = new org.red5.io.amf.Input(in);
          }
          // prepare remoting mode
          input.reset();
          // add deserialized object to the value list
          values.add(Deserializer.deserialize(input, Object.class));
          if (isAMF3) {
            refStorage = ((org.red5.io.amf3.Input) input).getRefStorage();
          }
        }
        args = values.toArray(new Object[values.size()]);
        if (log.isDebugEnabled()) {
          for (Object element : args) {
            log.debug("> " + element);
          }
        }

      } else if (type == AMF.TYPE_NULL) {
        log.debug("Got null amf type");

      } else if (type != AMF.TYPE_ARRAY) {
        throw new RuntimeException("AMF0 array type expected but found " + type);
      }

      String serviceName;
      String serviceMethod;
      int dotPos = serviceString.lastIndexOf('.');
      if (dotPos != -1) {
        serviceName = serviceString.substring(0, dotPos);
        serviceMethod = serviceString.substring(dotPos + 1, serviceString.length());
      } else {
        serviceName = "";
        serviceMethod = serviceString;
      }

      boolean isMessaging = false;
      if ("".equals(serviceName) && "null".equals(serviceMethod)) {
        // Use fixed service and method name for Flex messaging requests,
        // this probably will change in the future.
        serviceName = FlexMessagingService.SERVICE_NAME;
        serviceMethod = "handleRequest";
        isMessaging = true;
      }
      log.debug("Service: {} Method: {}", serviceName, serviceMethod);

      // Add the call to the list
      calls.add(
          new RemotingCall(serviceName, serviceMethod, args, clientCallback, isAMF3, isMessaging));
    }
    return calls;
  }
 @SuppressWarnings({"unchecked", "rawtypes", "serial"})
 public Object readObject(Deserializer deserializer, Type target) {
   int type = readAMF3Integer();
   log.debug("Type: {} and {} ref {}", new Object[] {type, (type & 1), (type >> 1)});
   if ((type & 1) == 0) {
     // Reference
     Object ref = getReference(type >> 1);
     if (ref != null) {
       return ref;
     }
     byte b = buf.get();
     if (b == 7) {
       log.debug("BEL: {}", b); // 7	
     } else {
       log.debug("Non-BEL byte: {}", b);
       log.debug("Extra byte: {}", buf.get());
     }
   }
   type >>= 1;
   List<String> attributes = null;
   String className;
   Object result = null;
   boolean inlineClass = (type & 1) == 1;
   log.debug("Class is in-line? {}", inlineClass);
   if (!inlineClass) {
     ClassReference info = refStorage.classReferences.get(type >> 1);
     className = info.className;
     attributes = info.attributeNames;
     type = info.type;
     if (attributes != null) {
       type |= attributes.size() << 2;
     }
   } else {
     type >>= 1;
     className = readString(String.class);
     log.debug("Type: {} classname: {}", type, className);
     // check for flex class alias since these wont be detected as externalizable
     if (classAliases.containsKey(className)) {
       // make sure type is externalizable
       type = 1;
     } else if (className.startsWith("flex")) {
       // set the attributes for messaging classes
       if (className.endsWith("CommandMessage")) {
         attributes =
             new LinkedList<String>() {
               {
                 add("timestamp");
                 add("headers");
                 add("operation");
                 add("body");
                 add("correlationId");
                 add("messageId");
                 add("timeToLive");
                 add("clientId");
                 add("destination");
               }
             };
       } else {
         log.debug("Attributes for {} were not set", className);
       }
     }
   }
   amf3_mode += 1;
   Object instance = newInstance(className);
   Map<String, Object> properties = null;
   PendingObject pending = new PendingObject();
   int tempRefId = storeReference(pending);
   log.debug("Object type: {}", (type & 0x03));
   switch (type & 0x03) {
     case AMF3.TYPE_OBJECT_PROPERTY:
       log.debug("Detected: Object property type");
       // Load object properties into map
       int count = type >> 2;
       log.debug("Count: {}", count);
       if (attributes == null) {
         attributes = new ArrayList<String>(count);
         for (int i = 0; i < count; i++) {
           attributes.add(readString(String.class));
         }
         refStorage.classReferences.add(
             new ClassReference(className, AMF3.TYPE_OBJECT_PROPERTY, attributes));
       }
       properties = new ObjectMap<String, Object>();
       for (int i = 0; i < count; i++) {
         String name = attributes.get(i);
         properties.put(name, deserializer.deserialize(this, getPropertyType(instance, name)));
       }
       break;
     case AMF3.TYPE_OBJECT_EXTERNALIZABLE:
       log.debug("Detected: Externalizable type");
       // Use custom class to deserialize the object
       if ("".equals(className)) {
         throw new RuntimeException("Classname is required to load an Externalizable object");
       }
       log.debug("Externalizable class: {}", className);
       if (className.length() == 3) {
         // check for special DS class aliases
         className = classAliases.get(className);
       }
       result = newInstance(className);
       if (result == null) {
         throw new RuntimeException(String.format("Could not instantiate class: %s", className));
       }
       if (!(result instanceof IExternalizable)) {
         throw new RuntimeException(
             String.format("Class must implement the IExternalizable interface: %s", className));
       }
       refStorage.classReferences.add(
           new ClassReference(className, AMF3.TYPE_OBJECT_EXTERNALIZABLE, null));
       storeReference(tempRefId, result);
       ((IExternalizable) result).readExternal(new DataInput(this, deserializer));
       break;
     case AMF3.TYPE_OBJECT_VALUE:
       log.debug("Detected: Object value type");
       // First, we should read typed (non-dynamic) properties ("sealed traits" according to AMF3
       // specification).
       // Property names are stored in the beginning, then values are stored.
       count = type >> 2;
       log.debug("Count: {}", count);
       if (attributes == null) {
         attributes = new ArrayList<String>(count);
         for (int i = 0; i < count; i++) {
           attributes.add(readString(String.class));
         }
         refStorage.classReferences.add(
             new ClassReference(className, AMF3.TYPE_OBJECT_VALUE, attributes));
       }
       // use the size of the attributes if we have no count
       if (count == 0 && attributes != null) {
         count = attributes.size();
         log.debug("Using class attribute size for property count: {}", count);
         // read the attributes from the stream and log if count doesnt match
         List<String> tmpAttributes = new ArrayList<String>(count);
         for (int i = 0; i < count; i++) {
           tmpAttributes.add(readString(String.class));
         }
         if (count != tmpAttributes.size()) {
           log.debug("Count and attributes length does not match!");
         }
         refStorage.classReferences.add(
             new ClassReference(className, AMF3.TYPE_OBJECT_VALUE, attributes));
       }
       properties = new ObjectMap<String, Object>();
       for (String key : attributes) {
         log.debug("Looking for property: {}", key);
         Object value = deserializer.deserialize(this, getPropertyType(instance, key));
         log.debug("Key: {} Value: {}", key, value);
         properties.put(key, value);
       }
       log.trace("Buffer - position: {} limit: {}", buf.position(), buf.limit());
       // no more items to read if we are at the end of the buffer
       if (buf.position() < buf.limit()) {
         // Now we should read dynamic properties which are stored as name-value pairs.
         // Dynamic properties are NOT remembered in 'classReferences'.
         String key = readString(String.class);
         while (!"".equals(key)) {
           Object value = deserializer.deserialize(this, getPropertyType(instance, key));
           properties.put(key, value);
           key = readString(String.class);
         }
       }
       break;
     default:
     case AMF3.TYPE_OBJECT_PROXY:
       log.debug("Detected: Object proxy type");
       if ("".equals(className)) {
         throw new RuntimeException("Classname is required to load an Externalizable object");
       }
       log.debug("Externalizable class: {}", className);
       result = newInstance(className);
       if (result == null) {
         throw new RuntimeException(String.format("Could not instantiate class: %s", className));
       }
       if (!(result instanceof IExternalizable)) {
         throw new RuntimeException(
             String.format("Class must implement the IExternalizable interface: %s", className));
       }
       refStorage.classReferences.add(new ClassReference(className, AMF3.TYPE_OBJECT_PROXY, null));
       storeReference(tempRefId, result);
       ((IExternalizable) result).readExternal(new DataInput(this, deserializer));
   }
   amf3_mode -= 1;
   if (result == null) {
     // Create result object based on classname
     if ("".equals(className)) {
       // "anonymous" object, load as Map
       // Resolve circular references
       for (Map.Entry<String, Object> entry : properties.entrySet()) {
         if (entry.getValue() == pending) {
           entry.setValue(properties);
         }
       }
       storeReference(tempRefId, properties);
       result = properties;
     } else if ("RecordSet".equals(className)) {
       // TODO: how are RecordSet objects encoded?
       throw new RuntimeException("Objects of type RecordSet not supported yet.");
     } else if ("RecordSetPage".equals(className)) {
       // TODO: how are RecordSetPage objects encoded?
       throw new RuntimeException("Objects of type RecordSetPage not supported yet.");
     } else {
       // Apply properties to object
       result = newInstance(className);
       if (result != null) {
         storeReference(tempRefId, result);
         Class resultClass = result.getClass();
         pending.resolveProperties(result);
         for (Map.Entry<String, Object> entry : properties.entrySet()) {
           // Resolve circular references
           final String key = entry.getKey();
           Object value = entry.getValue();
           if (value == pending) {
             value = result;
           }
           if (value instanceof PendingObject) {
             // Defer setting of value until real object is created
             ((PendingObject) value).addPendingProperty(result, resultClass, key);
             continue;
           }
           if (value != null) {
             try {
               final Field field = resultClass.getField(key);
               final Class fieldType = field.getType();
               if (!fieldType.isAssignableFrom(value.getClass())) {
                 value = ConversionUtils.convert(value, fieldType);
               } else if (value instanceof Enum) {
                 value = Enum.valueOf(fieldType, value.toString());
               }
               field.set(result, value);
             } catch (Exception e) {
               try {
                 BeanUtils.setProperty(result, key, value);
               } catch (IllegalAccessException ex) {
                 log.warn("Error mapping key: {} value: {}", key, value);
               } catch (InvocationTargetException ex) {
                 log.warn("Error mapping key: {} value: {}", key, value);
               }
             }
           } else {
             log.debug("Skipping null property: {}", key);
           }
         }
       } // else fall through
     }
   }
   return result;
 }
 /**
  * Returns an array
  *
  * @return int Length of array
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
 public Object readArray(Deserializer deserializer, Type target) {
   int count = readAMF3Integer();
   log.debug("Count: {} and {} ref {}", new Object[] {count, (count & 1), (count >> 1)});
   if ((count & 1) == 0) {
     // Reference
     Object ref = getReference(count >> 1);
     if (ref != null) {
       return ref;
     }
   }
   count = (count >> 1);
   String key = readString(String.class);
   amf3_mode += 1;
   Object result;
   if (key.equals("")) {
     Class<?> nested = Object.class;
     Class<?> collection = Collection.class;
     Collection resultCollection;
     if (target instanceof ParameterizedType) {
       ParameterizedType t = (ParameterizedType) target;
       Type[] actualTypeArguments = t.getActualTypeArguments();
       if (actualTypeArguments.length == 1) {
         nested = (Class<?>) actualTypeArguments[0];
       }
       target = t.getRawType();
     }
     if (target instanceof Class) {
       collection = (Class) target;
     }
     if (collection.isArray()) {
       nested = ArrayUtils.getGenericType(collection.getComponentType());
       result = Array.newInstance(nested, count);
       storeReference(result);
       for (int i = 0; i < count; i++) {
         final Object value = deserializer.deserialize(this, nested);
         Array.set(result, i, value);
       }
     } else {
       if (SortedSet.class.isAssignableFrom(collection)) {
         resultCollection = new TreeSet();
       } else if (Set.class.isAssignableFrom(collection)) {
         resultCollection = new HashSet(count);
       } else {
         resultCollection = new ArrayList(count);
       }
       result = resultCollection;
       storeReference(result);
       for (int i = 0; i < count; i++) {
         final Object value = deserializer.deserialize(this, nested);
         resultCollection.add(value);
       }
     }
   } else {
     Class<?> k = Object.class;
     Class<?> v = Object.class;
     Class<?> collection = Collection.class;
     if (target instanceof ParameterizedType) {
       ParameterizedType t = (ParameterizedType) target;
       Type[] actualTypeArguments = t.getActualTypeArguments();
       if (actualTypeArguments.length == 2) {
         k = (Class<?>) actualTypeArguments[0];
         v = (Class<?>) actualTypeArguments[1];
       }
       target = t.getRawType();
     }
     if (target instanceof Class) {
       collection = (Class) target;
     }
     if (SortedMap.class.isAssignableFrom(collection)) {
       collection = TreeMap.class;
     } else {
       collection = HashMap.class;
     }
     Map resultMap;
     try {
       resultMap = (Map) collection.newInstance();
     } catch (Exception e) {
       resultMap = new HashMap(count);
     }
     // associative array
     storeReference(resultMap);
     while (!key.equals("")) {
       final Object value = deserializer.deserialize(this, v);
       resultMap.put(key, value);
       key = readString(k);
     }
     for (int i = 0; i < count; i++) {
       final Object value = deserializer.deserialize(this, v);
       resultMap.put(i, value);
     }
     result = resultMap;
   }
   amf3_mode -= 1;
   return result;
 }