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

org.coos.javaframe.ActorAddress Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/**
 * 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;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

import org.coos.util.serialize.AFClassLoader;
import org.coos.util.serialize.AFSerializer;
import org.coos.util.serialize.StringHelper;
import org.coos.util.serialize.VectorHelper;

/**
 * The unique address of an actor. It contains a field actorId that is the
 * unique text string representing a state machine instance of type actorType.
 * All messages used are sub types of this class.
 * 
 * @author Knut Eilif Husa, Tellu AS
 * @author Geir melby, Tellu AS
 * @author Dag Belsnes
 */
public class ActorAddress implements AFSerializer {
	public static final String ROLE_TYPE = "roleType";
	public static final String ROLE_ID = "roleId";
	private String actorDomain; // actor schedulerData name
	private String actorID; // actor instance name
	private String actorType; // type of actor
	private String actorPort; // specific port of actor
	private String actorIP; // IP address for the actor
	private String actorIPPort; // IP port number for the actor
	private String proxyAddress; // IP port number for the actor
	private byte[] replyStack; // Adds posibility to store a replystack.
	private String protocol;

	/**
	 * Default constructor
	 */
	public ActorAddress() {
		this.actorDomain = null;
		this.actorID = null;
		this.actorType = null;
		this.actorPort = null;
		this.actorIP = "localhost";
		this.actorIPPort = null;
		this.protocol = "tcp";
	}

	public ActorAddress(String actorAddress) {

		// check schedulerData first
		this.actorDomain = getActorDomain(actorAddress);
		int indexType = actorAddress.indexOf('@');
		int indexPort = actorAddress.indexOf(':');

		if (indexType == -1) {
			indexType = 0;
		}

		if (indexPort == -1) {
			indexPort = indexType;
		}

		this.actorID = actorAddress.substring(0, indexPort);

		if (actorID.equals("")) {
			actorID = null;
		}

		// check if the address contains a "@"
		if (actorAddress.indexOf('@') == -1) {
			this.actorType = actorAddress.substring(indexType);
		} else {
			this.actorType = actorAddress.substring(indexType + 1);
		}

		if (actorType.equals("")) {
			actorType = null;
		}

		if (indexPort < indexType) {
			this.actorPort = actorAddress.substring(indexPort + 1, indexType);
		}

		if ((actorPort != null) && actorPort.equals("")) {
			actorPort = null;
		}

		this.actorIP = "localhost";
		this.actorIPPort = null;
		this.protocol = "udp";
	}

	private String getActorDomain(String actorId) {
		if (!actorId.startsWith("/")) {
			int i = actorId.indexOf("/", 1);
			if (i != -1) {
				// valid schedulerData name
				// to be able to handle hierarchical schedulerData names and
				// role state machines we substitute . with |
				return actorId.substring(0, i).replace('.', '|');
				// actorAddress = actorAddress.substring(i);
			}
		}
		return null;
	}

	/**
	 * The constructor formes the Address as a concatenation of the two input
	 * parameters
	 * 
	 * @param actorID
	 *            The ID of an actor
	 * @param actorType
	 *            The Type of an actor
	 */
	public ActorAddress(String actorID, String actorType) {
		this.actorDomain = getActorDomain(actorID);
		this.actorID = actorID;
		this.actorType = actorType;
		this.actorPort = null;
		this.actorIP = "localhost";
		this.actorIPPort = null;
		this.protocol = "tcp";
	}

	/**
	 * The constructor formes the Address as a concatenation of the two input
	 * parameters
	 * 
	 * @param actorID
	 *            The ID of an actor
	 * @param actorType
	 *            The Type of an actor
	 */
	public ActorAddress(String actorID, String actorType, String actorPort) {
		this(actorID, actorType);
		this.actorPort = actorPort;
	}

	/**
	 * Creates an ActorAddress with a known IP address
	 * 
	 * @param actorID
	 *            the ID of an actor.
	 * @param actorType
	 *            the Type of an actor.
	 * @param actorIpAddr
	 *            is the IP-address of the receiver of the message.
	 * @param actorIPPort
	 *            is the IP-port numeral.
	 */
	public ActorAddress(String actorID, String actorType, String actorIpAddr, String actorIPPort, String protocol) {
		this(actorID, actorType);
		this.actorIPPort = actorIPPort;
		this.protocol = protocol;

		if (actorIpAddr == null) {
			this.actorIP = "localhost";
		} else {
			this.actorIP = actorIpAddr;
		}
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	/**
	 * Creates an ActorAddress with a known IP-address and a given Port name
	 * 
	 * @param actorID
	 *            the ID of an actor.
	 * @param actorType
	 *            the Type of an actor.
	 * @param actorPort
	 *            Port name of the actor.
	 * @param actorIpAddr
	 *            is the IP-address of the receiver of the message.
	 * @param actorIPPort
	 *            is the IP-port numeral.
	 */
	public ActorAddress(String actorID, String actorType, String actorPort, String actorIpAddr, String actorIPPort,
			String protocol) {
		this(actorID, actorType, actorIpAddr, actorIPPort, protocol);
		this.actorPort = actorPort;
	}

	/**
	 * Create an ActorAddress from a DataInputStream.
	 * 
	 * @param din
	 *            InputStream to read.
	 */
	public ActorAddress(DataInputStream din) throws IOException {
		readInput(din, null);
	}

	/**
	 * Store the replyStack in the ActorAddress.
	 */
	public void setReplyStack(Vector replyStack) throws IOException {
		this.replyStack = VectorHelper.persist(replyStack);
	}

	/**
	 * Get the stored replyStack in the ActorAddress if it exist.
	 */
	public Vector getReplyStack() {
		if (!hasReplyStack()) {
			return null;
		}

		ByteArrayInputStream bin = new ByteArrayInputStream(replyStack);
		DataInputStream din = new DataInputStream(bin);

		try {
			return VectorHelper.resurrect(din, null);
		} catch (IOException e) {
			return null;
		}
	}

	public boolean hasReplyStack() {
		return ((replyStack != null) && (replyStack.length != 0));
	}

	public String getActorDomain() {
		return actorDomain;
	}

	public void setActorDomain(String actorDomain) {
		// to be able to handle hierarchical schedulerData names and role state
		// machines we substitute . with |
		if (actorDomain != null) {
			this.actorDomain = actorDomain.replace('.', '|');
		} else {
			this.actorDomain = null;
		}
	}

	public String getActorID() {
		return actorID;
	}

	public void setActorID(String actorID) {
		this.actorID = actorID;
		this.actorDomain = getActorDomain(actorID);
	}

	public String getActorType() {
		return actorType;
	}

	public void setActorType(String actorType) {
		this.actorType = actorType;
	}

	public String getActorPort() {
		return actorPort;
	}

	public void setActorPort(String actorPort) {
		this.actorPort = actorPort;
	}

	public boolean hasActorPort() {
		return (actorPort != null);
	}

	public String getActorIP() {
		return actorIP;
	}

	public void setActorIP(String actorIP) {
		this.actorIP = actorIP;
	}

	public String getActorIPPort() {
		return actorIPPort;
	}

	public void setActorIPPort(String actorIPPort) {
		this.actorIPPort = actorIPPort;
	}

	public ActorAddress getProxyAddress() {
		if (proxyAddress != null) {
			return new ActorAddress(proxyAddress);
		}
		return null;
	}

	public void setProxyAddress(ActorAddress proxyAddress) {
		this.proxyAddress = proxyAddress.key();
	}

	/**
	 * Check if the ActorAddress is valid.
	 * 
	 * @return true if ActorAddress is valid.
	 */
	public boolean isValied() {
		// TODO: Check if modification is acceptable, geir, 04.04.05
		if ((getActorID() != null /* && (!getActorID().equals("")) */)
				&& ((getActorType() != null) && !getActorType().equals(""))) {
			return true;
		}

		return false;
	}

	/**
	 * Returns a key that is an unique reference to an actor instance
	 * 
	 * @return Key of unique reference to an actor instance.
	 */
	public String key() {
		if (actorPort == null) {
			return actorID + "@" + actorType;
		}

		// Key with port
		return actorID + ":" + actorPort + "@" + actorType;
	}

	/**
	 * Returns a key that is an unique reference to an actor instance
	 * 
	 * @return Key of unique reference to an actor instance.
	 */
	public String keyWithOutPortAndRole() {
		int index = actorID.indexOf(".");
		String id = actorID;
		if (index != -1) {
			id = actorID.substring(0, index);
		} else {

		}
		return id + "@" + actorType;
	}

	/**
	 * Returns a key that is an unique reference to an actor instance
	 * 
	 * @return Key of unique reference to an actor instance.
	 */
	public String keyWithOutPort() {
		return actorID + "@" + actorType;
	}

	public String printActorDomain() {
		return toString();
	}

	/**
	 * printIpAddress returns a String representation of the IP address and port
	 * num.
	 * 
	 * @return string representation.
	 */
	public String printIpAddress() {
		String s = "";

		if (actorIP != null) {
			s = actorIP + ":";
		}

		if (actorIPPort != null) {
			s = s + actorIPPort;
		}

		return s;
	}

	public boolean isIpAddressSet() {
		return (!((actorIP == null) || actorIP.equals("localhost")));
	}

	/**
	 * Check wether a given ActorAddress refers to an instance which is a inner
	 * part of this ActorAddress.
	 * 
	 * @param aa
	 *            ActorAddress to check.
	 * @return boolean indicating wether it is an inner ActorAddress.
	 */
	public boolean isInnerActor(ActorAddress aa) {
		int contextStop = -1;

		if (this.actorPort != null) {
			// Has port in address.
			contextStop = key().lastIndexOf(':');
		} else {
			// no Port in address, last context is
			// the Type delimiter.
			contextStop = key().lastIndexOf('@');
		}

		// Check the key (with IP info) with the context information
		return aa.key().startsWith(key().substring(0, contextStop));
	}

	/**
	 * This function must implement the serialization of the object.
	 * 
	 * @return a byte array with the objects data
	 * @throws java.io.IOException
	 */
	public byte[] serialize() throws IOException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(bout);
		dout.write(StringHelper.persist(this.actorDomain));
		dout.write(StringHelper.persist(this.actorID));
		dout.write(StringHelper.persist(this.actorType));
		dout.write(StringHelper.persist(this.actorIP));
		dout.write(StringHelper.persist(this.actorIPPort));
		dout.write(StringHelper.persist(this.actorPort));
		dout.write(StringHelper.persist(this.proxyAddress));

		dout.write(StringHelper.persist(protocol));
		dout.flush();

		return bout.toByteArray();
	}

