blob: 2cc5287727accec883512c5e53c0667bbcee4fa8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 flex.messaging.io.amf;
import flex.messaging.MessageException;
import flex.messaging.io.MessageDeserializer;
import flex.messaging.io.MessageIOConstants;
import flex.messaging.io.RecoverableSerializationException;
import flex.messaging.io.SerializationContext;
import java.io.IOException;
import java.io.InputStream;
public class AmfMessageDeserializer implements MessageDeserializer
{
public static final String CODE_VERSION_MISMATCH = "VersionMismatch";
private static final int UNSUPPORTED_AMF_VERSION = 10310;
protected ActionMessageInput amfIn;
protected AmfTrace debugTrace;
protected boolean isDebug;
public AmfMessageDeserializer()
{
}
public void initialize(SerializationContext context, InputStream in, AmfTrace trace)
{
amfIn = new Amf0Input(context);
amfIn.setInputStream(in);
debugTrace = trace;
isDebug = debugTrace != null;
amfIn.setDebugTrace(debugTrace);
}
public void readMessage(ActionMessage m, ActionContext context) throws ClassNotFoundException, IOException
{
if (isDebug)
debugTrace.startRequest("Deserializing AMF/HTTP request");
int version = amfIn.readUnsignedShort();
// Treat FMS's AMF1 as AMF0.
if (version == MessageIOConstants.AMF1)
version = MessageIOConstants.AMF0;
if (version != MessageIOConstants.AMF0 && version != MessageIOConstants.AMF3)
{
//Unsupported AMF version {version}.
MessageException ex = new MessageException();
ex.setMessage(UNSUPPORTED_AMF_VERSION, new Object[] {new Integer(version)});
ex.setCode(CODE_VERSION_MISMATCH);
throw ex;
}
m.setVersion(version);
context.setVersion(version);
if (isDebug)
debugTrace.version(version);
// Read headers
int headerCount = amfIn.readUnsignedShort();
for (int i = 0; i < headerCount; ++i)
{
MessageHeader header = new MessageHeader();
m.addHeader(header);
readHeader(header, i);
}
// Read bodies
int bodyCount = amfIn.readUnsignedShort();
for (int i = 0; i < bodyCount; ++i)
{
MessageBody body = new MessageBody();
m.addBody(body);
readBody(body, i);
}
}
/**
* Deserialize a message header from the input stream.
* A message header is structured as:
* NAME kString
* MUST UNDERSTAND kBoolean
* LENGTH kInt
* DATA kObject
*
* @param header - will hold the deserialized message header
* @param index header index for debugging
* @throws IOException thrown by the underlying stream
* @throws ClassNotFoundException if we don't find the class for the header data.
*/
public void readHeader(MessageHeader header, int index) throws ClassNotFoundException, IOException
{
String name = amfIn.readUTF();
header.setName(name);
boolean mustUnderstand = amfIn.readBoolean();
header.setMustUnderstand(mustUnderstand);
amfIn.readInt(); // Length
amfIn.reset();
Object data;
if (isDebug)
debugTrace.startHeader(name, mustUnderstand, index);
try
{
data = readObject();
}
catch (RecoverableSerializationException ex)
{
ex.setCode("Client.Header.Encoding");
data = ex;
}
catch (MessageException ex)
{
ex.setCode("Client.Header.Encoding");
throw ex;
}
header.setData(data);
if (isDebug)
debugTrace.endHeader();
}
/**
* Deserialize a message body from the input stream.
*
* @param body - will hold the deserialized message body
* @param index message index for debugging
* @throws IOException thrown by the underlying stream
* @throws ClassNotFoundException if we don't find the class for the body data.
*/
public void readBody(MessageBody body, int index) throws ClassNotFoundException, IOException
{
String targetURI = amfIn.readUTF();
body.setTargetURI(targetURI);
String responseURI = amfIn.readUTF();
body.setResponseURI(responseURI);
amfIn.readInt(); // Length
amfIn.reset();
Object data;
if (isDebug)
debugTrace.startMessage(targetURI, responseURI, index);
try
{
data = readObject();
}
catch (RecoverableSerializationException ex)
{
ex.setCode("Client.Message.Encoding");
data = ex;
}
catch (MessageException ex)
{
ex.setCode("Client.Message.Encoding");
throw ex;
}
body.setData(data);
if (isDebug)
debugTrace.endMessage();
}
/**
* Read Object.
* @return Object the object read from AmfInput
* @throws ClassNotFoundException, IOException when exceptions occurs in reading the object
*/
public Object readObject() throws ClassNotFoundException, IOException
{
return amfIn.readObject();
}
}