All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.dyade.aaa.agent.MessageOutputStream Maven / Gradle / Ivy

/*
 * Copyright (C) 2008 ScalAgent Distributed Technologies 
 *
 * 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; either
 * version 2.1 of the License, or any later version.
 * 
 * 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 fr.dyade.aaa.agent;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * Class used to send messages through a stream.
 * 

* This OutputStream is a combination between a ByteArrayOutputStream and a * BufferedOutputStream. It allows the replacement of the underlying stream and * the serialization of object through an internal ObjectOutputStream. *

* Be careful this OutputStream is not synchronized. */ public abstract class MessageOutputStream extends OutputStream { /** * The internal ObjectOutputStream needed to serialize the notification. */ protected ObjectOutputStream oos; /** * The internal buffer where data is stored. */ protected byte buf[]; /** * The number of valid bytes in the buffer. */ protected int count; protected boolean compressedFlows = false; /** * Default logger for MessageOutputStream. */ protected static Logger logmon = null; /** * Returns default logger for MessageOutputStream. * @return Default logger for MessageOutputStream. */ protected static Logger getLogger() { if (logmon == null) logmon = Debug.getLogger("fr.dyade.aaa.agent.MessageOutputStream"); return logmon; } // ObjectStream constants needed to reinitialize the ObjectOutputStream. private static final byte STREAM_MAGIC1 = (byte)((ObjectStreamConstants.STREAM_MAGIC >>> 8) & 0xFF); private static final byte STREAM_MAGIC2 = (byte)((ObjectStreamConstants.STREAM_MAGIC >>> 0) & 0xFF); private static final byte STREAM_VERSION1 = (byte)((ObjectStreamConstants.STREAM_VERSION >>> 8) & 0xFF); private static final byte STREAM_VERSION2 = (byte)((ObjectStreamConstants.STREAM_VERSION >>> 0) & 0xFF); /** * Creates a new output stream to write data to an unspecified * underlying output stream through a buffer with default size. */ public MessageOutputStream() throws IOException { this(8192); } /** * Creates a new output stream to write data to an unspecified * underlying output stream through a buffer with specified size. * * @param size the buffer size. * @exception IllegalArgumentException if size is less than 0. * @exception IOException if the internal ObjectOutputStream cannot be * correctly initialized. */ public MessageOutputStream(int size) throws IOException { if (size <= 0) throw new IllegalArgumentException("Buffer size <= 0"); buf = new byte[size]; if (! compressedFlows) oos = new ObjectOutputStream(this); count = 0; } /** * Writes the specified byte to this output stream. * * @param b the byte to be written. * @exception IOException if an I/O error occurs. */ public abstract void write(int b) throws IOException; /** * Writes b.length bytes to this output stream. *

* This method calls its write method of three arguments with * the arguments b, 0, and b.length. * * @param b the data to be written. * @exception IOException if an I/O error occurs. * @see write(byte[], int, int) */ public final void write(byte b[]) throws IOException { write(b, 0, b.length); } /** * Writes len bytes from the specified byte array starting * at offset off to this output stream. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. */ public abstract void write(byte b[], int off, int len) throws IOException; /** * Writes a short directly to the buffer. * Be careful, the buffer must be large enough to contain the short. * * @param s the data. */ protected final void writeShort(short s) { buf[count++] = (byte) (s >>> 8); buf[count++] = (byte) (s >>> 0); } /** * Writes an int directly to the buffer. * Be careful, the buffer must be large enough to contain the int. * * @param i the data. */ protected final void writeInt(int i) { buf[count++] = (byte) (i >>> 24); buf[count++] = (byte) (i >>> 16); buf[count++] = (byte) (i >>> 8); buf[count++] = (byte) (i >>> 0); } /** * Writes the protocol header to this output stream. * This method must be overloaded in subclass. */ abstract protected void writeHeader() throws IOException; /** * Writes the message header data to the buffer. * * @param msg The message to write out. */ protected final void writeMessageHeader(Message msg) { if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessageHeader()"); // Writes sender's AgentId writeShort(msg.from.from); writeShort(msg.from.to); writeInt(msg.from.stamp); // Writes adressee's AgentId writeShort(msg.to.from); writeShort(msg.to.to); writeInt(msg.to.stamp); // Writes source server id of message writeShort(msg.source); // Writes destination server id of message writeShort(msg.dest); // Writes stamp of message writeInt(msg.stamp); if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessageHeader returns"); } /** * Writes a message to this output stream. * This method can be overloaded in subclass. * * @param msg The message to write out. * @param time The current time in milliseconds, this parameter * is used to the handling of notification expiration. */ protected final void writeMessage(Message msg, long time) throws IOException { if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessage()"); // Writes the protocol specific data. writeHeader(); if (msg != null) { // Writes the message header data. writeMessageHeader(msg); if (msg.not == null) { if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessage - 1"); buf[count++] = Message.NULL; flush(); } else { if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessage - 2"); // Writes notification attributes buf[count++] = msg.optToByte(); try { if (msg.not.expiration > 0) msg.not.expiration -= time; // Writes a serializable object to this output stream. if (compressedFlows) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gzipos = new GZIPOutputStream(baos); oos = new ObjectOutputStream(gzipos); oos.writeObject(msg.not); // Be careful, the reset writes a TC_RESET byte oos.reset(); // The OOS flush call the flush of this output stream. oos.flush(); gzipos.finish(); gzipos.flush(); if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeNotification - size=" + baos.size()); writeInt(baos.size()); baos.writeTo(this); flush(); oos = null; } else { // Write the STREAM_MAGIC constant buf[count++] = STREAM_MAGIC1; buf[count++] = STREAM_MAGIC2; // Write the STREAM_VERSION constant buf[count++] = STREAM_VERSION1; buf[count++] = STREAM_VERSION2; oos.writeObject(msg.not); // Be careful, the reset writes a TC_RESET byte oos.reset(); // The OOS flush call the flush of this output stream. oos.flush(); } } finally { if ((msg.not != null) && (msg.not.expiration > 0)) msg.not.expiration += time; } } } else { flush(); } if (getLogger().isLoggable(BasicLevel.DEBUG)) getLogger().log(BasicLevel.DEBUG, "writeMessage returns"); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy