package network.connectors; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.ObjectOutputStream; import platform.ClassManager.ChangeClassInputStream; import util.streams.samples.Sample; import java.io.Serializable; import platform.plugins.installables.network.DNS.KalimuchoDNS; import util.NetworkAddress; /** * This class is used to encapsulate samples created by BCs.<br> * Connectors receive encapsulated data because the normally sent class * of samples can be an unknown class for the connector. * The OU of the Osagaia container always encapsulate the samples produced by the BC before sending them to a connector. * The IU of the Osagaia container desencapsulate the samples before giving them to the BC. * * @author Dalmau */ public class EncapsulatedSample implements Serializable { private static final long serialVersionUID = 64240050101000111L; // pour serialisation /** * The number of extra bytes in the EncapsulatedSample when serialized from the size of its contents. * This information is used by the platform to calculate the number of bytes sent or received on the network. */ public transient static final int EXTRA_SIZE = 111; private byte[] contenu; private transient String expediteur = "unknown"; private long date; /** * */ public EncapsulatedSample() { contenu = new byte[0]; expediteur = "unknown"; date = System.currentTimeMillis(); } /** * Create an encapsulated sample from a Sample * @param ini the sample to encapsulate */ public EncapsulatedSample(Sample ini) { date = ini.getDate(); expediteur = "unknown"; contenu = new byte[0]; if (ini != null) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(ini); // serialisation en octets contenu = bos.toByteArray(); } catch (IOException ioe) { System.err.println("ByteArraySample: Cant convert Sample to byte array"); } } } /** * Returns the size of the byte array included in this encapsulated sample * @return the size of the byte array included in this encapsulated sample */ public int size() {return contenu.length; } /** * When an encapsulated sample is received by network, the address of the expeditor is set by this method * @param exp the address of the expeditor of an encapsulated sample received by network */ public void setExpeditor(String exp) { expediteur = exp; } /** * Desencapsulate a sample according to a given class loader * @param cl the class loader used to desencapsulate the sample (normaly the class loader of the BC that uses this sample) * @return the desencapsulated sample */ public Sample getSample(ClassLoader cl) { Sample retour; ByteArrayInputStream bis = new ByteArrayInputStream(contenu); try { ChangeClassInputStream ois = new ChangeClassInputStream(bis, cl); retour = (Sample)ois.readObject(); // deserialisation retour.setDate(date); if (expediteur != null) retour.setExpeditor(expediteur); else retour.setExpeditor("unknown"); } catch (IOException ioe) { System.err.println("EncapsulatedSample: Cant read encapsulated Sample in byte array"); retour = null; } catch (ClassNotFoundException cnfe) { System.err.println("EncapsulatedSample: Class error converting EncapsulatedSample to Sample"); retour = null; } return retour; } /** * Adds the actual local time to the encapsulated sample */ public void setLocalDate() { date = System.currentTimeMillis(); } /** * Sets the date of the encapsulated sample in local time: * This date is calculated from the remote date according to the clock shift between * the sender and the local host (if available). Otherwise the date is the local reception date. * @param dns the dns service (if this service is not active this methos is not called) * @param expediteur the address of the sender of the encapsulated sample */ public void setRemoteDate(KalimuchoDNS dns, NetworkAddress expediteur) { String IDexpeditor = dns.getHostID(expediteur); if (IDexpeditor != null) { if (dns.isRemoteHostClockShiftAvailable(IDexpeditor)) date = date+dns.getRemoteHostClockShift(IDexpeditor); } else setLocalDate(); } }