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

org.coos.messaging.impl.DefaultEndpoint 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.messaging.impl;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.coos.messaging.AsyncCallback;
import org.coos.messaging.ConnectingException;
import org.coos.messaging.Consumer;
import org.coos.messaging.Endpoint;
import org.coos.messaging.EndpointException;
import org.coos.messaging.Exchange;
import org.coos.messaging.ExchangePattern;
import org.coos.messaging.Link;
import org.coos.messaging.Message;
import org.coos.messaging.Notification;
import org.coos.messaging.Plugin;
import org.coos.messaging.Processor;
import org.coos.messaging.ProcessorException;
import org.coos.messaging.Producer;
import org.coos.messaging.Service;
import org.coos.messaging.SubscriptionFilter;
import org.coos.messaging.util.ExecutorService;
import org.coos.messaging.util.Executors;
import org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
import org.coos.messaging.util.URIHelper;
import org.coos.messaging.util.URIProtocolHelper;
import org.coos.messaging.util.UuidGenerator;
import org.coos.messaging.util.UuidHelper;
import org.coos.module.ACConstants;
import org.coos.module.ACMessageFactory;
import org.coos.module.CommonConstants;
import org.coos.module.EdgeLCMMessageFactory;
import org.coos.module.EdgeMessageProperties;
import org.coos.module.LCMEdgeMessageFactory;

/**
 * @author Knut Eilif Husa, Tellu AS
 * @author anders
 */
public abstract class DefaultEndpoint extends DefaultProcessor implements Endpoint {

	private String uri;
	private String endpointUuid;
	private Plugin plugin;
	private Vector aliases = new Vector();
	private Hashtable outLinks = new Hashtable();
	private Vector services = new Vector();
	private Hashtable exchanges = new Hashtable();
	private Hashtable callbacks = new Hashtable();
	private UuidGenerator uuidGenerator = new UuidGenerator();
	private int maxPoolSize = DEFAULT_MAX_POOL_SIZE;
	protected ExecutorService threadPool;
	private long timeout;
	protected Vector deferQueue = new Vector();
	protected Log log = LogFactory.getLog(this.getClass().getName());


	private String securityToken;
	private String endpointState = STATE_READY;
	private Hashtable childStates = new Hashtable();

	protected DefaultEndpoint() {
	}

	public DefaultEndpoint(String uri, Processor processor) {
		// This is for test purposes since this constructor only is called in
		// tests
		this.uri = uri;
		outLinks.put("coos", processor);
		threadPool = Executors.newThreadPool(2);
		uuidGenerator = new UuidGenerator("xId-" + ((getName() == null) ? getEndpointUuid() : getName()));
		setEndpointState(Endpoint.STATE_RUNNING);

	}

	public void setName(String name) {
		if (name != null && !UuidHelper.isUuid(name)) {
			aliases.addElement(name);
		}
		super.setName(name);
	}

	public Consumer createConsumer() {
		// TODO Auto-generated method stub
		return null;
	}

	public Producer createProducer() {
		// TODO Auto-generated method stub
		return null;
	}

	public String getEndpointUuid() {
		return endpointUuid;
	}

	public void setEndpointUuid(String endpointUuid) {
		this.endpointUuid = endpointUuid;
		log.putMDC("UUID", endpointUuid);
	}

	public String getEndpointState() {
		return endpointState;
	}

	public void setEndpointState(String endpointState) {
		this.endpointState = endpointState;
		if (isStateRunning()) {
			for (int i = 0; i < deferQueue.size(); i++) {
				Message message = (Message) deferQueue.elementAt(i);
				processMessage(message);
			}
			deferQueue.removeAllElements();
		}
	}

	public void setChildEndpointState(String childName, String state) {
		childStates.put(childName, state);
	}

	public String getChildEndpointState(String childName) {
		return (String) childStates.get(childName);
	}

	public void setProperties(Hashtable properties) {
		this.properties = properties;
		String timoutStr = (String) properties.get(PROP_EXCHANGE_TIMEOUT);
		if (timoutStr != null) {
			timeout = Long.parseLong(timoutStr);
		} else {
			timeout = DEFAULT_TIMEOUT;
		}

		String maxPoolSizeStr = (String) properties.get(PROP_MAX_POOL_SIZE);
		if (maxPoolSizeStr != null) {
			maxPoolSize = Integer.parseInt(maxPoolSizeStr);
		} else {
			maxPoolSize = DEFAULT_MAX_POOL_SIZE;
		}
	}

	public String getSecurityToken() {
		return securityToken;
	}

	public Exchange createExchange() {
		Exchange exchange = new DefaultExchange(new ExchangePattern(ExchangePattern.OutIn));		
		return exchange;
	}

	public Exchange createExchange(ExchangePattern pattern) {
		Exchange exchange = new DefaultExchange(pattern);		
		return exchange;
	}

	public String getEndpointUri() {
		return uri;
	}

	public void setEndpointUri(String endpointUri) {
		this.uri = endpointUri;
		log.putMDC("URI", endpointUri);
	}

	public String createUuid() {
		return uuidGenerator.generateId();
	}

	/**
	 * Method that registers endpoint into lifecycle manager.
	 * 
	 * @throws EndpointException
	 *             if registration failes
	 */
	private void registerLCM() throws EndpointException {
		// registration to LCM

		boolean failIfError = false;

		String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);
		if (lcmRegReq != null) {
			if (lcmRegReq.equals("true")) {
				failIfError = true;
			} else
				return; // Skip registration
		}
		log.info("Registering endpoint: " + uri + " to LifeCycleManager.");
		Message regMsg = LCMEdgeMessageFactory.createRegisterEndpointMessage(endpointState, getChildStates(),
				PROP_LCM_POLLING_INTERVAL);
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			if (failIfError)
				throw new EndpointException("Registration to LifeCycleManager failed due to :"
						+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		} else {
			Message reply = ex.getInBoundMessage();
			String signalName = reply.getHeader(Message.MESSAGE_NAME);
			if (signalName.equals(CommonConstants.REPLY_NACK)) {
				if (failIfError)
					throw new EndpointException("Registration to lifecycle manager failed");
				// else
				// log.
			}
		}
	}

	private void unRegisterLCM() throws EndpointException {
		// unregistration to LCM
		String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);
		if (lcmRegReq == null || !lcmRegReq.equals("true")) {
			return;
		}
		log.info("UnRegistering endpoint: " + uri + " from LifeCycleManager.");
		Message regMsg = LCMEdgeMessageFactory.createUnregisterEndpointMessage();
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			throw new EndpointException("Endpoint: " + getEndpointUri()
					+ ", Unregistration to LifeCycleManager failed due to: "
					+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		}
		Message reply = ex.getInBoundMessage();
		String signalName = reply.getHeader(Message.MESSAGE_NAME);
		if (signalName.equals(CommonConstants.REPLY_NACK)) {
			throw new EndpointException("Endpoint: " + getEndpointUri()
					+ ", Unregistration to lifecycle manager failed");
		}

	}

	/**
	 * Method that reports state to LCM
	 * 
	 * @param childAddress
	 * 
	 * @throws EndpointException
	 */
	private void replyChildState(String childAddress) throws EndpointException {
		log.info("Reporting state: " + endpointState + " to LifeCycleManager.");
		Message regMsg = new DefaultMessage(EdgeLCMMessageFactory.EDGE_REQUEST_CHILD_STATE);
		Hashtable msgProps = new Hashtable();
		msgProps.put(EdgeMessageProperties.EDGE_PROP_STATE, getChildStates().get(childAddress));
		msgProps.put(EdgeMessageProperties.EDGE_PROP_CHILD_NAME, childAddress);
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			throw new EndpointException("Child State reply to LifeCycleManager failed due to :"
					+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		}
		Message reply = ex.getInBoundMessage();
		String signalName = reply.getHeader(Message.MESSAGE_NAME);
		if (signalName.equals(CommonConstants.REPLY_NACK)) {
			throw new EndpointException("Child State reply to lifecycle manager failed");
		}
	}

	/**
	 * Method that reports state to LCM
	 * 
	 * @throws EndpointException
	 */
	private void replyState() throws EndpointException {
		log.info("Reporting state: " + endpointState + " to LifeCycleManager.");
		Message regMsg = new DefaultMessage(EdgeLCMMessageFactory.EDGE_REQUEST_STATE);
		Hashtable msgProps = new Hashtable();
		msgProps.put(EdgeMessageProperties.EDGE_PROP_STATE, endpointState);
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		regMsg.setBody(msgProps);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			throw new EndpointException("State reply to LifeCycleManager failed due to :"
					+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		}
		Message reply = ex.getInBoundMessage();
		String signalName = reply.getHeader(Message.MESSAGE_NAME);
		if (signalName.equals(CommonConstants.REPLY_NACK)) {
			throw new EndpointException("State reply to lifecycle manager failed");
		}
	}

	private void replyChildren() throws EndpointException {
		log.info("Reporting state: " + endpointState + " to LifeCycleManager.");
		Message regMsg = new DefaultMessage(EdgeLCMMessageFactory.EDGE_REQUEST_CHILDREN);
		Hashtable msgProps = new Hashtable();
		msgProps.put(EdgeMessageProperties.EDGE_PROP_CHILDREN, getChildStates());
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		regMsg.setBody(msgProps);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			throw new EndpointException("Children reply to LifeCycleManager failed due to :"
					+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		}
		Message reply = ex.getInBoundMessage();
		String signalName = reply.getHeader(Message.MESSAGE_NAME);
		if (signalName.equals(CommonConstants.REPLY_NACK)) {
			throw new EndpointException("Children reply to lifecycle manager failed");
		}
	}

	public void reportState() throws EndpointException {
		boolean failIfError = false;

		String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);
		if (lcmRegReq != null) {
			if (lcmRegReq.equals("true")) {
				failIfError = true;
			} else
				return; // Skip registration
		}

		log.info("Sending state: " + getEndpointState() + " to LifeCycleManager.");
		Message regMsg = LCMEdgeMessageFactory.createSetStateMessage(getEndpointState());
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);

		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			if (failIfError)
				throw new EndpointException("Pushing state to Lifecycle Mangager failed :"
						+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		} else {
			Message reply = ex.getInBoundMessage();
			String signalName = reply.getHeader(Message.MESSAGE_NAME);
			if (signalName.equals(CommonConstants.REPLY_NACK)) {
				if (failIfError)
					throw new EndpointException("Pushing state to Lifecycle Manager failed.");
				// else
				// log.
			}
		}
	}

	public void reportChildState(String childName) throws EndpointException {
		boolean failIfError = false;

		String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);
		if (lcmRegReq != null) {
			if (lcmRegReq.equals("true")) {
				failIfError = true;
			} else
				return; // Skip registration
		}
		String childState = (String) getChildStates().get(childName);

		log.info("Sending state: " + childState + " of child: " + childName + " to LifeCycleManager.");
		Message regMsg = LCMEdgeMessageFactory.createRegisterEndpointChildMessage(childName, childState);
		regMsg.setSenderEndpointUri(getEndpointUri());
		regMsg.setReceiverEndpointUri(LIFE_CYCLE_MANGER_ADDRESS);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(regMsg);
		ex = processExchange(ex);
		if (ex.getFaultMessage() != null) {
			if (failIfError)
				throw new EndpointException("Pushing child-state to Lifecycle Mangager failed :"
						+ ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		} else {
			Message reply = ex.getInBoundMessage();
			String signalName = reply.getHeader(Message.MESSAGE_NAME);
			if (signalName.equals(CommonConstants.REPLY_NACK)) {
				if (failIfError)
					throw new EndpointException("Pushing child-state to Lifecycle Manager failed.");
				// else
				// log.
			}
		}
	}

	/**
	 * Method that logs the endpoint onto the Bus. The login required property
	 * must be set to true for the endpoint to login. Upon a successful login a
	 * security token will be issued
	 * 
	 * @throws EndpointException
	 */
	private void login() throws EndpointException {
		// login
		String loginReq = (String) properties.get(PROP_LOGIN_REQUIRED);
		if (loginReq == null || !loginReq.equals("true")) {
			return;
		}
		String loginName = (String) properties.get(PROP_LOGIN_NAME);
		if (loginName == null) {
			throw new EndpointException("No loginName defined");
		}
		String password = (String) properties.get(PROP_PASSWORD);
		if (password == null) {
			throw new EndpointException("No password defined");
		}
		log.info("Login endpoint: " + uri + " with user: " + loginName + " to AccessControlManager.");

		Message loginMsg = ACMessageFactory.createLoginMsg(loginName, password);

		// Message loginMsg = new DefaultMessage(
		// ACMessageConstants.AC_REQUEST_LOGIN);
		// Hashtable msgProps = new Hashtable();
		// msgProps.put(ACMessageConstants.AC_PROP_USERNAME, loginName);
		// msgProps.put(ACMessageConstants.AC_PROP_PASSWORD, password);

		loginMsg.setSenderEndpointUri(getEndpointUri());
		loginMsg.setReceiverEndpointUri(ACCESS_CONTROL_ADDRESS);
		// loginMsg.setBody(msgProps);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(loginMsg);
		ex = processExchange(ex);

		System.out.println("finished processing exchange in login()");
		if (ex.getFaultMessage() != null) {
			throw new EndpointException("Login failed due to :" + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
		}
		Message reply = ex.getInBoundMessage();
		String signalName = reply.getHeader(Message.MESSAGE_NAME);
		if (signalName.equals(ACMessageFactory.AC_REQUEST_LOGIN)) {
			Hashtable msgProps = reply.getBodyAsProperties();
			securityToken = (String) msgProps.get(ACConstants.AC_PROP_TOKEN);
			if (securityToken == null) {
				String errorMessage = (String) msgProps.get(ACConstants.AC_PROP_ERROR_MESSAGE);
				throw new EndpointException("Login failed due to :" + errorMessage);
			}
		}

	}

	/**
	 * Sync processing of inBound messages
	 * 
	 * @param exchange
	 * @return
	 */
	public Exchange processExchange(Exchange exchange) {
		Processor processor = prepareExchange(exchange);
		log.debug("Endpoint: " + uri + ", Processing outgoing exchange: " + exchange);
		if (exchange.getFaultMessage() != null) {
			return exchange;
		}
		synchronized (exchange) {
			try {
				processor.processMessage(exchange.getOutBoundMessage());
			} catch (ProcessorException e) {
				Message fault = new DefaultMessage();
				fault.setReceiverEndpointUri(getEndpointUri());
				fault.setHeader(Message.TYPE_MSG, Message.TYPE_ERROR);
				fault.setHeader(Message.ERROR_REASON, e.getMessage());
				fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
				exchange.setFaultMessage(fault);
				exchange.setException(e);
				log.warn("Endpoint: " + uri + ", Exception processing exchange: " + exchange);
				return exchange;
			}

			if (exchange.getPattern().equals(ExchangePattern.OutIn)) {
				try {
					exchange.wait(timeout);
					if (exchange.getInBoundMessage() == null && exchange.getFaultMessage() == null) {
						log.warn("Endpoint: " + uri + ", exchange: "+exchange+" timed out ("+timeout+" ms).");
						Message fault = new DefaultMessage();
						fault.setReceiverEndpointUri(getEndpointUri());
						fault.setHeader(Message.TYPE, Message.TYPE_ERROR);
						fault.setHeader(Message.ERROR_REASON, "Exchange timeout");
						fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
						exchange.setFaultMessage(fault);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return exchange;
	}

	/**
	 * Prepares the exchange before it is processed. This includes checking that
	 * sender and receiver adresses are resolved
	 * 
	 * @param exchange
	 *            the exchange
	 */
	private Processor prepareExchange(Exchange exchange) {
		try {

			if (!isStateRunning()) {
				throw new EndpointException("Endpoint not able to handle exchanges. Endpoint State is: "
						+ endpointState);
			}

			String senderUri = exchange.getOutBoundMessage().getSenderEndpointUri();
			URIHelper helper;

			if (senderUri == null || senderUri.equals("")) {
				helper = new URIHelper(uri);
			} else {
				helper = new URIHelper(senderUri);
			}
			helper.setEndpoint(endpointUuid);
			exchange.getOutBoundMessage().setSenderEndpointUri(helper.getEndpointUri());

			String uri = exchange.getOutBoundMessage().getReceiverEndpointUri();
						
			if(exchange.getExchangeId() == null){
				exchange.setExchangeId(uuidGenerator.generateId());
			}
			
			if (exchange.getPattern().equals(ExchangePattern.OutIn)) {
				exchanges.put(exchange.getExchangeId(), exchange);
			}
			
			if(exchange.getPattern().equals(ExchangePattern.InOut)){
				//If this is a reply we search through the message for header values that are to be passed
				//along with the reply
				exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_ID, exchange.getInBoundMessage().getHeader(Message.EXCHANGE_ID));
				Message outMsg = exchange.getOutBoundMessage();
				Message inMsg = exchange.getInBoundMessage();
				Enumeration keys = inMsg.getHeaders().keys();
				while (keys.hasMoreElements()) {
					String key = (String) keys.nextElement();
					if(key.startsWith(Message.EXCHANGE_PREFIX)){
						outMsg.setHeader(key, exchange.getInBoundMessage().getHeader(key));
					}
				}
				
			} else {
				exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
			}
						
			exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_PATTERN, exchange.getPattern().toString());
			if (exchange.getOutBoundMessage().getType() == null) {
				exchange.getOutBoundMessage().setHeader(Message.TYPE, Message.TYPE_MSG);
			}
			

			String protocol = URIProtocolHelper.getProtocol(uri);

			Processor processor = resolveOutgoingProcessor(protocol);

			if (protocol.equals("coos")) {

				helper = new URIHelper(uri);
				exchange.getOutBoundMessage().setReceiverEndpointName(helper.getEndpoint());
				exchange.getOutBoundMessage().setSenderEndpointName(
						((getName() == null) ? getEndpointUuid() : getName()));

				if (securityToken != null) {
					exchange.getOutBoundMessage().setHeader(Message.SECURITYTOKEN, securityToken);
				}
			}

			return processor;

		} catch (Exception e) {
			e.printStackTrace();
			exchange.setFaultMessage(new DefaultMessage().setHeader(Message.ERROR_REASON, e.getMessage()));
		}

		return null;

	}

	private boolean isStateRunning() {
		if (endpointState.equals(STATE_INSTALLED) || endpointState.equals(STATE_PAUSED)
				|| endpointState.equals(STATE_READY) || endpointState.equals(STATE_STARTUP_FAILED)
				|| endpointState.equals(STATE_UNINNSTALLED) || endpointState.equals(STATE_UPDATING)
				|| endpointState.equals(STATE_UPGRADING))
			return false;
		return true;
	}

	protected Processor resolveOutgoingProcessor(String protocol) throws EndpointException {
		Processor processor = (Processor) outLinks.get(protocol);

		if (processor == null) {
			throw new EndpointException("No channel defined for protocol: " + protocol);
		}
		return processor;
	}

	/**
	 * Async processing of outbound messages
	 * 
	 * @param exchange
	 * @param callback
	 */
	public void processExchange(Exchange exchange, AsyncCallback callback) {
		log.debug("Endpoint: " + uri + ", Processing outgoing exchange: " + exchange);
		Processor processor = prepareExchange(exchange);
		if (exchange.getFaultMessage() != null) {
			callback.processExchange(exchange);
			return;
		}
		exchanges.put(exchange.getExchangeId(), exchange);
		callbacks.put(exchange.getExchangeId(), callback);
		synchronized (exchange) {
			try {
				processor.processMessage(exchange.getOutBoundMessage());
			} catch (ProcessorException e) {
				Message fault = new DefaultMessage();
				fault.setHeader(Message.TYPE_MSG, Message.TYPE_ERROR);
				fault.setHeader(Message.ERROR_REASON, e.getMessage());
				fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
				fault.setHeader(Message.EXCHANGE_PATTERN, exchange.getPattern().toString());
				processMessage(fault);

			}
		}
	}

	/**
	 * Processing of Inbound messages
	 * 
	 * @param msg
	 */
	public void processMessage(Message msg) {
		if (!isStateRunning()) {
			log.warn("Endpoint " + uri + " is not running. Message ignored: " + msg.getName());
			return;
		}
		String msgType = msg.getHeader(Message.TYPE);
		if (msgType.equals(Message.TYPE_MSG) || msgType.equals(Message.TYPE_ERROR)) {
			if (msg.getName().equals(Notification.NOTIFY)) {
				msg = new DefaultNotification(msg);
			}
			String xpattern = msg.getHeader(Message.EXCHANGE_PATTERN);
			ExchangePattern xp = new ExchangePattern(xpattern);
			final String xId = msg.getHeader(Message.EXCHANGE_ID);
			final Message retMsg = msg;
			try {
				retMsg.getBody();
			} catch (Exception e) {
				retMsg.setHeader(Message.TYPE, Message.TYPE_ERROR);
				retMsg.setHeader(Message.ERROR_REASON, "Deserialization error: " + e.getMessage());
			}
			Consumer consumer = createConsumer();
			// Error handling
			if (msg.getHeader(Message.TYPE).equals(Message.TYPE_ERROR)) {
				if (exchanges.containsKey(xId)) {

					threadPool.execute(new Runnable() {
						public void run() {
							Exchange exchange = (Exchange) exchanges.remove(xId);
							log.warn("Endpoint: " + uri + ", Processing incoming exchange: " + exchange + ": fault :"
									+ retMsg);
							synchronized (exchange) {
								exchange.setFaultMessage(retMsg);
								if (callbacks.containsKey(xId)) {
									// this is an async return
									AsyncCallback callback = (AsyncCallback) callbacks.remove(xId);
									callback.processExchange(exchange);
								} else {
									// this is a sync return
									exchange.notify();
								}
							}
						}
					});
				} else {
					log.warn("Endpoint: " + uri + ", Error message:" + retMsg);
				}

			} else {
				// Message handling
				Exchange exchange = null;
				if (exchanges.containsKey(xId) && !xp.isOutBoundInitiated()) {
					// this is a return or a message to same endpoint.

					threadPool.execute(new Runnable() {
						public void run() {
							Exchange exchange2 = (Exchange) exchanges.remove(xId);
							log.debug("Endpoint: " + uri + ", Processing incoming exchange: " + exchange2);
							synchronized (exchange2) {
								exchange2.setInBoundMessage(retMsg);
								if (callbacks.containsKey(xId)) {
									// this is an async return
									AsyncCallback callback = (AsyncCallback) callbacks.remove(xId);
									callback.processExchange(exchange2);
								} else {
									// this is a sync return
									exchange2.notify();
								}
							}
						}
					});

				} else if (consumer != null) {
					if (msg.getHeader(Message.MESSAGE_NAME).equals(EdgeLCMMessageFactory.EDGE_REQUEST_STATE)) {
						threadPool.execute(new Runnable() {
							public void run() {
								try {
									replyState();
								} catch (EndpointException e) {
									e.printStackTrace();
								}
							}
						});
						return;
					} else if (msg.getHeader(Message.MESSAGE_NAME).equals(
							EdgeLCMMessageFactory.EDGE_REQUEST_CHILD_STATE)) {
						final String childAddress = (String) msg.getBodyAsProperties().get(
								EdgeMessageProperties.EDGE_PROP_CHILD_NAME);
						threadPool.execute(new Runnable() {
							public void run() {
								try {
									replyChildState(childAddress);
								} catch (EndpointException e) {
									e.printStackTrace();
								}
							}
						});
						return;
					} else if (msg.getHeader(Message.MESSAGE_NAME).equals(EdgeLCMMessageFactory.EDGE_REQUEST_CHILDREN)) {
						threadPool.execute(new Runnable() {
							public void run() {
								try {
									replyChildren();
								} catch (EndpointException e) {
									e.printStackTrace();
								}
							}
						});
						return;
					}

					// this is an initiating request, will only be handled in
					// state running, else it will be defered to
					// the endpoint reaches state running
					if (checkDefer(msg))
						return;

					if (xpattern.equals(ExchangePattern.OutIn)) {
						exchange = createExchange(new ExchangePattern(ExchangePattern.InOut));
					} else {
						// default behaviour is inOnly
						exchange = createExchange(new ExchangePattern(ExchangePattern.InOnly));
					}

					if (exchange != null) {
						exchange.setInBoundMessage(msg);
						exchange.setExchangeId(xId);
						final Exchange exchange1 = exchange;
						final Consumer consumer1 = consumer;
						threadPool.execute(new Runnable() {
							public void run() {
								// Todo might insert e semaphore here to control
								// concurrent access to consumer
								log.debug("Endpoint: " + uri + ", Processing incoming exchange: " + exchange1);
								consumer1.process(exchange1);
							}
						});
					}
				}
			}
		}
	}

	protected boolean checkDefer(Message msg) {
		if (!isStateRunning()) {
			deferQueue.addElement(msg);
			return true;
		}
		return false;
	}

	public Vector getServices() {
		return services;
	}

	public final void initializeEndpoint() {
		uuidGenerator = new UuidGenerator("xId-" + ((getName() == null) ? getEndpointUuid() : getName()));
		threadPool = Executors.newThreadPool(maxPoolSize);

		threadPool.execute(new Runnable() {
			public void run() {
				if (getEndpointState().equals(STATE_READY)) {
					try {
						preStart();
						start();
						postStart();
					} catch (Exception e) {
						e.printStackTrace();
						setEndpointState(STATE_STARTUP_FAILED);
					}
				}
				// Let the hanging thread return in pluginchannel.connect(), if startupOrdered is true
				synchronized (DefaultEndpoint.this) {
					DefaultEndpoint.this.notify();
				}
			}
		});
	}

	protected void preStart() throws EndpointException {
		String s = !name.equals(endpointUuid)?"(name="+name+")":"";
		log.info("Starting endpoint: " + endpointUuid + s);
		setEndpointState(STATE_STARTING);

		// login to the accessControl Manager
		login();

		// if (producer instanceof Service && !(producer instanceof Endpoint)) {
		// services.addElement(producer);
		// ((Service) producer).start();
		// }
	}

	public void start() throws Exception {
		// Override this method
	}

	protected void postStart() throws EndpointException {
		createProducer();

		setEndpointState(STATE_RUNNING);
		// register to the life cycle manager
		registerLCM();
		
		String s = !name.equals(endpointUuid)?"(name="+name+")":"";
		log.info("Successfully started endpoint: " + endpointUuid + s);
	}

	public void stop() throws Exception {
		// Override this method
	}

	public final void shutDownEndpoint() {

		if (!isStateRunning()) {
			return;
		}
		log.info("Stopping endpoint: " + uri);
		setEndpointState(STATE_STOPPING);

		try {
			stop();
		} catch (Exception e) {
			e.printStackTrace();
		}

		for (int i = 0; i < services.size(); i++) {
			Service service = (Service) services.elementAt(i);
			try {
				service.stop();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// register to the life cycle manager
		try {
			unRegisterLCM();
		} catch (EndpointException e) {
			e.printStackTrace();
		}

		if (threadPool != null) // Null if endpoint was not started successfully
			// (ie couldn't connect)
			threadPool.stop();

		setEndpointState(STATE_READY);
	}


	public void addLink(String protocol, Link link) throws ConnectingException {
		outLinks.put(protocol, link);

	}

	public void addAlias(String alias) {
		if (alias != null && !UuidHelper.isUuid(alias)) {
			aliases.addElement(alias);
		}
		updateAliases();
	}

	public void removeAlias(String alias) {
		aliases.removeElement(alias);
		updateAliases();
	}

	public Vector getAliases() {
		return aliases;
	}

	private void updateAliases() {
		Link link = (Link) outLinks.get("coos");
		if (link != null) {
			Message msg = new DefaultMessage("alias", Message.TYPE_ALIAS);
			msg.setReceiverEndpointUri("coos://" + link.getDestinationUuid());
			msg.setBody(aliases);
			Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
			ex.setOutBoundMessage(msg);
			processExchange(ex);
		}
	}

	public Processor getDefaultProcessor() {
		return this;
	}

	public Link getLink(String id) {
		return (Link) outLinks.get(id);
	}

	public void removeLink(String id) {
		outLinks.remove(id);

	}

	public void removeLinkById(String linkId) {
		// TODO Auto-generated method stub

	}

	public boolean subscribe(SubscriptionFilter filter) {
		log.debug("Endpoint: " + uri + " subscribing: " + filter);
		filter.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
		filter.setSenderEndpointUri(uri);
		filter.setHeader(Message.MESSAGE_NAME, SubscriptionFilter.SUBSCRIBE);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
		ex.setOutBoundMessage(filter);
		processExchange(ex);
		if(ex.getFaultMessage() != null){
			return false;
		}
		return true;
	}

	public void unsubscribe() {
		log.debug("Endpoint: " + uri + " unSubscribing all");
		Message msg = new DefaultMessage(SubscriptionFilter.UNSUBSCRIBE_ALL);
		msg.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
		msg.setSenderEndpointUri(uri);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(msg);
		processExchange(ex);
	}

	public void unsubscribe(SubscriptionFilter filter) {
		log.debug("Endpoint: " + uri + " unSubscribing: " + filter);
		filter.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
		filter.setSenderEndpointUri(uri);
		filter.setHeader(Message.MESSAGE_NAME, SubscriptionFilter.UNSUBSCRIBE);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(filter);
		processExchange(ex);
	}

	public void publish(Notification notification) {
		log.debug("Endpoint: " + uri + " publishing: " + notification);
		notification.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
		notification.setSenderEndpointUri(uri);
		Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
		ex.setOutBoundMessage(notification);
		processExchange(ex);
	}

	public void setChildStates(Hashtable childStates) {
		this.childStates = childStates;
	}

	public Hashtable getChildStates() {
		return childStates;
	}

	public Hashtable getProperties() {
		return properties;
	}

	public void setLinkAliases(Vector regAliases, Link outlink) {
		// Not implemented
	}

	public Plugin getPlugin() {
		return plugin;
	}

	public void setPlugin(Plugin plugin) {
		this.plugin = plugin;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy