package network.platform;
import platform.servicesregister.ServicesRegisterManager;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import network.NetworkMessage;
import network.NetworkEmitterContainer;
import util.NetworkAddress;
import platform.InternalPlatformMessage;
import util.Parameters;
/**
* Extends NetworkMessage and holds:<br>
* A string which is the platform command<br>
* The name of the PF service to which this message is<br>
* The name of the PF servoce to reply to this message<br>
* A serialized BC as a byte array<br>
* This class is used by the platform only.
*
* @author Dalmau
*/
/*
* Classe pour envoyer et recevoir des messages par reseau par la PF
*/
public class NetworkPlatformMessage extends NetworkMessage implements Serializable {
private static final long serialVersionUID = 64240030300000001L; // pour serialisation
private String contenu; // commande et parametres pour une PF
private String owner; // service destinataire du message
private String replyTo; // service auquel repondre
private byte[] serializedObject; // CM serialise
private long date;
/* Le CM serialise est envoye sous forme de tableau d'octets et pas d'objet car
* lorsque le message est relaye par une PF il est possible que cette PF n'ait
* pas de chargeur de classe pour ce CM.
* La PF qui migre un composant le convertit en tableau d'octets
* La PF qui relaye le message se conten te de transmettre ce tableau d'octets
* (elle n'a pas le chargeur de classe pour le convertir en objet)
* La PF qui recoit le message transforme ce tableau d'octets en objet
* (elle a le chargeur de classe pour le faire)
*/
/**
* Construction without parameters necessary for de-serialisation with KSN
*/
public NetworkPlatformMessage() {
// constructeur sans parametre necessaire pour pouvoir deserialiser
super();
contenu = "";
owner = "";
replyTo = "";
date = System.currentTimeMillis();
serializedObject = new byte[0];
}
/**
* Construction of a message
*
* @param own PF service for which this message is
* @param addr Address and port number to send this message to
*/
public NetworkPlatformMessage(String own, String addr) {
super(addr);
NetworkEmitterContainer nec = (NetworkEmitterContainer)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_EMISSIONS_CONTAINER);
int port = nec.getPlatformCommandPortNumber(new NetworkAddress(getAddress()).getType());
setPortNumber(port);
setExpeditorPort(port);
contenu = "";
owner = own;
replyTo = own;
date = System.currentTimeMillis();
serializedObject = new byte[0];
}
/**
* Construction of a message from an internal platform message
* If a BC is present as an object it is converted into a byte array.
*
* @param ini the internal platform message
*/
public NetworkPlatformMessage(InternalPlatformMessage ini) {
this(ini.getOwner(), ini.getAddress());
setPortNumber(ini.getPortNumber());
setFinalAddress(ini.getFinalAddress());
setFinalPort(ini.getFinalPort());
setExpeditorAddress(ini.getExpeditorAddress());
setExpeditorPort(ini.getExpeditorPort());
setReplyTo(ini.getReplyTo());
setDate(ini.getDate());
if (ini.getBC() != null) { // s'il y a un CM serialise le convertir en tableau d'octets
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(ini.getBC()); // serialisation en octets
serializedObject = bos.toByteArray();
}
catch (IOException ioe) {
System.err.println("Cant convert serialized BC to byte array");
serializedObject = new byte[0];
}
}
else serializedObject = new byte[0]; // pas de CM serialise dans ce message
addContent(ini.getContent());
}
/**
* Deserializes a NetworkPlatformMessage from a byte array.
* This is usefull because broadcast or multicast servers can't receive objects but only byte arrays
* @param content the byte array to deserialize from
*/
public NetworkPlatformMessage(byte[] content) {
super(); // pas d'adresse et de port d'envoi
ByteArrayInputStream bis = new ByteArrayInputStream(content);
try {
ObjectInputStream ois = new ObjectInputStream(bis);
finalAddress = (String)ois.readObject();
finalPort = ((Integer)ois.readObject()).intValue();
expeditorAddress = (String)ois.readObject();
expeditorPort = ((Integer)ois.readObject()).intValue();
senderID = (String)ois.readObject();
expeditorID = (String)ois.readObject();
contenu = (String)ois.readObject();
owner = (String)ois.readObject();
replyTo = (String)ois.readObject();
date = ((Long)ois.readObject()).longValue();
int taille = ((Integer)ois.readObject()).intValue();
serializedObject = new byte[taille];
for (int i=0; i<taille; i++) serializedObject[i] = (byte)bis.read();
}
catch (IOException ioe) {
System.err.println("Error converting a received network Platform message : IOError");
}
catch (ClassNotFoundException ioe) {
System.err.println("Error converting a received network Platform message : class not found");
}
}
/**
* Serializes a NetworkPlatformMessage to a byte array.
* This is usefull because broadcast or multicast senders can't send objects but only byte arrays
* @return the serilized NetworkPlatformMessage into a byte array
*/
public byte[] toByteArray() {
byte[] retour;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(finalAddress);
oos.writeObject(new Integer(finalPort));
oos.writeObject(expeditorAddress);
oos.writeObject(new Integer(expeditorPort));
oos.writeObject(senderID);
oos.writeObject(expeditorID);
oos.writeObject(contenu);
oos.writeObject(owner);
oos.writeObject(replyTo);
oos.writeObject(new Long(date));
oos.writeObject(new Integer(serializedObject.length));
for (int i=0; i<serializedObject.length; i++) bos.write(serializedObject[i]);
retour = bos.toByteArray();
}
catch (IOException ioe) {
System.err.println("Error converting a network platform message to byte array");
retour = null;
}
return retour;
}
/**
* Makes a copy a the message.
* When a message is sent some informations can be modified by the network sender.
* So it is necessary to make a copy of the message because the same message can be sent on various networks.
* In this case each sender will modify the message so it cant be the same object.
* @return a clome of the message
*/
@Override
public NetworkPlatformMessage clone() {
NetworkPlatformMessage copie = new NetworkPlatformMessage();
copie.setAddress(new String(destinationAddress));
copie.setPortNumber(destinationPort);
copie.setExpeditorAddress(new String(expeditorAddress));
copie.setExpeditorPort(expeditorPort);
copie.setFinalAddress(new String(finalAddress));
copie.setFinalPort(finalPort);
copie.setSenderID(new String(getSenderID()));
copie.setExpeditorID(new String(getExpeditorID()));
copie.setOwner(new String(owner));
copie.setReplyTo(new String(replyTo));
copie.setDate(System.currentTimeMillis());
copie.addContent(new String(contenu));
byte[] code = new byte[serializedObject.length];
for (int i=0; i<serializedObject.length; i++) code[i] = serializedObject[i];
copie.setSerializedObject(code);
return copie;
}
/**
* Add a string to the message
*
* @param e The string to be added to the message
*/
public void addContent(String e) {
contenu = e;
}
/**
* Get the string in the message
*
* @return command or alarm in the message
*/
public String getContent() {
return contenu;
}
/**
* Sets the service to which this message is
* @param own the service to which this message is
*/
public void setOwner(String own) {
owner = own;
}
/**
* Sets the service to which the answer of this message is
* @param to the service to which the answer of this message is
*/
public void setReplyTo(String to) {
replyTo = to;
}
/**
* Gets the service to which this message is
* @return the service to which this message is
*/
public String getOwner() { return owner; }
/**
* Gets the service to which the answer of this message is
* @return the service to which the answer of this message is
*/
public String getReplyTo() { return replyTo; }
/**
* Returns the date of creation of the massage
* @return the date of creation of the massage
*/
public long getDate() { return date; }
/**
* Sets the date of creation of the massage
* @param d the date of creation of the massage
*/
public void setDate(long d) { date = d; }
/**
* Gets the serialized BC as a byte array (empty array if there is no BC)
* @return the serialized BC as a byte array
*/
public byte[] getSerializedObject() { return serializedObject; }
/**
* Sets the byte array containing a serialized BC
* @param code the byte array containing a serialized BC
*/
public void setSerializedObject(byte[] code) { serializedObject = code; }
}