Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.red5.io.amf.Output Maven / Gradle / Ivy
Go to download
A standalone RTMP client library ported from the Red5 project
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.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
//import java.util.Set;
import java.util.TimeZone;
//import net.sf.ehcache.Cache;
//import net.sf.ehcache.CacheException;
//import net.sf.ehcache.CacheManager;
//import net.sf.ehcache.Element;
//import org.apache.commons.beanutils.BeanMap;
import org.apache.mina.core.buffer.IoBuffer;
import org.red5.annotations.Anonymous;
import org.red5.io.amf3.ByteArray;
import org.red5.io.object.BaseOutput;
//import org.red5.io.object.ICustomSerializable;
import org.red5.io.object.RecordSet;
import org.red5.io.object.Serializer;
import org.red5.io.utils.XMLUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
/**
*
* @author The Red5 Project ([email protected] )
* @author Luke Hubbard, Codegent Ltd ([email protected] )
* @author Paul Gregoire ([email protected] )
* @author Harald Radi ([email protected] )
*/
public class Output extends BaseOutput implements org.red5.io.object.Output {
protected static Logger log = LoggerFactory.getLogger(Output.class);
/**
* Cache encoded strings... the TK way...
*/
// private static Cache stringCache;
//
// private static Cache serializeCache;
//
// private static Cache fieldCache;
//
// private static Cache getterCache;
//
// private static CacheManager cacheManager;
// private static CacheManager getCacheManager() {
// if (cacheManager == null) {
// if (System.getProperty("red5.root") != null) {
// // we're running Red5 as a server.
// try {
// cacheManager = new CacheManager(System.getProperty("red5.root") + File.separator + "conf"
// + File.separator + "ehcache.xml");
// } catch (CacheException e) {
// cacheManager = constructDefault();
// }
// } else {
// // not a server, maybe running tests?
// cacheManager = constructDefault();
// }
// }
//
// return cacheManager;
// }
// private static CacheManager constructDefault() {
// CacheManager manager = new CacheManager();
// if (!manager.cacheExists("org.red5.io.amf.Output.stringCache"))
// manager.addCache("org.red5.io.amf.Output.stringCache");
// if (!manager.cacheExists("org.red5.io.amf.Output.getterCache"))
// manager.addCache("org.red5.io.amf.Output.getterCache");
// if (!manager.cacheExists("org.red5.io.amf.Output.fieldCache"))
// manager.addCache("org.red5.io.amf.Output.fieldCache");
// if (!manager.cacheExists("org.red5.io.amf.Output.serializeCache"))
// manager.addCache("org.red5.io.amf.Output.serializeCache");
// return manager;
// }
/**
* Output buffer
*/
protected IoBuffer buf;
/**
* Creates output with given byte buffer
* @param buf Bute buffer
*/
public Output(IoBuffer buf) {
super();
this.buf = buf;
}
/** {@inheritDoc} */
public boolean isCustom(Object custom) {
return false;
}
protected boolean checkWriteReference(Object obj) {
if (hasReference(obj)) {
writeReference(obj);
return true;
} else
return false;
}
/** {@inheritDoc} */
public void writeArray(Collection> array, Serializer serializer) {
if (checkWriteReference(array)) {
return;
}
storeReference(array);
buf.put(AMF.TYPE_ARRAY);
buf.putInt(array.size());
for (Object item : array) {
serializer.serialize(this, item);
}
}
/** {@inheritDoc} */
public void writeArray(Object[] array, Serializer serializer) {
log.debug("writeArray - array: {} serializer: {}", array, serializer);
if (array != null) {
if (checkWriteReference(array)) {
return;
}
storeReference(array);
buf.put(AMF.TYPE_ARRAY);
buf.putInt(array.length);
for (Object item : array) {
serializer.serialize(this, item);
}
} else {
writeNull();
}
}
/** {@inheritDoc} */
public void writeArray(Object array, Serializer serializer) {
if (array != null) {
if (checkWriteReference(array)) {
return;
}
storeReference(array);
buf.put(AMF.TYPE_ARRAY);
buf.putInt(Array.getLength(array));
for (int i = 0; i < Array.getLength(array); i++) {
serializer.serialize(this, Array.get(array, i));
}
} else {
writeNull();
}
}
/** {@inheritDoc} */
public void writeMap(Map map, Serializer serializer) {
if (checkWriteReference(map)) {
return;
}
storeReference(map);
buf.put(AMF.TYPE_MIXED_ARRAY);
int maxInt = -1;
for (int i = 0; i < map.size(); i++) {
try {
if (!map.containsKey(i))
break;
} catch (ClassCastException err) {
// Map has non-number keys.
break;
}
maxInt = i;
}
buf.putInt(maxInt + 1);
for (Map.Entry entry : map.entrySet()) {
final String key = entry.getKey().toString();
if ("length".equals(key)) {
continue;
}
putString(key);
serializer.serialize(this, entry.getValue());
}
if (maxInt >= 0) {
putString("length");
serializer.serialize(this, maxInt + 1);
}
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
}
/** {@inheritDoc} */
public void writeMap(Collection> array, Serializer serializer) {
if (checkWriteReference(array)) {
return;
}
storeReference(array);
buf.put(AMF.TYPE_MIXED_ARRAY);
buf.putInt(array.size() + 1);
int idx = 0;
for (Object item : array) {
if (item != null) {
putString(String.valueOf(idx++));
serializer.serialize(this, item);
} else {
idx++;
}
}
putString("length");
serializer.serialize(this, array.size() + 1);
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
}
/** {@inheritDoc} */
public void writeRecordSet(RecordSet recordset, Serializer serializer) {
if (checkWriteReference(recordset)) {
return;
}
storeReference(recordset);
// Write out start of object marker
buf.put(AMF.TYPE_CLASS_OBJECT);
putString("RecordSet");
// Serialize
Map info = recordset.serialize();
// Write out serverInfo key
putString("serverInfo");
// Serialize
serializer.serialize(this, info);
// Write out end of object marker
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
}
/** {@inheritDoc} */
public boolean supportsDataType(byte type) {
return false;
}
/** {@inheritDoc} */
public void writeBoolean(Boolean bol) {
buf.put(AMF.TYPE_BOOLEAN);
buf.put(bol ? AMF.VALUE_TRUE : AMF.VALUE_FALSE);
}
/** {@inheritDoc} */
public void writeCustom(Object custom) {
}
/** {@inheritDoc} */
public void writeDate(Date date) {
buf.put(AMF.TYPE_DATE);
buf.putDouble(date.getTime());
buf.putShort((short) (TimeZone.getDefault().getRawOffset() / 60 / 1000));
}
/** {@inheritDoc} */
public void writeNull() {
// System.err.println("Write null");
buf.put(AMF.TYPE_NULL);
}
/** {@inheritDoc} */
public void writeNumber(Number num) {
buf.put(AMF.TYPE_NUMBER);
buf.putDouble(num.doubleValue());
}
/** {@inheritDoc} */
public void writeReference(Object obj) {
log.debug("Write reference");
buf.put(AMF.TYPE_REFERENCE);
buf.putShort(getReferenceId(obj));
}
/** {@inheritDoc} */
// @SuppressWarnings({ "rawtypes" })
public void writeObject(Object object, Serializer serializer) {
/*
if (checkWriteReference(object)) {
return;
}
storeReference(object);
// Create new map out of bean properties
BeanMap beanMap = new BeanMap(object);
// Set of bean attributes
Set set = beanMap.keySet();
if ((set.size() == 0) || (set.size() == 1 && beanMap.containsKey("class"))) {
// BeanMap is empty or can only access "class" attribute, skip it
writeArbitraryObject(object, serializer);
return;
}
// Write out either start of object marker for class name or "empty" start of object marker
Class> objectClass = object.getClass();
if (!objectClass.isAnnotationPresent(Anonymous.class)) {
buf.put(AMF.TYPE_CLASS_OBJECT);
putString(buf, serializer.getClassName(objectClass));
} else {
buf.put(AMF.TYPE_OBJECT);
}
if (object instanceof ICustomSerializable) {
((ICustomSerializable) object).serialize(this, serializer);
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
return;
}
// Iterate thru entries and write out property names with separators
for (Object key : set) {
String fieldName = key.toString();
log.debug("Field name: {} class: {}", fieldName, objectClass);
Field field = getField(objectClass, fieldName);
Method getter = getGetter(objectClass, beanMap, fieldName);
// Check if the Field corresponding to the getter/setter pair is transient
if (!serializeField(serializer, objectClass, fieldName, field, getter)) {
continue;
}
putString(buf, fieldName);
serializer.serialize(this, field, getter, object, beanMap.get(key));
}
// Write out end of object mark
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
*/
}
// @SuppressWarnings("unchecked")
protected boolean serializeField(Serializer serializer, Class> objectClass, String keyName, Field field,
Method getter) {
// to prevent, NullPointerExceptions, get the element first and check if it's null.
//Element element = getSerializeCache().get(objectClass);
//Map serializeMap = (element == null ? null : (Map) element.getObjectValue());
Map serializeMap = null ;
if (serializeMap == null) {
serializeMap = new HashMap();
//getSerializeCache().put(new Element(objectClass, serializeMap));
}
Boolean serialize;
// if (getSerializeCache().isKeyInCache(keyName)) {
// serialize = serializeMap.get(keyName);
// } else
{
serialize = serializer.serializeField(keyName, field, getter);
serializeMap.put(keyName, serialize);
}
return serialize;
}
// @SuppressWarnings("unchecked")
protected Field getField(Class> objectClass, String keyName) {
//again, to prevent null pointers, check if the element exists first.
// Element element = getFieldCache().get(objectClass);
// Map fieldMap = (element == null ? null : (Map) element.getObjectValue());
Map fieldMap = null;
if (fieldMap == null) {
fieldMap = new HashMap();
//getFieldCache().put(new Element(objectClass, fieldMap));
}
Field field = null;
if (fieldMap.containsKey(keyName)) {
field = fieldMap.get(keyName);
} else {
for (Class> clazz = objectClass; !clazz.equals(Object.class); clazz = clazz.getSuperclass()) {
Field[] fields = clazz.getDeclaredFields();
if (fields.length > 0) {
for (Field fld : fields) {
if (fld.getName().equals(keyName)) {
field = fld;
break;
}
}
}
}
fieldMap.put(keyName, field);
}
return field;
}
// @SuppressWarnings("unchecked")
// protected Method getGetter(Class> objectClass, BeanMap beanMap, String keyName) {
//check element to prevent null pointer
// Element element = getGetterCache().get(objectClass);
// Map getterMap = (element == null ? null : (Map) element.getObjectValue());
// if (getterMap == null) {
// getterMap = new HashMap();
// getGetterCache().put(new Element(objectClass, getterMap));
// }
//
// Method getter;
// if (getterMap.containsKey(keyName)) {
// getter = getterMap.get(keyName);
// } else {
// getter = beanMap.getReadMethod(keyName);
// getterMap.put(keyName, getter);
// }
// return getter;
// return null;
// }
/** {@inheritDoc} */
public void writeObject(Map map, Serializer serializer) {
if (checkWriteReference(map)) {
return;
}
storeReference(map);
buf.put(AMF.TYPE_OBJECT);
// boolean isBeanMap = (map instanceof BeanMap);
for (Map.Entry entry : map.entrySet()) {
//if (isBeanMap && "class".equals(entry.getKey())) {
if ("class".equals(entry.getKey())) {
continue;
}
putString(entry.getKey().toString());
serializer.serialize(this, entry.getValue());
}
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
}
/**
* Writes an arbitrary object to the output.
*
* @param serializer Output writer
* @param object Object to write
*/
protected void writeArbitraryObject(Object object, Serializer serializer) {
log.debug("writeObject");
// If we need to serialize class information...
Class> objectClass = object.getClass();
if (!objectClass.isAnnotationPresent(Anonymous.class)) {
// Write out start object marker for class name
buf.put(AMF.TYPE_CLASS_OBJECT);
putString(buf, serializer.getClassName(objectClass));
} else {
// Write out start object marker without class name
buf.put(AMF.TYPE_OBJECT);
}
// Iterate thru fields of an object to build "name-value" map from it
for (Field field : objectClass.getFields()) {
String fieldName = field.getName();
log.debug("Field: {} class: {}", field, objectClass);
// Check if the Field corresponding to the getter/setter pair is transient
if (!serializeField(serializer, objectClass, fieldName, field, null)) {
continue;
}
Object value;
try {
// Get field value
value = field.get(object);
} catch (IllegalAccessException err) {
// Swallow on private and protected properties access exception
continue;
}
// Write out prop name
putString(buf, fieldName);
// Write out
serializer.serialize(this, field, null, object, value);
}
// Write out end of object marker
buf.put((byte) 0x00);
buf.put((byte) 0x00);
buf.put(AMF.TYPE_END_OF_OBJECT);
}
/** {@inheritDoc} */
public void writeString(String string) {
final byte[] encoded = encodeString(string);
final int len = encoded.length;
if (len < AMF.LONG_STRING_LENGTH) {
buf.put(AMF.TYPE_STRING);
buf.putShort((short) len);
} else {
buf.put(AMF.TYPE_LONG_STRING);
buf.putInt(len);
}
buf.put(encoded);
}
/** {@inheritDoc} */
public void writeByteArray(ByteArray array) {
throw new RuntimeException("ByteArray objects not supported with AMF0");
}
/**
* Encode string.
*
* @param string
* @return encoded string
*/
protected static byte[] encodeString(String string) {
//Element element = getStringCache().get(string);
//byte[] encoded = (element == null ? null : (byte[]) element.getObjectValue());
byte[] encoded = null;
if (encoded == null) {
ByteBuffer buf = AMF.CHARSET.encode(string);
encoded = new byte[buf.limit()];
buf.get(encoded);
//getStringCache().put(new Element(string, encoded));
}
return encoded;
}
/**
* Write out string
* @param buf Byte buffer to write to
* @param string String to write
*/
public static void putString(IoBuffer buf, String string) {
final byte[] encoded = encodeString(string);
buf.putShort((short) encoded.length);
buf.put(encoded);
}
/** {@inheritDoc} */
public void putString(String string) {
putString(buf, string);
}
/** {@inheritDoc} */
public void writeXML(Document xml) {
buf.put(AMF.TYPE_XML);
putString(XMLUtils.docToString(xml));
}
/**
* Convenience method to allow XML text to be used, instead
* of requiring an XML Document.
*
* @param xml xml to write
*/
public void writeXML(String xml) {
buf.put(AMF.TYPE_XML);
putString(xml);
}
/**
* Return buffer of this Output object
* @return Byte buffer of this Output object
*/
public IoBuffer buf() {
return this.buf;
}
public void reset() {
clearReferences();
}
// protected static Cache getStringCache() {
// if (stringCache == null) {
// stringCache = getCacheManager().getCache("org.red5.io.amf.Output.stringCache");
// }
//
// return stringCache;
// }
//
// protected static Cache getSerializeCache() {
// if (serializeCache == null) {
// serializeCache = getCacheManager().getCache("org.red5.io.amf.Output.serializeCache");
// }
//
// return serializeCache;
// }
//
// protected static Cache getFieldCache() {
// if (fieldCache == null) {
// fieldCache = getCacheManager().getCache("org.red5.io.amf.Output.fieldCache");
// }
//
// return fieldCache;
// }
//
// protected static Cache getGetterCache() {
// if (getterCache == null) {
// getterCache = getCacheManager().getCache("org.red5.io.amf.Output.getterCache");
// }
//
// return getterCache;
// }
}