/*--- formatted by Jindent 2.1, (www.c-lab.de/~jindent) ---*/ /* * *************************************************************** * The LEAP libraries, when combined with certain JADE platform components, * provide a run-time environment for enabling FIPA agents to execute on * lightweight devices running Java. LEAP and JADE teams have jointly * designed the API for ease of integration and hence to take advantage * of these dual developments and extensions so that users only see * one development platform and a * single homogeneous set of APIs. Enabling deployment to a wide range of * devices whilst still having access to the full development * environment and functionalities that JADE provides. * Copyright (C) 2001 Siemens AG. * * GNU Lesser General Public License * * 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, * version 2.1 of the License. * * 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. * ************************************************************** */ package jade.imtp.leap; import java.io.DataInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Date; import java.util.Vector; import jade.core.*; import jade.core.messaging.GenericMessage; import jade.lang.acl.ACLMessage; import jade.lang.acl.LEAPACLCodec; import jade.domain.FIPAAgentManagement.Envelope; import jade.domain.FIPAAgentManagement.Property; import jade.domain.FIPAAgentManagement.ReceivedObject; import jade.util.leap.Properties; import jade.util.leap.ArrayList; import jade.mtp.MTPDescriptor; import jade.security.*; import jade.imtp.leap.JICP.JICPAddress; import jade.imtp.leap.JICP.JICPProtocol; import jade.imtp.leap.http.HTTPAddress; import jade.imtp.leap.http.HTTPProtocol; /** * This class implements a data input stream deserializing * Deliverables from a given byte array according to the LEAP surrogate * serialization mechanism. In order to function correctly, the byte array * must contain serialized Deliverables, primitive types or J2SE class types, * that are considered (by this stream class) as primitive types. * * @author Michael Watzke * @author Giovanni Caire * @author Nicolas Lhuillier * @author Jerome Picault */ class DeliverableDataInputStream extends DataInputStream { private StubHelper myStubHelper; /** * Constructs a data input stream that is deserializing Deliverables from the * given byte array according to the LEAP surrogate serialization mechanism. * @param serialized_byte_array the byte array this data input stream * deserializes Deliverables from */ public DeliverableDataInputStream(byte[] serialized_byte_array, StubHelper sh) { super(new ByteArrayInputStream(serialized_byte_array)); myStubHelper = sh; } /** * Reads an object whose class is not known from the context from * this data input stream. * @return the object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization or the object is an instance of a class that cannot be * deserialized. */ public Object readObject() throws LEAPSerializationException { String className = null; // This is defined here as it is used also inside the catch blocks try { boolean presenceFlag = readBoolean(); if (presenceFlag) { byte id = readByte(); switch (id) { // Directly handle deserialization of classes that must be // deserialized more frequently case Serializer.HORIZONTALCOMMAND_ID: return deserializeHorizontalCommand(); case Serializer.ACL_ID: return deserializeACL(); case Serializer.AID_ID: return deserializeAID(); case Serializer.AIDARRAY_ID: return deserializeAIDArray(); case Serializer.GENERICMESSAGE_ID: return deserializeGenericMessage(); case Serializer.STRING_ID: return readUTF(); case Serializer.CONTAINERID_ID: return deserializeContainerID(); case Serializer.CONTAINERIDARRAY_ID: return deserializeContainerIDArray(); case Serializer.BOOLEAN_ID: return new Boolean(readBoolean()); case Serializer.INTEGER_ID: return new Integer(readInt()); case Serializer.DATE_ID: return deserializeDate(); case Serializer.STRINGARRAY_ID: return deserializeStringArray(); case Serializer.VECTOR_ID: return deserializeVector(); case Serializer.MTPDESCRIPTOR_ID: return deserializeMTPDescriptor(); case Serializer.NODEDESCRIPTOR_ID: return deserializeNodeDescriptor(); case Serializer.NODE_ID: return deserializeNode(); case Serializer.PLATFORMMANAGER_ID: return deserializePlatformManager(); case Serializer.NODEARRAY_ID: return deserializeNodeArray(); case Serializer.ENVELOPE_ID: return deserializeEnvelope(); case Serializer.ARRAYLIST_ID: return deserializeArrayList(); case Serializer.BYTEARRAY_ID: return deserializeByteArray(); case Serializer.PROPERTIES_ID: return deserializeProperties(); case Serializer.RECEIVEDOBJECT_ID: return deserializeReceivedObject(); case Serializer.SERVICEDESCRIPTOR_ID: return deserializeServiceDescriptor(); case Serializer.SLICEPROXY_ID: return deserializeSliceProxy(); //#DOTNET_EXCLUDE_BEGIN case Serializer.SERVICESLICEPROXY_ID: return deserializeServiceSliceProxy(); //#DOTNET_EXCLUDE_END case Serializer.JICPADDRESS_ID: return deserializeJICPAddress(); case Serializer.HTTPADDRESS_ID: return deserializeHTTPAddress(); case Serializer.THROWABLE_ID: return deserializeThrowable(); case Serializer.PROPERTY_ID: return deserializeProperty(); //#MIDP_EXCLUDE_BEGIN case Serializer.SERIALIZABLE_ID: byte[] bytes = deserializeByteArray(); ByteArrayInputStream inp = new ByteArrayInputStream(bytes); java.io.ObjectInputStream decoder = new java.io.ObjectInputStream(inp); Object obj = decoder.readObject(); return obj; //#MIDP_EXCLUDE_END case Serializer.DEFAULT_ID: String serName = readUTF(); Serializer s = (Serializer) Class.forName(serName).newInstance(); Object o = s.deserialize(this); return o; default: throw new LEAPSerializationException("Unknown class ID: "+id); } } // END of if (presenceFlag) else { return null; } } // END of try catch (IOException e) { throw new LEAPSerializationException("I/O Error Deserializing a generic object"); } catch(LEAPSerializationException leapse) { throw leapse; // Let this one through } catch (Exception e) { throw new LEAPSerializationException("Error creating (de)Serializer: "+e); } } /** * Reads an object of type String from this data input stream. * @return the String object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ public String readString() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return readUTF(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing String"); } } /** * Reads an object of type Date from this data input stream. * @return the Date object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ public Date readDate() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeDate(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing Date"); } } /** * Reads an object of type StringBuffer from this data input stream. * @return the StringBuffer object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ public StringBuffer readStringBuffer() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeStringBuffer(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing StringBuffer"); } } /** * Reads an object of type Vector from this data input stream. * @return the Vector object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ public Vector readVector() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeVector(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing Vector"); } } /** * Reads an array of String from this data input stream. * @return the array of String that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ public String[] readStringArray() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeStringArray(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing String[]"); } } /** * Reads an object of type Long from this data input stream. * @return the Long object that has been read. * @exception LEAPSerializationException if an error occurs during * deserialization. */ /* * public Long readLongObject() throws LEAPSerializationException { * try { * boolean presenceFlag = readBoolean(); * * if (presenceFlag) { * return new Long(readLong()); * } * else { * return null; * } * } * catch (IOException e) { * throw new LEAPSerializationException("Error deserializing Long"); * } * } */ // PRIVATE METHODS // All the following methods are used to actually deserialize instances of // Java classes from this input stream. They are only used internally when // the context ensures that the Java object to be serialized is not null! /** */ public Date deserializeDate() throws IOException { return new Date(readLong()); } /** */ public StringBuffer deserializeStringBuffer() throws IOException { return new StringBuffer(readUTF()); } /** */ public Vector deserializeVector() throws IOException, LEAPSerializationException { int size = readInt(); Vector v = new Vector(size); for (int i = 0; i < size; i++) { v.addElement(readObject()); } return v; } /** */ public String[] deserializeStringArray() throws IOException, LEAPSerializationException { String[] sa = new String[readInt()]; for (int i = 0; i < sa.length; i++) { sa[i] = readString(); } return sa; } private HorizontalCommand deserializeHorizontalCommand() throws LEAPSerializationException { try { // Read the mandatory command name and command service String name = readUTF(); String service = readUTF(); // Read the optional command interaction String interaction = readString(); // Create the command and add all the read parameters to it GenericCommand result = new GenericCommand(name, service, interaction); int sz = readInt(); for(int i = 0; i < sz; i++) { result.addParam(readObject()); } return result; } catch(IOException ioe) { throw new LEAPSerializationException("Error deserializing horizontal command"); } } /** * Note that when delivering messages to agents we never deal with ACLMessage objects * since they are ALWAYS encoded/decoded by the Messaging filters. However there may * be services that use ACLMessage objects as parameters in their HCommands */ private ACLMessage deserializeACL() throws IOException, LEAPSerializationException { ACLMessage msg = LEAPACLCodec.deserializeACL(this); //#CUSTOM_EXCLUDE_BEGIN if (readBoolean()) { Envelope env = deserializeEnvelope(); msg.setEnvelope(env); } //#CUSTOM_EXCLUDE_END return msg; } /** */ public AID readAID() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeAID(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing AID"); } } /** * Package scoped as it may be called by external serializers */ AID deserializeAID() throws IOException, LEAPSerializationException { return LEAPACLCodec.deserializeAID(this); } public AID[] deserializeAIDArray() throws IOException, LEAPSerializationException { AID[] aida = new AID[readInt()]; for (int i = 0; i < aida.length; i++) { aida[i] = readAID(); } return aida; } private GenericMessage deserializeGenericMessage() throws IOException, LEAPSerializationException { byte[] payload = deserializeByteArray(); Envelope env = (Envelope) readObject(); GenericMessage gm = new GenericMessage(env, payload); gm.setAMSFailure(readBoolean()); gm.setTraceID((String) readObject()); return gm; } /** * Package scoped as it is called by the CommandDispatcher */ Command deserializeCommand() throws LEAPSerializationException { try { Command cmd = new Command(readInt(), readInt()); int paramCnt = readInt(); for (int i = 0; i < paramCnt; ++i) { cmd.addParam(readObject()); } return cmd; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing Command"); } } /** */ private ContainerID deserializeContainerID() throws LEAPSerializationException { try { ContainerID cid = new ContainerID(); cid.setName(readUTF()); cid.setAddress(readUTF()); return cid; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing ContainerID"); } } public ContainerID readContainerID() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeContainerID(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing AID"); } } public ContainerID[] deserializeContainerIDArray() throws IOException, LEAPSerializationException { ContainerID[] cida = new ContainerID[readInt()]; for (int i = 0; i < cida.length; i++) { cida[i] = readContainerID(); } return cida; } /** */ private MTPDescriptor deserializeMTPDescriptor() throws LEAPSerializationException { try { String name = readUTF(); String className = readUTF(); String[] addresses = readStringArray(); String[] protoNames = readStringArray(); return new MTPDescriptor(name, className, addresses, protoNames); } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing MTPDescriptor"); } } private ServiceDescriptor deserializeServiceDescriptor() throws LEAPSerializationException { String name = null; String className = null; try { name = readUTF(); className = readUTF(); Service svc = (Service) Class.forName(className).newInstance(); return new ServiceDescriptor(name, svc); } catch (ClassNotFoundException cnfe) { throw new LEAPSerializationException("Cannot deserialize ServiceDescriptor: class "+className+" for service "+name+" not found"); } catch (Throwable t) { throw new LEAPSerializationException("Error deserializing ServiceDescriptor"); } } private SliceProxy deserializeSliceProxy() throws LEAPSerializationException { String className = null; try { className = readUTF(); SliceProxy proxy = (SliceProxy) Class.forName(className).newInstance(); proxy.setNode(readNode()); return proxy; } catch (ClassNotFoundException cnfe) { throw new LEAPSerializationException("Cannot deserialize SliceProxy: class "+className+" not found"); } catch (Throwable t) { throw new LEAPSerializationException("Error deserializing SliceProxy"); } } //#DOTNET_EXCLUDE_BEGIN private Service.SliceProxy deserializeServiceSliceProxy() throws LEAPSerializationException { try { String className = readUTF(); Service.SliceProxy proxy = (Service.SliceProxy) Class.forName(className).newInstance(); proxy.setNode(readNode()); return proxy; } catch (Throwable t) { throw new LEAPSerializationException("Error deserializing Service.SliceProxy"); } } //#DOTNET_EXCLUDE_END private NodeDescriptor deserializeNodeDescriptor() throws LEAPSerializationException { try { NodeDescriptor dsc = null; Node node = deserializeNode(); if(readBoolean()) { ContainerID cid = deserializeContainerID(); dsc = new NodeDescriptor(cid, node); } else { dsc = new NodeDescriptor(node); } dsc.setParentNode(readNode()); dsc.setUsername(readString()); dsc.setPassword((byte[]) readObject()); dsc.setPrincipal((JADEPrincipal) readObject()); dsc.setOwnerPrincipal((JADEPrincipal) readObject()); dsc.setOwnerCredentials((Credentials) readObject()); return dsc; } catch(IOException ioe) { throw new LEAPSerializationException("Error deserializing NodeDescriptor"); } } // Package-scoped since it is used by the NodeSerializer Node deserializeNode() throws LEAPSerializationException { try { String name = readString(); boolean hasPM = readBoolean(); NodeStub stub = (NodeStub) deserializeStub(); stub.setName(name); stub.setPlatformManager(hasPM); return stub; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing node"); } } private PlatformManager deserializePlatformManager() throws LEAPSerializationException { String address = readString(); PlatformManagerStub stub = (PlatformManagerStub) deserializeStub(); stub.setLocalAddress(address); return stub; } private Stub deserializeStub() throws LEAPSerializationException { try { String stubClassName = readUTF(); Stub stub = (Stub) Class.forName(stubClassName).newInstance(); stub.remoteID = readInt(); stub.platformName = readString(); stub.remoteTAs = deserializeArrayList(); stub.bind(myStubHelper); return stub; } catch(Throwable t) { throw new LEAPSerializationException("Error deserializing stub"); } } private Node readNode() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if(presenceFlag) { return deserializeNode(); } else { return null; } } catch(IOException ioe) { throw new LEAPSerializationException("Error deserializing Node"); } } private Node[] deserializeNodeArray() throws LEAPSerializationException { try { Node[] nodes = new Node[readInt()]; for(int i = 0; i < nodes.length; i++) { nodes[i] = readNode(); } return nodes; } catch(IOException ioe) { throw new LEAPSerializationException("Error deserializing Node[]"); } } public Node[] readNodeArray() throws LEAPSerializationException { try { boolean presenceFlag = readBoolean(); if (presenceFlag) { return deserializeNodeArray(); } else { return null; } } catch (IOException e) { throw new LEAPSerializationException("Error deserializing Node[]"); } } private Envelope deserializeEnvelope() throws LEAPSerializationException { try { Envelope e = new Envelope(); while (readBoolean()) { e.addTo(deserializeAID()); } e.setFrom(readAID()); e.setComments(readString()); e.setAclRepresentation(readString()); e.setPayloadLength(new Long(readLong())); e.setPayloadEncoding(readString()); e.setDate(readDate()); while (readBoolean()) { e.addIntendedReceiver(deserializeAID()); } e.setReceived((ReceivedObject) readObject()); while (readBoolean()) { e.addProperties(deserializeProperty()); } return e; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing Envelope"); } } private ArrayList deserializeArrayList() throws LEAPSerializationException { try { ArrayList l = new ArrayList(); int size = readInt(); for (int i = 0; i < size; ++i) { l.add(readObject()); } return l; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing ArrayList"); } } private byte[] deserializeByteArray() throws LEAPSerializationException { try { byte[] ba = new byte[readInt()]; read(ba, 0, ba.length); return ba; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing Byte Array"); } } private Properties deserializeProperties() throws LEAPSerializationException { try { Properties p = new Properties(); int size = readInt(); for (int i = 0; i < size; i++) { p.setProperty((String) readObject(), (String) readObject()); } return p; } catch (IOException ioe) { throw new LEAPSerializationException("Error deserializing Properties"); } } private ReceivedObject deserializeReceivedObject() throws LEAPSerializationException { ReceivedObject r = new ReceivedObject(); r.setBy(readString()); r.setFrom(readString()); r.setDate(readDate()); r.setId(readString()); r.setVia(readString()); return r; } /** */ private Property deserializeProperty() throws LEAPSerializationException { Property p = new Property(); p.setName(readString()); p.setValue(readObject()); return p; } private JICPAddress deserializeJICPAddress() throws LEAPSerializationException { String protocol = readString(); if (!JICPProtocol.NAME.equals(protocol)) { throw new LEAPSerializationException("Unexpected protocol \""+protocol+"\" when \"" +JICPProtocol.NAME+"\" was expected."); } String host = readString(); String port = readString(); String file = readString(); String anchor = readString(); return new JICPAddress(host, port, file, anchor); } private HTTPAddress deserializeHTTPAddress() throws LEAPSerializationException { String protocol = readString(); if (!HTTPProtocol.NAME.equals(protocol)) { throw new LEAPSerializationException("Unexpected protocol \""+protocol+"\" when \"" +HTTPProtocol.NAME+"\" was expected."); } String host = readString(); String port = readString(); String file = readString(); String anchor = readString(); return new HTTPAddress(host, port, file, anchor); } private Throwable deserializeThrowable() throws LEAPSerializationException { String className = readString(); String message = readString(); try { Throwable result = (Throwable)Class.forName(className).newInstance(); // FIXME: How do we set the message? return result; } catch(Throwable t) { // Actual class not found: simply create a java.lang.Exception return new java.lang.Exception(message + " [Original exception was: " + className + "]"); } } } // End of DeliverableDataInputStream class