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

org.coos.javaframe.messages.RouterMsg Maven / Gradle / Ivy

/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.javaframe.messages;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.coos.actorframe.messages.AFConstants;
import org.coos.javaframe.ActorAddress;
import org.coos.javaframe.Logger;
import org.coos.javaframe.LoggerFactory;
import org.coos.javaframe.TraceConstants;
import org.coos.util.serialize.AFClassLoader;
import org.coos.util.serialize.StringHelper;

/**
 * 
 * @author Geir Melby, Tellu AS
 */
public class RouterMsg extends Message {
	public byte typeOfMessage;
	public ActorAddress receiver;
	public ActorAddress sender;
	public int timeToLive;
	public String className;
	public int msgLength;
	public byte[] data;
	public boolean receivingRoutingInfo;

	public static final byte ROUTER_MESSAGE = 1;
	public static final byte ACTOR_MESSAGE = 2;
	public static final byte TEST_MESSAGE = 3;
	public static final byte OPTIMIZED_MESSAGE = 4;
	public static final byte AFPROPERTY_MESSAGE = 5;
	public static final byte CLDC_MESSAGE = 6;

	public static final int NORMAL_TIME_TO_LIVE = 10;
	private static String AFPROPERTY_CLASS_NAME = "org.coos.javaframe.messages.AFPropertyMsg";

	private Logger log;

	public RouterMsg() {
		log = LoggerFactory.getLogger(this.getClass().getName());
	}

	public RouterMsg(ActorMsg msg) throws IOException {
		initClass(msg, NORMAL_TIME_TO_LIVE);
	}

	public RouterMsg(ActorMsg msg, int timeToLive) throws IOException {
		initClass(msg, timeToLive);
	}

	private void initClass(ActorMsg msg, int timeToLive) throws IOException {
		if (msg instanceof RouterManagementMsg) {
			this.typeOfMessage = ROUTER_MESSAGE;
		} else if (msg instanceof OptimizedMsg) {
			this.typeOfMessage = OPTIMIZED_MESSAGE;
			this.className = "OptimizedMsg";
		} else if (msg instanceof AFPropertyMsg) {
			this.typeOfMessage = AFPROPERTY_MESSAGE;
			this.className = AFPROPERTY_CLASS_NAME;
		} else {
			this.typeOfMessage = ACTOR_MESSAGE;
		}
		this.receiver = msg.getReceiverRole();
		this.sender = msg.getSenderRole();
		this.timeToLive = timeToLive;

		this.data = msg.serialize();
		this.msgLength = data.length;

		// write the classname
		if (this.className == null) {
			this.className = msg.getClass().getName();
		}
	}

	public RouterMsg(byte[] indata) throws IOException {
		this(new ByteArrayInputStream(indata));
	}

	public RouterMsg(InputStream is) throws IOException {
		DataInputStream din = new DataInputStream(is);

		typeOfMessage = din.readByte();
		if (typeOfMessage == OPTIMIZED_MESSAGE) {
			String actorId = din.readUTF();
			String actorType = din.readUTF();
			sender = new ActorAddress(actorId, actorType);
			receiver = OptimizedMsg.sendAddress;
			timeToLive = 20;
			// dataIsCompressed = false;
			// receivingRoutingInfo = false;
			msgLength = din.readInt();
			this.data = new byte[msgLength];
			din.readFully(this.data, 0, msgLength);
			className = "OptimizedMsg";
		} else if (typeOfMessage == TEST_MESSAGE) {
			// transportProtocol = "-";
			sender = null;
			receiver = null;
			// timeToLive = 0;
			// dataIsCompressed = false;
			// receivingRoutingInfo = false;
		} else if (typeOfMessage == AFPROPERTY_MESSAGE) {
			receiver = ActorAddressHelper.resurrect(din);
			sender = ActorAddressHelper.resurrect(din);
			timeToLive = din.readInt();
			this.receivingRoutingInfo = din.readBoolean();
			msgLength = din.readInt();
			this.data = new byte[msgLength];
			din.readFully(this.data, 0, msgLength);
			className = AFPROPERTY_CLASS_NAME;
		} else if (typeOfMessage == CLDC_MESSAGE) {
			timeToLive = NORMAL_TIME_TO_LIVE;
			this.receivingRoutingInfo = false;
			msgLength = din.readInt();
			this.data = new byte[msgLength];
			din.readFully(this.data, 0, msgLength);
			className = AFPROPERTY_CLASS_NAME;
			ActorAddress[] header = readHeader(data);
			receiver = header[0];
			sender = header[1];

		} else if (typeOfMessage == ROUTER_MESSAGE || typeOfMessage == ACTOR_MESSAGE) {
			receiver = ActorAddressHelper.resurrect(din);
			sender = ActorAddressHelper.resurrect(din);
			timeToLive = din.readInt();
			className = StringHelper.resurrect(din);
			this.receivingRoutingInfo = din.readBoolean();
			msgLength = din.readInt();
			this.data = new byte[msgLength];
			din.readFully(this.data, 0, msgLength);
		}
		// din.close();
	}

