/*--- 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.DataOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Date; import java.util.Vector; import java.util.Enumeration; 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.Iterator; import jade.util.leap.Properties; import jade.util.leap.ArrayList; import jade.mtp.MTPDescriptor; import jade.mtp.TransportAddress; import jade.imtp.leap.JICP.JICPAddress; import jade.imtp.leap.http.HTTPAddress; /** * This class implements a data output stream serializing * Deliverables, primitive types and J2SE class types that are considered as * primitive type to a given byte array according to the LEAP surrogate * serialization mechanism. * * @author Michael Watzke * @author Giovanni Caire * @author Nicolas Lhuillier * @author Jerome Picault */ class DeliverableDataOutputStream extends DataOutputStream { private StubHelper myStubHelper; /** * Constructs a data output stream that is serializing Deliverables to a * given byte array according to the LEAP surrogate serialization * mechanism. */ public DeliverableDataOutputStream(StubHelper sh) { super(new ByteArrayOutputStream()); myStubHelper = sh; } /** * Get the byte array that contains the frozen, serialized Deliverables * written to this data output stream. * @return the byte array containing the serialized Deliverables written * to this data output stream */ public byte[] getSerializedByteArray() { return ((ByteArrayOutputStream) out).toByteArray(); } /** * Writes an object whose class is not known from the context to * this data output stream. * @param o the object to be written. * @exception LEAPSerializationException if an error occurs during * serialization or the object is an instance of a class that cannot be * serialized. */ public void writeObject(Object o) throws LEAPSerializationException { try { if (o != null) { // Presence flag true writeBoolean(true); // Directly handle serialization of classes that must be // serialized more frequently if (o instanceof HorizontalCommand) { writeByte(Serializer.HORIZONTALCOMMAND_ID); serializeHorizontalCommand((HorizontalCommand)o); } else if (o instanceof ACLMessage) { // ACLMessage writeByte(Serializer.ACL_ID); serializeACL((ACLMessage) o); } else if (o instanceof AID) { // AID writeByte(Serializer.AID_ID); serializeAID((AID) o); } else if (o instanceof AID[]) { // AID array writeByte(Serializer.AIDARRAY_ID); serializeAIDArray((AID[]) o); } else if (o instanceof GenericMessage) { // GenericMessage writeByte(Serializer.GENERICMESSAGE_ID); serializeGenericMessage((GenericMessage) o); } else if (o instanceof String) { // String writeByte(Serializer.STRING_ID); writeUTF((String) o); } else if (o instanceof NodeDescriptor) { // NodeDescriptor writeByte(Serializer.NODEDESCRIPTOR_ID); serializeNodeDescriptor((NodeDescriptor) o); } else if (o instanceof ContainerID) { // ContainerID writeByte(Serializer.CONTAINERID_ID); serializeContainerID((ContainerID) o); } else if (o instanceof ContainerID[]) { // ContainerID[] writeByte(Serializer.CONTAINERIDARRAY_ID); serializeContainerIDArray((ContainerID[]) o); } else if (o instanceof Boolean) { // Boolean writeByte(Serializer.BOOLEAN_ID); writeBoolean(((Boolean) o).booleanValue()); } else if (o instanceof Integer) { // Integer writeByte(Serializer.INTEGER_ID); writeInt(((Integer) o).intValue()); } else if (o instanceof Date) { // Date writeByte(Serializer.DATE_ID); serializeDate((Date) o); } else if (o instanceof String[]) { // Array of Strings writeByte(Serializer.STRINGARRAY_ID); serializeStringArray((String[]) o); } else if (o instanceof Vector) { // Vector writeByte(Serializer.VECTOR_ID); serializeVector((Vector) o); } else if (o instanceof MTPDescriptor) { // MTPDescriptor writeByte(Serializer.MTPDESCRIPTOR_ID); serializeMTPDescriptor((MTPDescriptor) o); } else if (o instanceof Node) { // Node writeByte(Serializer.NODE_ID); serializeNode((Node) o); } else if (o instanceof PlatformManager) { // PlatformManager writeByte(Serializer.PLATFORMMANAGER_ID); serializePlatformManager((PlatformManager) o); } else if (o instanceof Node[]) { // Array of Node writeByte(Serializer.NODEARRAY_ID); serializeNodeArray((Node[]) o); } else if (o instanceof ArrayList) { // ArrayList writeByte(Serializer.ARRAYLIST_ID); serializeArrayList((ArrayList) o); } else if (o instanceof byte[]) { // Byte Array writeByte(Serializer.BYTEARRAY_ID); serializeByteArray((byte[]) o); } else if (o instanceof Envelope) { // Envelope writeByte(Serializer.ENVELOPE_ID); serializeEnvelope((Envelope) o); } else if (o instanceof JICPAddress) { // JICPAddress writeByte(Serializer.JICPADDRESS_ID); serializeTransportAddress((JICPAddress) o); } else if (o instanceof HTTPAddress) { // HTTPAddress writeByte(Serializer.HTTPADDRESS_ID); serializeTransportAddress((HTTPAddress) o); } else if (o instanceof Properties) { // Properties writeByte(Serializer.PROPERTIES_ID); serializeProperties((Properties) o); } else if (o instanceof ReceivedObject) { // ReceivedObject writeByte(Serializer.RECEIVEDOBJECT_ID); serializeReceivedObject((ReceivedObject) o); } else if (o instanceof ServiceDescriptor) { // ServiceDescriptor writeByte(Serializer.SERVICEDESCRIPTOR_ID); serializeServiceDescriptor((ServiceDescriptor) o); } else if (o instanceof SliceProxy) { // SliceProxy writeByte(Serializer.SLICEPROXY_ID); serializeSliceProxy((SliceProxy) o); } //#DOTNET_EXCLUDE_BEGIN else if (o instanceof Service.SliceProxy) { // Service.SliceProxy writeByte(Serializer.SERVICESLICEPROXY_ID); serializeServiceSliceProxy((Service.SliceProxy) o); } //#DOTNET_EXCLUDE_END else if(o instanceof Property) { // Property writeByte(Serializer.PROPERTY_ID); serializeProperty((Property) o); } /*#MIDP_INCLUDE_BEGIN // In J2SE and PJAVA we use Java serialization to transport // Throwable objects so that we keep the correct message. else if(o instanceof Throwable) { // Throwable writeByte(Serializer.THROWABLE_ID); serializeThrowable((Throwable) o); } #MIDP_INCLUDE_END*/ //#MIDP_EXCLUDE_BEGIN else if (o instanceof java.io.Serializable) { // Serializable writeByte(Serializer.SERIALIZABLE_ID); ByteArrayOutputStream out = new ByteArrayOutputStream(); java.io.ObjectOutputStream encoder = new java.io.ObjectOutputStream(out); encoder.writeObject(o); byte[] bytes = out.toByteArray(); serializeByteArray(bytes); } //#MIDP_EXCLUDE_END else { // Delegate serialization of other classes // to a proper Serializer object Serializer s = getSerializer(o); writeByte(Serializer.DEFAULT_ID); writeUTF(s.getClass().getName()); s.serialize(o, this); } } // END of if (o != null) else { // Presence flag false writeBoolean(false); } } // END of try catch (IOException ioe) { throw new LEAPSerializationException("Error Serializing object "+o); } } /** * Writes an AID object to this data output stream. * @param id the AID to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeAID(AID id) throws LEAPSerializationException { try { if (id != null) { writeBoolean(true); // Presence flag true serializeAID(id); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing AID"); } } /** * Writes a String object to this data output stream. * @param s the String to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeString(String s) throws LEAPSerializationException { try { if (s != null) { writeBoolean(true); // Presence flag true writeUTF(s); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing String"); } } /** * Writes a Date object to this data output stream. * @param d the Date to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeDate(Date d) throws LEAPSerializationException { try { if (d != null) { writeBoolean(true); // Presence flag true serializeDate(d); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing Date"); } } /** * Writes a StringBuffer object to this data output stream. * @param s the StringBuffer to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeStringBuffer(StringBuffer s) throws LEAPSerializationException { try { if (s != null) { writeBoolean(true); // Presence flag true serializeStringBuffer(s); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing String"); } } /** * Writes a Vector object to this data output stream. * @param v the Vector to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeVector(Vector v) throws LEAPSerializationException { try { if (v != null) { writeBoolean(true); // Presence flag true serializeVector(v); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing Vector"); } } /** * Writes an array of String to this data output stream. * @param sa the array of String to be written. * @exception LEAPSerializationException if an error occurs during * serialization */ public void writeStringArray(String[] sa) throws LEAPSerializationException { try { if (sa != null) { writeBoolean(true); // Presence flag true serializeStringArray(sa); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing String[]"); } } // PRIVATE METHODS // All the following methods are used to actually serialize instances of // Java classes to this output stream. They are only used internally when // the context ensures that the Java object to be serialized is not null! /** */ private void serializeDate(Date d) throws IOException { writeLong(d.getTime()); } /** */ private void serializeStringBuffer(StringBuffer sb) throws IOException { writeUTF(sb.toString()); } /** */ private void serializeVector(Vector v) throws IOException, LEAPSerializationException { writeInt(v.size()); for (int i = 0; i < v.size(); i++) { writeObject(v.elementAt(i)); } } /** */ private void serializeStringArray(String[] sa) throws IOException, LEAPSerializationException { writeInt(sa.length); for (int i = 0; i < sa.length; i++) { writeString(sa[i]); } } private void serializeNodeDescriptor(NodeDescriptor desc) throws IOException, LEAPSerializationException { serializeNode(desc.getNode()); writeContainerID(desc.getContainer()); writeNode(desc.getParentNode()); writeString(desc.getUsername()); writeObject(desc.getPassword()); writeObject(desc.getPrincipal()); writeObject(desc.getOwnerPrincipal()); writeObject(desc.getOwnerCredentials()); } private void serializeHorizontalCommand(HorizontalCommand cmd) throws LEAPSerializationException { try { // Write the mandatory command name and command service writeUTF(cmd.getName()); writeUTF(cmd.getService()); // Write optional interaction ID writeString(cmd.getInteraction()); // Write all parameters Object[] params = cmd.getParams(); int sz = params.length; writeInt(sz); for(int i = 0; i < sz; i++) { writeObject(params[i]); } } catch(IOException ioe) { throw new LEAPSerializationException("Error serializing 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 void serializeACL(ACLMessage msg) throws IOException, LEAPSerializationException { LEAPACLCodec.serializeACL(msg, this); //#CUSTOM_EXCLUDE_BEGIN // NOTE that the above call does not serialize the envelope Envelope env = msg.getEnvelope(); if (env != null) { writeBoolean(true); serializeEnvelope(env); } else { writeBoolean(false); } //#CUSTOM_EXCLUDE_END } /** * Package scoped as it is called by the EnvelopSerializer */ void serializeAID(AID id) throws IOException, LEAPSerializationException { LEAPACLCodec.serializeAID(id, this); } private void serializeAIDArray(AID[] aida) throws IOException, LEAPSerializationException { writeInt(aida.length); for (int i = 0; i < aida.length; i++) { writeAID(aida[i]); } } private void serializeGenericMessage(GenericMessage gm) throws IOException, LEAPSerializationException { byte[] payload = gm.getPayload(); if (payload == null) { payload = (new LEAPACLCodec()).encode(gm.getACLMessage(), null); } serializeByteArray(payload); writeObject(gm.getEnvelope()); writeBoolean(gm.isAMSFailure()); writeObject(gm.getTraceID()); } /** * Package scoped as it is called by the CommandDispatcher */ void serializeCommand(Command cmd) throws LEAPSerializationException { try { writeInt(cmd.getCode()); // the code of the command has to // be at index 0 and it has to be // a 4 byte integer. writeInt(cmd.getObjectID()); int paramCnt = cmd.getParamCnt(); writeInt(paramCnt); for (int i = 0; i < paramCnt; ++i) { writeObject(cmd.getParamAt(i)); } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing Command"); } } /** */ public void serializeContainerID(ContainerID cid) throws LEAPSerializationException { try { writeUTF(cid.getName()); writeUTF(cid.getAddress()); } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing ContainerID"); } } public void writeContainerID(ContainerID id) throws LEAPSerializationException { try { if (id != null) { writeBoolean(true); // Presence flag true serializeContainerID(id); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing ContainerID"); } } private void serializeContainerIDArray(ContainerID[] cida) throws IOException, LEAPSerializationException { writeInt(cida.length); for (int i = 0; i < cida.length; i++) { writeContainerID(cida[i]); } } /** */ public void serializeMTPDescriptor(MTPDescriptor dsc) throws LEAPSerializationException { try { writeUTF(dsc.getName()); writeUTF(dsc.getClassName()); writeStringArray(dsc.getAddresses()); writeStringArray(dsc.getSupportedProtocols()); } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing MTPDescriptor"); } } /** */ private void serializeServiceDescriptor(ServiceDescriptor dsc) throws LEAPSerializationException { try { writeUTF(dsc.getName()); Service svc = dsc.getService(); writeUTF(svc.getClass().getName()); } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing ServiceDescriptor"); } } /** */ private void serializeSliceProxy(SliceProxy proxy) throws LEAPSerializationException { try { writeUTF(proxy.getClass().getName()); writeNode(proxy.getNode()); } catch (Throwable t) { throw new LEAPSerializationException("Error serializing SliceProxy"); } } //#DOTNET_EXCLUDE_BEGIN /** */ private void serializeServiceSliceProxy(Service.SliceProxy proxy) throws LEAPSerializationException { try { writeUTF(proxy.getClass().getName()); writeNode(proxy.getNode()); } catch (Throwable t) { throw new LEAPSerializationException("Error serializing Service.SliceProxy"); } } //#DOTNET_EXCLUDE_END private void serializeNode(Node n) throws LEAPSerializationException { try { writeString(n.getName()); writeBoolean(n.hasPlatformManager()); NodeStub stub = null; if (n instanceof NodeStub) { // This is already a stub --> serialize it directly stub = (NodeStub) n; } else { // This is a real node --> get a stub and serialize it stub = (NodeStub) myStubHelper.buildLocalStub(n); } serializeStub(stub); } catch(IOException ioe) { ioe.printStackTrace(); throw new LEAPSerializationException("Error building a Node stub"); } catch(IMTPException imtpe) { imtpe.printStackTrace(); throw new LEAPSerializationException("Error building a Node stub"); } } private void writeNode(Node n) throws LEAPSerializationException { try { if (n != null) { writeBoolean(true); // Presence flag true serializeNode(n); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing Node[]"); } } private void serializePlatformManager(PlatformManager pm) throws LEAPSerializationException { try { writeString(pm.getLocalAddress()); PlatformManagerStub stub = null; if (pm instanceof PlatformManagerStub) { // This is already a stub --> serialize it directly stub = (PlatformManagerStub) pm; } else { // This is a real PlatformManager --> get a stub and serialize it stub = (PlatformManagerStub) myStubHelper.buildLocalStub(pm); } serializeStub(stub); } catch(IMTPException imtpe) { imtpe.printStackTrace(); throw new LEAPSerializationException("Error building a PlatformManager stub"); } } private void serializeStub(Stub stub) throws LEAPSerializationException { try { writeUTF(stub.getClass().getName()); // Write the remote ID, uniquely identifying the remotized object this stub points to writeInt(stub.remoteID); // Write the name of the platform this stub belongs to writeString(stub.platformName); // Write all the transport addresses serializeArrayList((ArrayList) stub.remoteTAs); } catch(IOException ioe) { throw new LEAPSerializationException("I/O Error during stub serialization"); } } private void serializeNodeArray(Node[] nodes) throws LEAPSerializationException { try { writeInt(nodes.length); for (int i = 0; i < nodes.length; i++) { writeNode(nodes[i]); } } catch (IOException ioe) { throw new LEAPSerializationException("IO error serializing node array"); } } public void writeNodeArray(Node[] nodes) throws LEAPSerializationException { try { if (nodes != null) { writeBoolean(true); // Presence flag true serializeNodeArray(nodes); } else { writeBoolean(false); // Presence flag false } } catch (IOException ioe) { throw new LEAPSerializationException("Error serializing Node[]"); } } /** */ private void serializeArrayList(ArrayList l) throws LEAPSerializationException { try { int size = l.size(); writeInt(size); for (int i = 0; i < size; i++) { writeObject(l.get(i)); } } catch (IOException ioe) { throw new LEAPSerializationException("I/O error serializing ArrayList "+l); } } /** */ private void serializeByteArray(byte[] ba) throws LEAPSerializationException { try { writeInt(ba.length); write(ba, 0, ba.length); } catch (IOException ioe) { throw new LEAPSerializationException("IO error serializing byte[] "+ba); } } /** */ private void serializeEnvelope(Envelope e) throws LEAPSerializationException { try { // to Iterator it = e.getAllTo(); while (it.hasNext()) { writeBoolean(true); serializeAID((AID) it.next()); } writeBoolean(false); writeAID(e.getFrom()); writeString(e.getComments()); writeString(e.getAclRepresentation()); writeLong(e.getPayloadLength().longValue()); writeString(e.getPayloadEncoding()); writeDate(e.getDate()); // intended receivers it = e.getAllIntendedReceiver(); while (it.hasNext()) { writeBoolean(true); serializeAID((AID) it.next()); } writeBoolean(false); writeObject(e.getReceived()); // properties it = e.getAllProperties(); while (it.hasNext()) { writeBoolean(true); serializeProperty((Property) it.next()); } writeBoolean(false); } catch (IOException ioe) { throw new LEAPSerializationException("IO error serializing Envelope "+e); } } /** */ private void serializeTransportAddress(TransportAddress addr) throws LEAPSerializationException { writeString(addr.getProto()); writeString(addr.getHost()); writeString(addr.getPort()); writeString(addr.getFile()); writeString(addr.getAnchor()); } /** */ private void serializeProperties(Properties p) throws LEAPSerializationException { try { int size = p.size(); writeInt(size); Enumeration e = p.propertyNames(); while (e.hasMoreElements()) { Object key = e.nextElement(); writeObject(key); writeObject(p.getProperty((String) key)); } } catch (IOException ioe) { throw new LEAPSerializationException("I/O error serializing Properties "+p); } } /** */ private void serializeReceivedObject(ReceivedObject r) throws LEAPSerializationException { writeString(r.getBy()); writeString(r.getFrom()); writeDate(r.getDate()); writeString(r.getId()); writeString(r.getVia()); } /** */ private void serializeProperty(Property p) throws LEAPSerializationException { writeString(p.getName()); writeObject(p.getValue()); } private void serializeThrowable(Throwable t) throws LEAPSerializationException { writeString(t.getClass().getName()); writeString(t.getMessage()); } /** */ private Serializer getSerializer(Object o) throws LEAPSerializationException { String fullName = o.getClass().getName(); int index = fullName.lastIndexOf('.'); String name = fullName.substring(index+1); String serName = new String("jade.imtp.leap."+name+"Serializer"); // DEBUG // System.out.println(serName); try { Serializer s = (Serializer) Class.forName(serName).newInstance(); return s; } catch (Exception e) { throw new LEAPSerializationException("Error creating Serializer for object "+o); } } }