	/**
	 * Use this function for resurrection of the object
	 * 
	 * @param data
	 *            The serialized data containing the object data
	 * @throws java.io.IOException
	 */
	public ByteArrayInputStream deSerialize(byte[] data, AFClassLoader cl) throws IOException {
		ByteArrayInputStream bin = new ByteArrayInputStream(data);
		DataInputStream din = new DataInputStream(bin);
		readInput(din, cl);
		return bin;
	}

	private void readInput(DataInputStream din, AFClassLoader cl) throws IOException {
		actorDomain = StringHelper.resurrect(din);
		actorID = StringHelper.resurrect(din);
		actorType = StringHelper.resurrect(din);
		actorIP = StringHelper.resurrect(din);
		actorIPPort = StringHelper.resurrect(din);
		actorPort = StringHelper.resurrect(din);
		proxyAddress = StringHelper.resurrect(din);

		protocol = StringHelper.resurrect(din);

	}

	/**
	 * Compare to other Object without caring about the context information.
	 * 
	 * @param obj
	 */
	public boolean equalsIgnoreContext(Object obj) {
		if (obj instanceof ActorAddress) {
			ActorAddress aa = (ActorAddress) obj;

			if ((aa.getActorID() == null) || (aa.getActorType() == null)) {
				return false;
			}

			if (this.actorID.endsWith(aa.getActorID()) && aa.getActorType().equals(this.actorType)
					&& aa.getActorIP().equals(this.actorIP)) {
				if ((hasActorPort() && aa.hasActorPort() && actorPort.equals(aa.actorPort))
						|| (!hasActorPort() && !aa.hasActorPort())) {
					return true;
				}

				return false;
			}

			return false;
		} else if (obj instanceof String) {
			if (this.actorID.endsWith((String) obj)) {
				return true;
			}

			return false;
		}

		return super.equals(obj);
	}