	/**
	 * Reads the reciever and sender address of the sesialized actor message
	 * 
	 * @param data
	 *            is the payload of the router message (Actor message)
	 * @return actor addresses [recceiver, sender]
	 * @throws IOException
	 */
	private ActorAddress[] readHeader(byte[] data) throws IOException {
		ByteArrayInputStream bin = new ByteArrayInputStream(data);
		DataInputStream din = new DataInputStream(bin);
		return new ActorAddress[] { ActorAddressHelper.resurrect(din), ActorAddressHelper.resurrect(din) };
	}

	/**
	 * Creates a new actor message out of the payload of the RouterMsg. The type
	 * of message to be created is based on the class name property of the
	 * router message.
	 * 
	 * @return the new message
	 * @throws IOException
	 */
	public ActorMsg deSerializeMessage() throws IOException {
		// ActorMsg msg = createActorMsgClass(className);
		return deSerializeMessage(null);
	}

	/**
	 * Creates a new actor message out of the payload of the RouterMsg. The type
	 * of message to be created is based on the class name property of the
	 * router message.
	 * 
	 * @return the new message
	 * @throws IOException
	 */
	public ActorMsg deSerializeMessage(AFClassLoader loader) throws IOException {
		ActorMsg msg;
		try {
			if (typeOfMessage == OPTIMIZED_MESSAGE) {
				// supports an optimized version of the protocol
				msg = new OptimizedMsg();
				className = "OptimizedMsg";

				msg.setReceiverRole(receiver);
				msg.setSenderRole(sender);
			} else if (typeOfMessage == AFPROPERTY_MESSAGE) {
				msg = new AFPropertyMsg();
				updatePropMsg((AFPropertyMsg) msg);
			} else if (typeOfMessage == CLDC_MESSAGE) {
				msg = new AFPropertyMsg();
			} else {
				Class cl;
				if (loader == null) {
					cl = Class.forName(className);
				} else {
					cl = loader.loadClass(className);
				}
				msg = (ActorMsg) cl.newInstance();
			}
			// The message body / payload of the router message is deserilized
			// to an actor message.

			msg.deSerialize(data, loader);
			// update addressing info
			// msg.setReceiverRole(receiver);
			// msg.setSenderRole(senderAddress);
			return msg;
		} catch (ClassNotFoundException e) {
			log.log(TraceConstants.tlError, TraceConstants.tcSystem,
					"RouterMsg.deSerializeMessage:Class name for the message not found: " + className);
			return null;
		} catch (IllegalAccessException e) {
			log.log(TraceConstants.tlError, TraceConstants.tcSystem,
					"RouterMsg.deSerializeMessage:IllegalAccessException occured: " + e);
			return null;
		} catch (InstantiationException e) {
			log.log(TraceConstants.tlError, TraceConstants.tcSystem,
					"RouterMsg.deSerializeMessage:InstantiationException occured: " + e);
			return null;
		}
	}

	/**
	 * This is special for the two ActorFrame protocoll messages "RoleConfirm"
	 * and "RolePlay". Both messages contains a RoleRequest message that has to
	 * be updated with correct IP-addresses such as the the receiving actor can
	 * use this RoleRequest message in his respons to the requesting actor
	 * 
	 * @param pm
	 *            is the actor property message
	 * @return a property message updated with correct IP-settings
	 */
	public AFPropertyMsg updatePropMsg(AFPropertyMsg pm) {
		if (pm.equals(AFConstants.ROLE_PLAY_MSG) || pm.equals(AFConstants.ROLE_CONFIRM_MSG)) {
			AFPropertyMsg rrm = (AFPropertyMsg) pm.getProperty("rrm");
			if (!rrm.getSenderRole().isIpAddressSet()) {
				rrm.getSenderRole().setActorIP(pm.getSenderRole().getActorIP());
				rrm.getSenderRole().setActorIPPort(pm.getSenderRole().getActorIPPort());
				rrm.getSenderRole().setProtocol(pm.getSenderRole().getProtocol());
			}
		}

		return pm;
	}

	public byte[] serialize() throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(out);
		dout.writeByte(typeOfMessage);
		if (typeOfMessage == ROUTER_MESSAGE || typeOfMessage == ACTOR_MESSAGE) {
			dout.write(ActorAddressHelper.persist(receiver));
			dout.write(ActorAddressHelper.persist(sender));
			dout.writeInt(timeToLive);
			dout.write(StringHelper.persist(className));
			dout.writeBoolean(this.receivingRoutingInfo);
			dout.writeInt(msgLength);
			dout.write(data);
		} else if (typeOfMessage == AFPROPERTY_MESSAGE) {
			dout.write(ActorAddressHelper.persist(receiver));
			dout.write(ActorAddressHelper.persist(sender));
			dout.writeInt(timeToLive);
			dout.writeBoolean(this.receivingRoutingInfo);
			dout.writeInt(msgLength);
			dout.write(data);
		} else if (typeOfMessage == CLDC_MESSAGE) {
			dout.writeInt(msgLength);
			dout.write(data);
		} else if (typeOfMessage == OPTIMIZED_MESSAGE) {
			dout.writeUTF(sender.getActorID());
			dout.writeUTF(sender.getActorType());
			dout.writeInt(msgLength);
			dout.write(data);
		} else if (typeOfMessage == TEST_MESSAGE) {
			// no more data is nessarry
		}
		dout.close();
		out.close();
		return out.toByteArray();
	}

	public byte getTypeOfMessage() {
		return typeOfMessage;
	}

	public void setTypeOfMessage(byte typeOfMessage) {
		this.typeOfMessage = typeOfMessage;
	}

	public ActorAddress getReceiver() {
		return receiver;
	}

	public ActorAddress getSender() {
		return sender;
	}

	public int getTimeToLive() {
		return timeToLive;
	}

	public void setReceiver(ActorAddress receiver) {
		this.receiver = receiver;
	}

	public void setSender(ActorAddress sender) {
		this.sender = sender;
	}

	public void setTimeToLive(int timeToLive) {
		this.timeToLive = timeToLive;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public boolean isReceivingRoutingInfo() {
		return receivingRoutingInfo;
	}

	public void setReceivingRoutingInfo(boolean receivingRoutingInfo) {
		this.receivingRoutingInfo = receivingRoutingInfo;
	}

	public String messageContent() {
		StringBuffer sb = new StringBuffer("RouterMsg:");
		sb.append(" ClassName: " + className);
		sb.append(" MsgLength " + msgLength);
		sb.append(" TypeOfMessage:" + typeOfMessage);
		sb.append(" Receiver: " + receiver);
		sb.append(" Sender:" + sender);
		sb.append(" ReceivingRoutingInfo: " + receivingRoutingInfo);
		return sb.toString();
	}

	public String toString() {
		return "RouterMsg type:" + typeOfMessage;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy