
org.red5.io.amf.Input Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-rmtp-client Show documentation
Show all versions of android-rmtp-client Show documentation
A standalone RTMP client library ported from the Red5 project
The newest version!
package org.red5.io.amf;
/*
* RED5 Open Source Flash Server - http://code.google.com/p/red5/
*
* Copyright (c) 2006-2010 by respective authors (see below). All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any later
* version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
//import org.apache.commons.beanutils.BeanUtils;
//import org.apache.commons.beanutils.BeanUtilsBean;
//import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.mina.core.buffer.IoBuffer;
import org.red5.io.amf3.ByteArray;
import org.red5.io.object.BaseInput;
import org.red5.io.object.DataTypes;
import org.red5.io.object.Deserializer;
import org.red5.io.object.RecordSet;
import org.red5.io.object.RecordSetPage;
import org.red5.io.utils.ArrayUtils;
import org.red5.io.utils.ObjectMap;
import org.red5.io.utils.XMLUtils;
import org.red5.server.service.ConversionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
/**
* Input for Red5 data types
*
* @author The Red5 Project ([email protected])
* @author Luke Hubbard, Codegent Ltd ([email protected])
*/
@SuppressWarnings("serial")
public class Input extends BaseInput implements org.red5.io.object.Input {
protected static Logger log = LoggerFactory.getLogger(Input.class);
protected static Map classAliases = new HashMap(3) {
{
put("DSA", "org.red5.compatibility.flex.messaging.messages.AsyncMessageExt");
put("DSC", "org.red5.compatibility.flex.messaging.messages.CommandMessageExt");
put("DSK", "org.red5.compatibility.flex.messaging.messages.AcknowledgeMessageExt");
}
};
protected IoBuffer buf;
protected byte currentDataType;
/**
* Creates Input object from byte buffer
*
* @param buf Byte buffer
*/
public Input(IoBuffer buf) {
super();
this.buf = buf;
}
/**
* Reads the data type.
*
* @return byte Data type
*/
public byte readDataType() {
if (buf != null) {
// XXX Paul: prevent an NPE here by returning the current data type
// when there is a null buffer
currentDataType = buf.get();
} else {
log.error("Why is buf null?");
}
return readDataType(currentDataType);
}
/**
* Reads the data type.
*
* @param dataType Data type as byte
* @return One of AMF class constants with type
* @see org.red5.io.amf.AMF
*/
protected byte readDataType(byte dataType) {
byte coreType;
switch (currentDataType) {
case AMF.TYPE_NULL:
case AMF.TYPE_UNDEFINED:
coreType = DataTypes.CORE_NULL;
break;
case AMF.TYPE_NUMBER:
coreType = DataTypes.CORE_NUMBER;
break;
case AMF.TYPE_BOOLEAN:
coreType = DataTypes.CORE_BOOLEAN;
break;
case AMF.TYPE_STRING:
case AMF.TYPE_LONG_STRING:
coreType = DataTypes.CORE_STRING;
break;
case AMF.TYPE_CLASS_OBJECT:
case AMF.TYPE_OBJECT:
coreType = DataTypes.CORE_OBJECT;
break;
case AMF.TYPE_MIXED_ARRAY:
coreType = DataTypes.CORE_MAP;
break;
case AMF.TYPE_ARRAY:
coreType = DataTypes.CORE_ARRAY;
break;
case AMF.TYPE_DATE:
coreType = DataTypes.CORE_DATE;
break;
case AMF.TYPE_XML:
coreType = DataTypes.CORE_XML;
break;
case AMF.TYPE_REFERENCE:
coreType = DataTypes.OPT_REFERENCE;
break;
case AMF.TYPE_UNSUPPORTED:
case AMF.TYPE_MOVIECLIP:
case AMF.TYPE_RECORDSET:
// These types are not handled by core datatypes
// So add the amf mask to them, this way the deserializer
// will call back to readCustom, we can then handle or return null
coreType = (byte) (currentDataType + DataTypes.CUSTOM_AMF_MASK);
break;
case AMF.TYPE_END_OF_OBJECT:
default:
// End of object, and anything else lets just skip
coreType = DataTypes.CORE_SKIP;
break;
}
return coreType;
}
// Basic
/**
* Reads a null.
*
* @return Object
*/
public Object readNull(Type target) {
return null;
}
/**
* Reads a boolean.
*
* @return boolean
*/
public Boolean readBoolean(Type target) {
// TODO: check values
return (buf.get() == AMF.VALUE_TRUE) ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Reads a Number. In ActionScript 1 and 2 Number type represents all numbers,
* both floats and integers.
*
* @return Number
*/
public Number readNumber(Type target) {
double num = buf.getDouble();
if (num == Math.round(num)) {
if (num < Integer.MAX_VALUE) {
return (int) num;
} else {
return Math.round(num);
}
} else {
return num;
}
}
/**
* Reads string from buffer
* @return String
*/
public String getString() {
return getString(buf);
}
/**
* Reads a string
*
* @return String
*/
public String readString(Type target) {
int len = 0;
switch (currentDataType) {
case AMF.TYPE_LONG_STRING:
len = buf.getInt();
break;
case AMF.TYPE_STRING:
len = buf.getUnsignedShort();
break;
default:
log.debug("Unknown AMF type: {}", currentDataType);
}
int limit = buf.limit();
// log.debug("Limit: {}", limit);
String string = bufferToString(buf.buf(), len);
buf.limit(limit); // Reset the limit
return string;
}
/**
* Returns a string based on the buffer
*
* @param buf Byte buffer with data
* @return String Decoded string
*/
public static String getString(IoBuffer buf) {
int len = buf.getUnsignedShort();
// log.debug("Length: {}", len);
int limit = buf.limit();
// log.debug("Limit: {}", limit);
String string = bufferToString(buf.buf(), len);
buf.limit(limit); // Reset the limit
return string;
}
/**
* Converts the bytes into a string.
*
* @param strBuf
* @return contents of the ByteBuffer as a String
*/
private final static String bufferToString(final java.nio.ByteBuffer strBuf, int len) {
//Trac #601 - part of the problem seems to be a null byte buffer
String string = null;
if (strBuf != null) {
int pos = strBuf.position();
// log.debug("String buf - position: {} limit: {}", pos, (pos + len));
strBuf.limit(pos + len);
string = AMF.CHARSET.decode(strBuf).toString();
// log.debug("String: {}", string);
} else {
log.warn("ByteBuffer was null attempting to read String");
}
return string;
}
/**
* Returns a date
*
* @return Date Decoded string object
*/
public Date readDate(Type target) {
/*
* Date: 0x0B T7 T6 .. T0 Z1 Z2 T7 to T0 form a 64 bit Big Endian number
* that specifies the number of nanoseconds that have passed since
* 1/1/1970 0:00 to the specified time. This format is UTC 1970. Z1 an
* Z0 for a 16 bit Big Endian number indicating the indicated time's
* timezone in minutes.
*/
long ms = (long) buf.getDouble();
// The timezone can be ignored as the date always is encoded in UTC
@SuppressWarnings("unused")
short timeZoneMins = buf.getShort();
Date date = new Date(ms);
storeReference(date);
return date;
}
// Array
public Object readArray(Deserializer deserializer, Type target) {
// log.debug("readArray - deserializer: {} target: {}", deserializer, target);
Object result = null;
int count = buf.getInt();
// log.debug("Count: {}", count);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy