Package org.objectweb.joram.shared.messages

Source Code of org.objectweb.joram.shared.messages.Specialized_OIS

/*
* JORAM: Java(TM) Open Reliable Asynchronous Messaging
* Copyright (C) 2006 - 2011 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.
*
* Initial developer(s): ScalAgent Distributed Technologies
* Contributor(s):
*/
package org.objectweb.joram.shared.messages;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

import org.objectweb.joram.shared.admin.AbstractAdminMessage;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import fr.dyade.aaa.common.Debug;
import fr.dyade.aaa.common.stream.Properties;
import fr.dyade.aaa.common.stream.StreamUtil;
import fr.dyade.aaa.common.stream.Streamable;

/**
* Implements the <code>Message</code> data structure.
*/
public final class Message implements Cloneable, Serializable, Streamable {
  /** define serialVersionUID for interoperability */
  private static final long serialVersionUID = 3L;

  // default value from javax.jms.Message (jms 1.1)
  public static final int NON_PERSISTENT = 1;
  public static final int PERSISTENT = 2;
  public static final int DEFAULT_DELIVERY_MODE = PERSISTENT;
  public static final int DEFAULT_PRIORITY = 4;
  public static final long DEFAULT_TIME_TO_LIVE = 0;
 
  /** logger */
  public static Logger logger = Debug.getLogger(Message.class.getName());

  /**
   * Constructs a bright new <code>Message</code>.
   */
  public Message() {}

  /** Body of the message. */
  public transient byte[] body = null;

  /** The message properties table. */
  public transient Properties properties = null;

  /**
   * Returns a property as an object.
   *
   * @param name  The property name.
   */
  public Object getProperty(String name) {
    if (properties == null) return null;
    return properties.get(name);
  }

  /**
   * Sets a property value.
   * If the value is not a Java primitive object its string representation is used.
   *
   * @param name    The property name.
   * @param value  The property value.
   *
   * @exception IllegalArgumentException  If the key name is illegal (null or empty string).
   */
  public void setProperty(String name, Object value) {
    if (name == null || name.equals(""))
      throw new IllegalArgumentException("Invalid property name: " + name);
   
    if (properties == null)
      properties = new Properties();
   
    if (value instanceof Boolean || value instanceof Number || value instanceof String) {
      properties.put(name, value);
    } else {
      properties.put(name, value.toString());
    }
  }

  /** The message identifier. */
  public transient String id = null;
 
  /** <code>true</code> if the message must be persisted. */
  public transient boolean persistent = true;
  /** A simple message carries an empty body. */
  public static final int SIMPLE = 0;
  /** A text message carries a String body. */
  public static final int TEXT = 1;
  /** An object message carries a serializable object. */
  public static final int OBJECT = 2;
  /** A map message carries an hashtable. */
  public static final int MAP = 3;
  /** A stream message carries a bytes stream. */
  public static final int STREAM = 4;
  /** A bytes message carries an array of bytes. */
  public static final int BYTES = 5;
  /** A admin message carries a streamable object. */
  public static final int ADMIN = 6;

  /**
   * The client message type: SIMPLE, TEXT, OBJECT, MAP, STREAM, BYTES, ADMIN.
   * By default, the message type is SIMPLE.
   */
  public transient int type = SIMPLE;

  /**
   * The JMSType header field contains a message type identifier supplied by a
   * client when a message is sent.
   */
  public transient String jmsType = null;

  /**
   * The message priority from 0 to 9, 9 being the highest.
   * By default, the priority is 4?
   */
  public transient int priority = DEFAULT_PRIORITY;
  /** The message expiration time, by default 0 for infinite time-to-live. */
  public transient long expiration = 0;

  /** The message time stamp. */
  public transient long timestamp;

  /**
   * <code>true</code> if the message has been denied at least once by a
   * consumer.
   */
  public transient boolean redelivered = false;

  /** The message destination identifier. */
  public transient String toId = null;

  /** The message destination type. */
  public transient byte toType;

  /**
   * Sets the message destination.
   *
   * @param id  The destination identifier.
   * @param type The type of the destination.
   */
  public final void setDestination(String id, byte type) {
    toId = id;
    toType = type;
  }

//  /** Returns the message destination identifier. */
//  public final String getDestinationId() {
//    return toId;
//  }
//
//  /** Returns <code>true</code> if the destination is a queue. */
//  public final String getDestinationType() {
//    return toType;
//  }

  /** The reply to destination identifier. */
  public transient String replyToId = null;
  /** <code>true</code> if the "reply to" destination is a queue. */
  public transient byte replyToType;

//  /** Returns the destination id the reply should be sent to. */
//  public final String getReplyToId() {
//    return replyToId;
//  }
//
//  /** Returns <code>true</code> if the reply to destination is a queue. */
//  public final String replyToType() {
//    return replyToType;
//  }

  /**
   * Sets the destination to which a reply should be sent.
   *
   * @param id  The destination identifier.
   * @param type The destination type.
   */
  public final void setReplyTo(String id, byte type) {
    replyToId = id;
    replyToType = type;
  }

  /** The correlation identifier field. */
  public transient String correlationId = null;
  /** The number of delivery attempts for this message. */
  public transient  int deliveryCount = 0;

  /**
   * Sets a String as the body of the message.
   */
  public void setText(String text) {
    if (text == null) {
      body = null;
    } else {
      body = text.getBytes();
    }
  }

  /**
   * Returns the text body of the message.
   */
  public String getText() {
    if (body == null) {
      return null;
    }
    return new String(body);
  }

  /**
   * Sets an object as the body of the message.
   *
   * @exception IOException  In case of an error while setting the object.
   */
  public void setObject(Serializable object) throws IOException {
    type = Message.OBJECT;

    if (object == null) {
      body = null;
    } else {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(object);
      oos.flush();
      body = baos.toByteArray();
      oos.close();
      baos.close();
    }
  }

  /**
   * Returns the object body of the message.
   *
   * @exception Exception  In case of an error while getting the object.
   */
  public Serializable getObject() throws Exception {
    // TODO (AF): May be, we should verify that it is an Object message!!
    if (body == null) return null;

    ByteArrayInputStream bais = null;
    ObjectInputStream ois = null;
    Object obj = null;
   
    try {
      try {
        bais = new ByteArrayInputStream(body);
        ois = new ObjectInputStream(bais);
        obj = ois.readObject();
      } catch (ClassNotFoundException cnfexc) {
        // Could not build serialized object: reason could be linked to
        // class loaders hierarchy in an application server.
        class Specialized_OIS extends ObjectInputStream {
          Specialized_OIS(InputStream is) throws IOException {
            super(is);
          }

          protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
            String n = osc.getName();
            return Class.forName(n, false, Thread.currentThread().getContextClassLoader());
          }
        }

        bais = new ByteArrayInputStream(body);
        ois = new Specialized_OIS(bais);
        obj = ois.readObject();
      }
    } catch (Exception exc) {
      if (logger.isLoggable(BasicLevel.ERROR))
        logger.log(BasicLevel.ERROR, "ERROR: getObject()", exc);
      // Don't forget to rethrow the Exception
      throw exc;
    } finally {
      try {
        ois.close();
      } catch (Exception e) {}
      try {
        bais.close();
      } catch (Exception e) {}
    }

    return (Serializable) obj;
  }

  /**
   * Sets an AbstractAdminMessage as the body of the message.
   *
   * @exception IOException  In case of an error while setting the object.
   */
  public void setAdminMessage(AbstractAdminMessage adminMsg) throws IOException {
    type = Message.ADMIN;

    if (adminMsg == null) {
      body = null;
    } else {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      AbstractAdminMessage.write(adminMsg, baos);
      baos.flush();
      body = baos.toByteArray();
      baos.close();
    }
  }

  /**
   * Returns the AbstractAdminMessage body of the message.
   *
   * @exception IOException  In case of an error while getting the object.
   * @exception ClassNotFoundException  If the object class is unknown.
   */
  public AbstractAdminMessage getAdminMessage() {
    if (body == null) return null;

    ByteArrayInputStream bais = null;
    AbstractAdminMessage adminMsg = null;

    try {
     bais = new ByteArrayInputStream(body);
     adminMsg = AbstractAdminMessage.read(bais);
    } catch (Exception e) {
      if (logger.isLoggable(BasicLevel.ERROR))
        logger.log(BasicLevel.ERROR, "ERROR: getAdminMessage()", e);
    }
    return adminMsg;
  }

  public final String toString() {
    StringBuffer strbuf = new StringBuffer();
    toString(strbuf);
    return strbuf.toString();
  }

  public void toString(StringBuffer strbuf) {
    strbuf.append('(').append(super.toString());
    strbuf.append(",id=").append(id);
    strbuf.append(",type=").append(type);
    strbuf.append(",persistent=").append(persistent);
    strbuf.append(",priority=").append(priority);
    strbuf.append(",expiration=").append(expiration);
    strbuf.append(",timestamp=").append(timestamp);
    strbuf.append(",toId=").append(toId);
    strbuf.append(",replyToId=").append(replyToId);
    strbuf.append(",correlationId=").append(correlationId);
    strbuf.append(')');
  }

  /** Clones the message. */
  public Object clone() {
    try {
      Message clone = (Message) super.clone();
      if (body != null) {
        // AF: May be we can share the body as it should be RO.
        clone.body = new byte[body.length];
        System.arraycopy(body, 0, clone.body, 0, body.length);
      }
      if (properties != null) {
        clone.properties = (Properties) properties.clone();
      }
      return clone;
    } catch (CloneNotSupportedException cE) {
      // Should never happened!
      return null;
    }
  }

  public Hashtable soapCode() {
    Hashtable h = new Hashtable();
    // AF: TODO
    return h;
  }

  public static Message soapDecode(Hashtable h) {
    // AF: TODO
    return null;
  }

  private static final short typeFlag = 0x0001;
  private static final short replyToIdFlag = 0x0002;
  private static final short replyToTypeFlag = 0x0004;
  private static final short propertiesFlag = 0x0008;
  private static final short priorityFlag = 0x0010;
  private static final short expirationFlag = 0x0020;
  private static final short corrrelationIdFlag = 0x0040;
  private static final short deliveryCountFlag = 0x0080;
  private static final short jmsTypeFlag = 0x0100;
  private static final short redeliveredFlag = 0x0200;
  private static final short persistentFlag = 0x0400;

  /* ***** ***** ***** ***** *****
   * Streamable interface
   * ***** ***** ***** ***** ***** */

  /**
   *  The object implements the writeTo method to write its contents to
   * the output stream.
   *
   * @param os the stream to write the object to
   */
  public void writeTo(OutputStream os) throws IOException {
    writeHeaderTo(os);
    StreamUtil.writeTo(body, os);
  }

  public void writeHeaderTo(OutputStream os) throws IOException {
    StreamUtil.writeTo(id, os);
    StreamUtil.writeTo(toId, os);
    StreamUtil.writeTo(toType, os);
    StreamUtil.writeTo(timestamp, os);

    // One short is used to know which fields are set
    short s = 0;
    if (type != SIMPLE) { s |= typeFlag; }
    if (replyToId != null) { s |= replyToIdFlag; }
    if (replyToType != 0) { s |= replyToTypeFlag; }
    if (properties != null) { s |= propertiesFlag; }
    if (priority != DEFAULT_PRIORITY) { s |= priorityFlag; }
    if (expiration != 0) { s |= expirationFlag; }
    if (correlationId != null) { s |= corrrelationIdFlag; }
    if (deliveryCount != 0) { s |= deliveryCountFlag; }
    if (jmsType != null) { s |= jmsTypeFlag; }
    if (redelivered) { s |= redeliveredFlag; }
    if (persistent) { s |= persistentFlag; }
   
    StreamUtil.writeTo(s, os);
   
    if (type != SIMPLE) { StreamUtil.writeTo(type, os); }
    if (replyToId != null) { StreamUtil.writeTo(replyToId, os); }
    if (replyToType != 0) { StreamUtil.writeTo(replyToType, os); }
    if (properties != null) { StreamUtil.writeTo(properties, os); }
    if (priority != DEFAULT_PRIORITY) { StreamUtil.writeTo(priority, os); }
    if (expiration != 0) { StreamUtil.writeTo(expiration, os); }
    if (correlationId != null) { StreamUtil.writeTo(correlationId, os); }
    if (deliveryCount != 0) { StreamUtil.writeTo(deliveryCount, os); }
    if (jmsType != null) { StreamUtil.writeTo(jmsType, os); }

  }

  /**
   *  The object implements the readFrom method to restore its contents from
   * the input stream.
   *
   * @param is the stream to read data from in order to restore the object
   */
  public void readFrom(InputStream is) throws IOException {
    readHeaderFrom(is);
    body = StreamUtil.readByteArrayFrom(is);
  }

  public void readHeaderFrom(InputStream is) throws IOException {
    id = StreamUtil.readStringFrom(is);
    toId = StreamUtil.readStringFrom(is);
    toType = StreamUtil.readByteFrom(is);
    timestamp = StreamUtil.readLongFrom(is);
   
    short s = StreamUtil.readShortFrom(is);

    if ((s & typeFlag) != 0) { type = StreamUtil.readIntFrom(is); }
    if ((s & replyToIdFlag) != 0) { replyToId = StreamUtil.readStringFrom(is); }
    if ((s & replyToTypeFlag) != 0) { replyToType = StreamUtil.readByteFrom(is); }
    if ((s & propertiesFlag) != 0) { properties = StreamUtil.readPropertiesFrom(is); }
    if ((s & priorityFlag) != 0) { priority = StreamUtil.readIntFrom(is); }
    if ((s & expirationFlag) != 0) { expiration = StreamUtil.readLongFrom(is); }
    if ((s & corrrelationIdFlag) != 0) { correlationId = StreamUtil.readStringFrom(is); }
    if ((s & deliveryCountFlag) != 0) { deliveryCount = StreamUtil.readIntFrom(is); }
    if ((s & jmsTypeFlag) != 0) { jmsType = StreamUtil.readStringFrom(is); }
    redelivered = (s & redeliveredFlag) != 0;
    persistent = (s & persistentFlag) != 0;

  }

  /**
   *  this method allows to write to the output stream a vector of message.
   *
   * @param messages   the vector of messages
   * @param os     the stream to write the vector to
   */
  public static void writeVectorTo(Vector messages,
                                   OutputStream os) throws IOException {
    if (messages == null) {
      StreamUtil.writeTo(-1, os);
      if (logger.isLoggable(BasicLevel.DEBUG))
        logger.log(BasicLevel.DEBUG, "writeVectorTo: -1");
    } else {
      int size = messages.size();
      if (logger.isLoggable(BasicLevel.DEBUG))
        logger.log(BasicLevel.DEBUG, "writeVectorTo: " + size);
      StreamUtil.writeTo(size, os);
      for (int i=0; i<size; i++) {
        if (logger.isLoggable(BasicLevel.DEBUG))
          logger.log(BasicLevel.DEBUG, "writeVectorTo: msg#" + i);
        ((Message) messages.elementAt(i)).writeTo(os);
      }
    }
  }

  /**
   *  this method allows to read from the input stream a vector of messages.
   *
   * @param is   the stream to read data from in order to restore the vector
   * @return  the vector of messages
   */
  public static Vector readVectorFrom(InputStream is) throws IOException {
    int size = StreamUtil.readIntFrom(is);
   
    if (logger.isLoggable(BasicLevel.DEBUG))
      logger.log(BasicLevel.DEBUG, "readVectorFrom: " + size);
   
    if (size == -1) return null;

    Vector messages = new Vector(size);
    for (int i=0; i<size; i++) {
      if (logger.isLoggable(BasicLevel.DEBUG))
        logger.log(BasicLevel.DEBUG, "readVectorFrom: msg#" + i);
      Message msg = new Message();
      msg.readFrom(is);
      messages.addElement(msg);
    }
    return messages;
  }

//   /** ***** ***** ***** ***** ***** ***** ***** *****
//    * Externalizable interface
//    * ***** ***** ***** ***** ***** ***** ***** ***** */
 
//   public void writeExternal(ObjectOutput out) throws IOException {
//     writeTo(out);
//   }

//   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//     readFrom(in);
//   }

  /** ***** ***** ***** ***** ***** ***** ***** *****
   * Serializable interface
   * ***** ***** ***** ***** ***** ***** ***** ***** */

  private void writeObject(ObjectOutputStream out) throws IOException {
    writeTo(out);
  }

  /**
   * @throws ClassNotFoundException 
   */
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    readFrom(in);
  }
}
TOP

Related Classes of org.objectweb.joram.shared.messages.Specialized_OIS

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.