[Red5commits] [1660] merged changes from branch "joachim_amf3_integration" back in trunk
jbauch
luke at codegent.com
Thu Jan 25 16:40:21 EST 2007
merged changes from branch "joachim_amf3_integration" back in trunk
Timestamp: 01/25/07 16:02:18 EST (less than one hour ago)
Change: 1660
Author: jbauch
Files (see diff or trac for details):
doc/trunk/changelog.txt
java/server/trunk/.classpath
java/server/trunk/build.xml
java/server/trunk/src/org/red5/io/amf/Input.java
java/server/trunk/src/org/red5/io/amf/Output.java
java/server/trunk/src/org/red5/io/amf3/AMF3.java
java/server/trunk/src/org/red5/io/amf3/Input.java
java/server/trunk/src/org/red5/io/amf3/Output.java
java/server/trunk/src/org/red5/io/flv/impl/FLVReader.java
java/server/trunk/src/org/red5/io/mock/Input.java
java/server/trunk/src/org/red5/io/mock/Output.java
java/server/trunk/src/org/red5/io/mp3/impl/MP3Reader.java
java/server/trunk/src/org/red5/io/object/BaseInput.java
java/server/trunk/src/org/red5/io/object/BaseOutput.java
java/server/trunk/src/org/red5/io/object/Deserializer.java
java/server/trunk/src/org/red5/io/object/Input.java
java/server/trunk/src/org/red5/io/object/Output.java
java/server/trunk/src/org/red5/io/object/RecordSet.java
java/server/trunk/src/org/red5/io/object/Serializer.java
java/server/trunk/src/org/red5/io/utils/ObjectMap.java
java/server/trunk/src/org/red5/server/JettyLoader.java
java/server/trunk/src/org/red5/server/net/remoting/RemotingClient.java
java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventEncoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/SharedObjectSerializer.java
java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java
java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java
java/server/trunk/src/org/red5/server/so/FlexSharedObjectMessage.java
java/server/trunk/swf/DEV_Source/classes/org/red5/samples/echo
java/server/trunk/swf/DEV_Source/classes/org/red5/samples/echo/EchoClass.as
java/server/trunk/swf/DEV_Source/echotest.mxml
java/server/trunk/webapps/echo
java/server/trunk/webapps/echo/WEB-INF
java/server/trunk/webapps/echo/WEB-INF/log4j.properties
java/server/trunk/webapps/echo/WEB-INF/red5-web.properties
java/server/trunk/webapps/echo/WEB-INF/red5-web.xml
java/server/trunk/webapps/echo/WEB-INF/src
java/server/trunk/webapps/echo/WEB-INF/src/org
java/server/trunk/webapps/echo/WEB-INF/src/org/red5
java/server/trunk/webapps/echo/WEB-INF/src/org/red5/server
java/server/trunk/webapps/echo/WEB-INF/src/org/red5/server/webapp
java/server/trunk/webapps/echo/WEB-INF/src/org/red5/server/webapp/echo
java/server/trunk/webapps/echo/WEB-INF/src/org/red5/server/webapp/echo/Application.java
java/server/trunk/webapps/echo/WEB-INF/web.xml
Trac: http://mirror1.cvsdude.com/trac/osflash/red5/changeset/1660
Index: /java/server/trunk/src/org/red5/server/so/FlexSharedObjectMessage.java
===================================================================
--- /java/server/trunk/src/org/red5/server/so/FlexSharedObjectMessage.java (revision 1660)
+++ /java/server/trunk/src/org/red5/server/so/FlexSharedObjectMessage.java (revision 1660)
@@ -0,0 +1,39 @@
+package org.red5.server.so;
+
+import org.red5.server.api.event.IEventListener;
+
+public class FlexSharedObjectMessage extends SharedObjectMessage {
+
+ /**
+ * Creates Flex2 Shared Object event with given name, version and persistence flag
+ *
+ * @param name Event name
+ * @param version SO version
+ * @param persistent SO persistence flag
+ */
+ public FlexSharedObjectMessage(String name, int version, boolean persistent) {
+ this(null, name, version, persistent);
+ }
+
+ /**
+ * Creates Flex2 Shared Object event with given listener, name, SO version and persistence flag
+ *
+ * @param source Event listener
+ * @param name Event name
+ * @param version SO version
+ * @param persistent SO persistence flag
+ */
+ public FlexSharedObjectMessage(IEventListener source, String name, int version,
+ boolean persistent) {
+ super(source, name, version, persistent);
+
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public byte getDataType() {
+ return TYPE_FLEX_SHARED_OBJECT;
+ }
+
+
+}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java (revision 1606)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java (revision 1660)
@@ -10,7 +10,7 @@
}
- @Override
+ /** {@inheritDoc} */
+ @Override
public byte getDataType() {
- // TODO Auto-generated method stub
return TYPE_FLEX_MESSAGE;
}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java (revision 1628)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java (revision 1660)
@@ -69,6 +69,11 @@
public static final byte TYPE_VIDEO_DATA = 0x09;
- // Unknown: 0x0A ... 0x10
-
+ // Unknown: 0x0A ... 0x0F
+
+ /**
+ * AMF3 shared object
+ */
+ public static final byte TYPE_FLEX_SHARED_OBJECT = 0x10;
+
/**
* AMF3 message
Index: /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java (revision 1654)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java (revision 1660)
@@ -163,4 +163,5 @@
((IEventDispatcher) stream).dispatchEvent(message);
break;
+ case TYPE_FLEX_SHARED_OBJECT:
case TYPE_SHARED_OBJECT:
onSharedObject(conn, channel, header,
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java (revision 1631)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java (revision 1660)
@@ -60,4 +60,12 @@
/**
+ * Decodes shared object message event from AMF3 encoding
+ * @param in Byte buffer to decode
+ * @param rtmp RTMP protocol state
+ * @return ISharedObjectMessage event
+ */
+ public abstract ISharedObjectMessage decodeFlexSharedObject(ByteBuffer in, RTMP rtmp);
+
+ /**
* Decodes notification event
* @param in Byte buffer to decode
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java (revision 1654)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java (revision 1660)
@@ -79,17 +79,4 @@
private Serializer serializer;
- /**
- * Creates output object from byte buffer
- * @param buffer
- * @return
- */
- private Output getOutput(RTMP rtmp, ByteBuffer buffer) {
- if (rtmp.getEncoding() == Encoding.AMF3) {
- return new org.red5.io.amf3.Output(buffer);
- } else {
- return new org.red5.io.amf.Output(buffer);
- }
- }
-
/** {@inheritDoc} */
public ByteBuffer encode(ProtocolState state, Object message)
@@ -259,4 +246,6 @@
case TYPE_VIDEO_DATA:
return encodeVideoData((VideoData) message);
+ case TYPE_FLEX_SHARED_OBJECT:
+ return encodeFlexSharedObject((ISharedObjectMessage) message, rtmp);
case TYPE_SHARED_OBJECT:
return encodeSharedObject((ISharedObjectMessage) message, rtmp);
@@ -268,4 +257,5 @@
return encodeFlexMessage((FlexMessage) message, rtmp);
default:
+ log.warn("Unknown object type: " + header.getDataType());
return null;
}
@@ -303,9 +293,29 @@
/** {@inheritDoc} */
- public ByteBuffer encodeSharedObject(ISharedObjectMessage so, RTMP rtmp) {
-
+ public ByteBuffer encodeFlexSharedObject(ISharedObjectMessage so, RTMP rtmp) {
final ByteBuffer out = ByteBuffer.allocate(128);
out.setAutoExpand(true);
- final Output output = getOutput(rtmp, out);
+ out.put((byte) 0x00);
+ doEncodeSharedObject(so, rtmp, out);
+ return out;
+ }
+
+ /** {@inheritDoc} */
+ public ByteBuffer encodeSharedObject(ISharedObjectMessage so, RTMP rtmp) {
+ final ByteBuffer out = ByteBuffer.allocate(128);
+ out.setAutoExpand(true);
+ doEncodeSharedObject(so, rtmp, out);
+ return out;
+ }
+
+ /**
+ * Perform the actual encoding of the shared object contents.
+ *
+ * @param so
+ * @param rtmp
+ * @param out
+ */
+ public void doEncodeSharedObject(ISharedObjectMessage so, RTMP rtmp, ByteBuffer out) {
+ final Output output = new org.red5.io.amf.Output(out);
output.putString(so.getName());
@@ -418,5 +428,4 @@
}
}
- return out;
}
@@ -478,5 +487,9 @@
output = new org.red5.io.amf.Output(out);
} else {
- output = getOutput(rtmp, out);
+ if (rtmp.getEncoding() == Encoding.AMF3) {
+ output = new org.red5.io.amf3.Output(out);
+ } else {
+ output = new org.red5.io.amf.Output(out);
+ }
}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventEncoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventEncoder.java (revision 1631)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventEncoder.java (revision 1660)
@@ -101,3 +101,11 @@
public abstract ByteBuffer encodeSharedObject(ISharedObjectMessage so, RTMP rtmp);
+ /**
+ * Encodes SharedObjectMessage event to byte buffer using AMF3 encoding
+ * @param so ISharedObjectMessage event
+ * @param rtmp RTMP protocol state
+ * @return Byte buffer
+ */
+ public ByteBuffer encodeFlexSharedObject(ISharedObjectMessage so, RTMP rtmp);
+
}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 1654)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 1660)
@@ -56,4 +56,5 @@
import org.red5.server.service.Call;
import org.red5.server.service.PendingCall;
+import org.red5.server.so.FlexSharedObjectMessage;
import org.red5.server.so.ISharedObjectEvent;
import org.red5.server.so.ISharedObjectMessage;
@@ -87,19 +88,4 @@
public RTMPProtocolDecoder() {
- }
-
- /**
- * Return input (data values provider) object from byte buffer.
- *
- * @param rtmp RTMP protocol state
- * @param buffer Byte buffer
- * @return Input object
- */
- private Input getInput(RTMP rtmp, ByteBuffer buffer) {
- if (rtmp.getEncoding() == Encoding.AMF3) {
- return new org.red5.io.amf3.Input(buffer);
- } else {
- return new org.red5.io.amf.Input(buffer);
- }
}
@@ -438,4 +424,7 @@
message = decodeVideoData(in);
break;
+ case TYPE_FLEX_SHARED_OBJECT:
+ message = decodeFlexSharedObject(in, rtmp);
+ break;
case TYPE_SHARED_OBJECT:
message = decodeSharedObject(in, rtmp);
@@ -451,4 +440,5 @@
break;
default:
+ log.warn("Unknown object type: " + header.getDataType());
message = decodeUnknown(header.getDataType(), in);
break;
@@ -488,7 +478,8 @@
/** {@inheritDoc} */
- public ISharedObjectMessage decodeSharedObject(ByteBuffer in, RTMP rtmp) {
-
- final Input input = getInput(rtmp, in);
+ public ISharedObjectMessage decodeFlexSharedObject(ByteBuffer in, RTMP rtmp) {
+ // Unknown byte, always 0?
+ in.skip(1);
+ final Input input = new org.red5.io.amf.Input(in);
String name = input.getString();
// Read version of SO to modify
@@ -499,7 +490,35 @@
in.skip(4);
- final SharedObjectMessage so = new SharedObjectMessage(null, name,
+ final SharedObjectMessage so = new FlexSharedObjectMessage(null, name,
version, persistent);
-
+ doDecodeSharedObject(so, in, input);
+ return so;
+ }
+
+ /** {@inheritDoc} */
+ public ISharedObjectMessage decodeSharedObject(ByteBuffer in, RTMP rtmp) {
+ final Input input = new org.red5.io.amf.Input(in);
+ String name = input.getString();
+ // Read version of SO to modify
+ int version = in.getInt();
+ // Read persistence informations
+ boolean persistent = in.getInt() == 2;
+ // Skip unknown bytes
+ in.skip(4);
+
+ final SharedObjectMessage so = new FlexSharedObjectMessage(null, name,
+ version, persistent);
+ doDecodeSharedObject(so, in, input);
+ return so;
+ }
+
+ /**
+ * Perform the actual decoding of the shared object contents.
+ *
+ * @param so
+ * @param in
+ * @param rtmp
+ */
+ protected void doDecodeSharedObject(SharedObjectMessage so, ByteBuffer in, Input input) {
// Parse request body
while (in.hasRemaining()) {
@@ -554,5 +573,4 @@
so.addEvent(type, key, value);
}
- return so;
}
@@ -598,5 +616,9 @@
// TODO: we should use different code depending on server or client mode
int start = in.position();
- Input input = getInput(rtmp, in);
+ Input input;
+ if (rtmp.getEncoding() == Encoding.AMF3)
+ input = new org.red5.io.amf3.Input(in);
+ else
+ input = new org.red5.io.amf.Input(in);
String action = (String) deserializer.deserialize(input);
Index: /va/server/trunk/src/org/red5/server/net/rtmp/codec/SharedObjectSerializer.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/SharedObjectSerializer.java (revision 1406)
+++ (revision )
@@ -1,77 +1,0 @@
-package org.red5.server.net.rtmp.codec;
-
-/*
- * RED5 Open Source Flash Server - http://www.osflash.org/red5
- *
- * Copyright (c) 2006 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.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections.BeanMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.red5.io.object.Output;
-import org.red5.io.object.Serializer;
-
-/**
- * Data serializer for shared objects.
- *
- * @author The Red5 Project (red5 at osflash.org)
- * @author Joachim Bauch (jojo at struktur.de)
- */
-public class SharedObjectSerializer extends Serializer {
-
- // Initialize Logging
- protected static Log log = LogFactory.getLog(SharedObjectSerializer.class
- .getName());
-
- /**
- * Writes a map to the output.
- *
- * @param out
- * output stream
- * @param map
- * Map object to serialize
- */
- @Override
- public void writeMap(Output out, Map map) {
- if (log.isDebugEnabled()) {
- log.debug("writeMap");
- }
-
- final Set set = map.entrySet();
- // NOTE: we need to encode maps as objects for shared objects
- out.writeStartObject(null);
- Iterator it = set.iterator();
- boolean isBeanMap = (map instanceof BeanMap);
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- if (isBeanMap && ((String) entry.getKey()).equals("class")) {
- continue;
- }
- out.writeItemKey(entry.getKey().toString());
- serialize(out, entry.getValue());
- if (it.hasNext()) {
- out.markPropertySeparator();
- }
- }
- out.markEndObject();
- }
-
-}
Index: /java/server/trunk/src/org/red5/server/net/remoting/RemotingClient.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/remoting/RemotingClient.java (revision 1654)
+++ /java/server/trunk/src/org/red5/server/net/remoting/RemotingClient.java (revision 1660)
@@ -149,10 +149,5 @@
tmp.setAutoExpand(true);
Output tmpOut = new Output(tmp);
- Serializer serializer = new Serializer();
- tmpOut.writeStartArray(params.length);
- for (Object param : params) {
- serializer.serialize(tmpOut, param);
- }
- tmpOut.markEndArray();
+ tmpOut.writeArray(params, new Serializer());
tmp.flip();
Index: /java/server/trunk/src/org/red5/server/JettyLoader.java
===================================================================
--- /java/server/trunk/src/org/red5/server/JettyLoader.java (revision 1654)
+++ /java/server/trunk/src/org/red5/server/JettyLoader.java (revision 1660)
@@ -20,6 +20,4 @@
*/
-import java.io.IOException;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -34,4 +32,6 @@
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.io.IOException;
/**
Index: /java/server/trunk/src/org/red5/io/amf3/Input.java
===================================================================
--- /java/server/trunk/src/org/red5/io/amf3/Input.java (revision 1654)
+++ /java/server/trunk/src/org/red5/io/amf3/Input.java (revision 1660)
@@ -21,9 +21,11 @@
import java.io.IOException;
-import java.util.Calendar;
+import java.util.ArrayList;
import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -31,4 +33,8 @@
import org.red5.io.amf.AMF;
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.ObjectMap;
/**
@@ -44,4 +50,12 @@
*/
protected static Log log = LogFactory.getLog(Input.class.getName());
+ /**
+ * Set to a value above <tt>0</tt> to enforce AMF3 decoding mode.
+ */
+ private int amf3_mode;
+ /**
+ * List of string values found in the input stream.
+ */
+ private List<String> stringReferences;
/**
@@ -52,4 +66,6 @@
public Input(ByteBuffer buf) {
super(buf);
+ amf3_mode = 0;
+ stringReferences = new ArrayList<String>();
}
@@ -71,5 +87,5 @@
if (currentDataType == AMF.TYPE_AMF3_OBJECT) {
currentDataType = buf.get();
- } else {
+ } else if (amf3_mode == 0) {
// AMF0 object
return readDataType(currentDataType);
@@ -168,10 +184,11 @@
public String readString() {
int len = readAMF3Integer();
- if (len == 0)
+ if (len == 1)
+ // Empty string
return "";
if ((len & 1) == 0) {
// Reference
- return (String) getReference(len >> 1);
+ return stringReferences.get(len >> 1);
}
len >>= 1;
@@ -181,5 +198,5 @@
final String string = AMF3.CHARSET.decode(strBuf).toString();
buf.limit(limit); // Reset the limit
- storeReference(string);
+ stringReferences.add(string);
return string;
}
@@ -192,20 +209,13 @@
@Override
public Date readDate() {
- /*
- * 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.
- */
+ int ref = readAMF3Integer();
+ if ((ref & 1) == 0) {
+ // Reference to previously found date
+ return (Date) getReference(ref >> 1);
+ }
+
long ms = (long) buf.getDouble();
- short clientTimeZoneMins = buf.getShort();
- ms += clientTimeZoneMins * 60 * 1000;
- Calendar cal = new GregorianCalendar();
- cal.setTime(new Date(ms - TimeZone.getDefault().getRawOffset()));
- Date date = cal.getTime();
- if (cal.getTimeZone().inDaylightTime(date)) {
- date.setTime(date.getTime() - cal.getTimeZone().getDSTSavings());
- }
+ Date date = new Date(ms);
+ storeReference(date);
return date;
}
@@ -218,137 +228,125 @@
* @return int Length of array
*/
- @Override
- public int readStartArray() {
- System.err.println("MISSING: readStartArray");
- return buf.getInt();
- }
-
- /**
- * Skips elements TODO
- */
- @Override
- public void skipElementSeparator() {
- // SKIP
- }
-
- /**
- * Skips end array TODO
- */
- @Override
- public void skipEndArray() {
- // SKIP
- }
-
+ public Object readArray(Deserializer deserializer) {
+ int count = readAMF3Integer();
+ if ((count & 1) == 0) {
+ // Reference
+ return getReference(count >> 1);
+ }
+
+ count = (count >> 1);
+ String key = readString();
+ amf3_mode += 1;
+ Object result = null;
+ if (key.equals("")) {
+ // normal array
+ List<Object> resultList = new ArrayList<Object>(count);
+ storeReference(resultList);
+ for (int i=0; i<count; i++) {
+ final Object value = deserializer.deserialize(this);
+ resultList.add(value);
+ }
+ result = resultList;
+ } else {
+ // associative array
+ Map<Object, Object> resultMap = new HashMap<Object, Object>();
+ storeReference(resultMap);
+ while (!key.equals("")) {
+ final Object value = deserializer.deserialize(this);
+ resultMap.put(key, value);
+ key = readString();
+ }
+ for (int i=0; i<count; i++) {
+ final Object value = deserializer.deserialize(this);
+ resultMap.put(i, value);
+ }
+ result = resultMap;
+ }
+ amf3_mode -= 1;
+ return result;
+ }
+
+ public Object readMap(Deserializer deserializer) {
+ throw new RuntimeException("AMF3 doesn't support maps.");
+ }
+
// Object
- /**
- * Reads start list
- *
- * @return int Size of map
- */
- @Override
- public int readStartMap() {
- System.err.println("MISSING: readStartMap");
- return buf.getInt();
- }
-
- /**
- * Returns a boolean stating whether this has more items
- *
- * @return boolean <code>true</code> if this Input's buffer has more items, <code>false</code> otherwise
- */
- @Override
- public boolean hasMoreItems() {
- return hasMoreProperties();
- }
-
- /**
- * Reads the item index
- *
- * @return int Array item index
- */
- @Override
- public String readItemKey() {
- return readString();
- }
-
- /**
- * Skips item seperator
- */
- @Override
- public void skipItemSeparator() {
- // SKIP
- }
-
- /**
- * Skips end list
- */
- @Override
- public void skipEndMap() {
- skipEndObject();
- }
-
- // Object
-
- /**
- * Reads start object
- *
- * @return String
- */
- @Override
- public String readStartObject() {
- System.err.println("MISSING: readStartObject");
- return null;
- }
-
- /**
- * Returns a boolean stating whether there are more properties
- *
- * @return boolean <code>true</code> if there are more properties to read, <code>false</code> otherwise
- */
- @Override
- public boolean hasMoreProperties() {
- boolean isEnd = (buf.get() == 0);
- buf.position(buf.position()-1);
- return isEnd;
- }
-
- /**
- * Reads property name
- *
- * @return String Object property name
- */
- @Override
- public String readPropertyName() {
- return readString();
- }
-
- /**
- * Skips property seperator
- */
- @Override
- public void skipPropertySeparator() {
- // SKIP
- }
-
- /**
- * Skips end object
- */
- @Override
- public void skipEndObject() {
- buf.skip(1);
- }
-
+ public Object readObject(Deserializer deserializer) {
+ int type = readAMF3Integer();
+ if ((type & 1) == 0) {
+ // Reference
+ return getReference(type >> 1);
+ }
+
+ type >>= 1;
+ boolean inlineClass = (type & 1) == 1;
+ if (!inlineClass) {
+ throw new RuntimeException("Class references not supported yet.");
+ }
+
+ type >>= 1;
+ String className = readString();
+ Object result = null;
+ amf3_mode += 1;
+ // Load object properties into map
+ Map<String, Object> properties = new ObjectMap<String, Object>();
+ switch (type & 0x03) {
+ case AMF3.TYPE_OBJECT_PROPERTY:
+ int count = type >> 2;
+ List<String> propertyNames = new ArrayList<String>(count);
+ for (int i=0; i<count; i++) {
+ propertyNames.add(readString());
+ }
+ for (int i=0; i<count; i++) {
+ properties.put(propertyNames.get(i), deserializer.deserialize(this));
+ }
+ break;
+ case AMF3.TYPE_OBJECT_ANONYMOUS_PROPERTY:
+ properties.put("", deserializer.deserialize(this));
+ break;
+ case AMF3.TYPE_OBJECT_VALUE:
+ String key = readString();
+ while (!"".equals(key)) {
+ Object value = deserializer.deserialize(this);
+ properties.put(key, value);
+ key = readString();
+ }
+ break;
+ default:
+ case AMF3.TYPE_OBJECT_UNKNOWN:
+ throw new RuntimeException("Unknown object type: " + (type & 0x03));
+ }
+ amf3_mode -= 1;
+
+ // Create result object based on classname
+ if ("".equals(className)) {
+ // "anonymous" object, load as Map
+ storeReference(properties);
+ result = properties;
+ } else if ("RecordSet".equals(className)) {
+ // TODO: how are RecordSet objects encoded?
+ throw new RuntimeException("Objects of type " + className + " not supported yet.");
+ } else if ("RecordSetPage".equals(className)) {
+ // TODO: how are RecordSetPage objects encoded?
+ throw new RuntimeException("Objects of type " + className + " not supported yet.");
+ } else {
+ // Apply properties to object
+ result = newInstance(className);
+ if (result != null) {
+ storeReference(properties);
+ for (Map.Entry<String, Object> entry: properties.entrySet()) {
+ try {
+ BeanUtils.setProperty(result, entry.getKey(), entry.getValue());
+ } catch (Exception e) {
+ log.error("Error mapping property: " + entry.getKey() + " (" + entry.getValue() + ")");
+ }
+ }
+ } // else fall through
+ }
+ return result;
+ }
+
// Others
-
- /**
- * Reads xml
- *
- * @return String XML as String
- */
- @Override
- public String readXML() {
- return readString();
- }
/**
@@ -363,4 +361,9 @@
}
+ /** {@inheritDoc} */
+ public Object readReference() {
+ throw new RuntimeException("AMF3 doesn't support direct references.");
+ }
+
/**
* Resets map
@@ -368,5 +371,6 @@
@Override
public void reset() {
- this.clearReferences();
+ super.reset();
+ stringReferences.cle
Note:
Diffs are chopped if more than 25k.
This is to get past the limit on the mailing list.
More information about the Red5commits
mailing list