	/**
	 * toString returns a String representation of the address
	 * 
	 * @return String representation
	 */
	public String toString() {
		String s = "";

		if (isIpAddressSet()) {
			s = printIpAddress() + "/";
		}
		/*
		 * if (actorDomain != null) return "'" + actorDomain + "'" + s + key();
		 * else
		 */
		return s + key();
	}

	/**
	 * equals is redefined to compare two ActorAddresses based on actorID,
	 * actorType and actorPort
	 * 
	 * @param obj
	 *            The ActorAddress to compare
	 * @return true if same actorID and actorType
	 */
	public boolean equals(Object obj) {
		if (obj instanceof ActorAddress) {
			ActorAddress aa = (ActorAddress) obj;
			boolean port = (getActorIPPort() == null) && (this.actorIPPort == null);
			boolean ip = (getActorIP() == null) && (this.actorIP == null);
			boolean id = (aa.actorID != null) && (this.actorID != null) && aa.getActorID().equals(this.actorID);
			boolean type = (aa.actorType != null) && (this.actorType != null) && aa.actorID.equals(this.actorID);

			if (id && type) // && (ip || ((aa.actorIP != null) && (actorIP !=
			// null) && actorIP.equals(this.actorIP))) && (port
			// || ((aa.actorIPPort != null) && (actorIPPort !=
			// null) && actorIPPort.equals(this.actorIPPort))))
			{
				if ((hasActorPort() && aa.hasActorPort() && actorPort.equals(aa.actorPort))
						|| (!hasActorPort() && !aa.hasActorPort())) {
					// Equal if domains are equal or one of the domains is null.
					// Actordomain is null at creationtime.
					if ((aa.actorDomain == null || this.actorDomain == null)
							|| (aa.actorDomain.equals(this.actorDomain))) {
						return true;
					}
				}
			}

			return false;
		} else if (obj instanceof String) {
			if (((String) obj).equals(this.actorID)) {
				return true;
			}

			return false;
		}

		return super.equals(obj);
	}

	public Object clone() {
		try {
			ActorAddress clonedAA = new ActorAddress();
			clonedAA.deSerialize(serialize(), null);

			return clonedAA;
		} catch (IOException e) {
			return null;
		}
	}

	/**
	 * The hashcode of ActorAddress is a sum of the actorID and actorType hash
	 * codes
	 * 
	 * @return hash
	 */
	public int hashCode() {
		if ((actorID == null) || (actorType == null)) {
			return 0;
		} else {
			int hash = actorID.hashCode() + 31 * actorType.hashCode(); // +
			// actorIP.hashCode();
			if (actorDomain != null)
				hash += 31 * 31 * actorDomain.hashCode();
			return hash;
		}
	}

	public String getProtocol() {
		return protocol;
	}

	/**
	 * Gets the actor id without the actor domain address
	 * 
	 * @return the actor id without actor domain address ex: "/actor"
	 */
	public String getActorIdWithoutDomain() {

		if (!actorID.startsWith("/")) {
			int index = actorID.indexOf(".");
			String id = actorID;
			if (index != -1) {
				id = actorID.substring(0, index);
			}
			int i = id.indexOf("/", 1);
			if (i != -1) {
				return id.substring(i);
			}
		}
		return actorID;
	}

	public String getPath() {
		StringBuffer s = new StringBuffer();
		if (actorDomain != null) {
			s.append(actorDomain);
		}

		if (actorID.length() > 0 && actorID.charAt(0) == '/') {
			if (actorID != null) {
				s.append(actorID);
			}

			if (actorPort != null) {
				s.append(":" + actorPort);
			}

			if (actorType != null) {
				s.append("@" + actorType);
			}
		} else {
			System.out.println();
		}
		return s.toString();
	}

	public static void main(String[] args) {
		ActorAddress aa = new ActorAddress("a/b@B");
		System.out.println("ActorAddress: " + aa.getActorIdWithoutDomain());
		aa = new ActorAddress("/b@B");
		System.out.println("ActorAddress: " + aa.getActorIdWithoutDomain());
		aa = new ActorAddress("a/b.role@B");
		System.out.println("ActorAddress: " + aa.getActorIdWithoutDomain());

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy