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

org.certificateservices.messages.csmessages.manager.DefaultReqRespManager Maven / Gradle / Ivy

The newest version!
/************************************************************************
*                                                                       *
*  Certificate Service - Messages                                       *
*                                                                       *
*  This software is free software; you can redistribute it and/or       *
*  modify it under the terms of the GNU Lesser General Public License   *
*  License as published by the Free Software Foundation; either         *
*  version 3   of the License, or any later version.                    *
*                                                                       *
*  See terms of license at gnu.org.                                     *
*                                                                       *
*************************************************************************/
package org.certificateservices.messages.csmessages.manager;

import org.certificateservices.messages.MessageProcessingException;
import org.certificateservices.messages.csmessages.jaxb.CSMessage;
import org.certificateservices.messages.csmessages.jaxb.CSResponse;

import javax.xml.bind.JAXBElement;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Default request response manager sending a request on one queue and waiting for a response on a response queue.
 * 
 *
 * @author Philip Vendil
 *
 */
public class DefaultReqRespManager implements ReqRespManager,
		MessageResponseCallback {
	
	private static Logger log = Logger.getLogger(DefaultReqRespManager.class.getName());

	protected  Map responseMap = new HashMap();
	
	protected long timeOut;
	protected MessageHandler messageHandler;
	protected String messageListenerName;
	protected String messageSenderName;
	
	protected static long SLEEP_INTERVAL_MILLIS = 100;
	
	public static final String CALLBACK_ALIAS = "DefaultReqRespManager";
	
	/**
	 * Default constructor of a DefaultReqRespManager
	 * 
	 * @param timeOut time in milliseconds to wait for response.
	 * @param messageHandler, the related message handler.
	 * @param messageListenerName the name of the message listener to use, never null and must be registered in the message handler.
	 * @param messageSenderName the name of the message sender to use, never null and must be registered in the message handler.
	 * @throws MessageProcessingException if internal problems occurred setting up the request response manager.
	 */
	public DefaultReqRespManager(long timeOut, MessageHandler messageHandler, String messageSenderName, String messageListenerName) throws MessageProcessingException{
		this.timeOut = timeOut;
		this.messageHandler = messageHandler;
		this.messageSenderName = messageSenderName;
		this.messageListenerName = messageListenerName;
		// Register it self
		this.messageHandler.getMessageListener(messageListenerName).registerCallback(CALLBACK_ALIAS,this);
	}


	/**
	 * @see org.certificateservices.messages.csmessages.manager.ReqRespManager#sendRequest(java.lang.String, byte[])
	 */
	@Override
	public CSMessage sendRequest(String requestId, byte[] request)
			throws IllegalArgumentException, IOException,
			MessageProcessingException {
		return sendRequest(requestId,request,null);
	}

	/**
	 * @see org.certificateservices.messages.csmessages.manager.ReqRespManager#sendRequest(java.lang.String, byte[], Map)
	 */
	@Override
	public CSMessage sendRequest(String requestId, byte[] request, Map requestAttributes)
			throws IllegalArgumentException, IOException,
			MessageProcessingException {
		CSMessage retval = null;

		registerWaitForRequestId(requestId);

		messageHandler.sendMessage(messageSenderName,requestId, request, requestAttributes);

		long waitTime = 0;
		while(waitTime < timeOut){
			retval = checkIfResponseIsReady(requestId);
			if(retval != null){
				break;
			}
			try {
				Thread.sleep(SLEEP_INTERVAL_MILLIS);
			} catch (InterruptedException e) {
				log.severe("waiting process interupted while waiting for MQ response: " + e.getMessage());
			}
			waitTime+= SLEEP_INTERVAL_MILLIS;

		}

		if(retval == null){
			cancelWaitForResponse(requestId);
			throw new IOException("Error: Timeout exception after waiting for message with request id: " + requestId);
		}

		return retval;
	}
	
	/**
	 * @see org.certificateservices.messages.csmessages.manager.MessageResponseCallback#responseReceived(byte[], CSMessage, Map)
	 */
	@Override
	public void responseReceived(byte[] requestData, CSMessage responseMessage, Map messageAttributes) {
		String requestId = findRequestId(responseMessage);
		if(requestId != null){
			populateResponseMapIfStillExist(requestId, responseMessage);
		}
	}
	
	/**
	 * Signals that the current manager is listening for this message.
	 * 
	 * @param requestId  the id of the message to register
	 */
	protected synchronized void registerWaitForRequestId(String requestId){
		responseMap.put(requestId, new RequestEntry());
	}
	
	/**
	 * Method to check if a response have been sent to a request with the given id.
	 * @param requestId the id to check for 
	 * @return the PKIMessage response or null if no response have been recieved yet.
	 */
	protected synchronized CSMessage checkIfResponseIsReady(String requestId){
		CSMessage retval = null;
		RequestEntry entry = responseMap.get(requestId);
		if(entry != null && entry.getResponse() != null){
			retval = entry.getResponse();
			responseMap.remove(requestId);
		}
		
		return retval;
	}
	

	/**
	 * Method signaling that the waiting thread have stopped listening for
	 * a response to this request.
	 */
	protected synchronized void cancelWaitForResponse(String requestId){
		responseMap.remove(requestId);
	}
	
	/**
	 * Method that is called by the responseRecieved method that it received a message
	 * to this listener and should populate the response map.
	 */
	protected synchronized boolean populateResponseMapIfStillExist(String requestId, CSMessage responseMessage){
		boolean retval = false;
		RequestEntry entry = responseMap.get(requestId);
		if(entry != null){
			entry.setResponse(responseMessage);
			retval = true;
		}
		
		return retval;
	}

	/**
	 * Method that extracts the requestId from the responseMessage. Where
	 * IssueTokenCredentialsResponse and GetCredentialResponse and FailureResponse is supported.
	 *  
	 * @param responseMessage the message to parse request id from
	 * @return the request id or null if no valid request id was found in the response
	 */
	protected String findRequestId(CSMessage responseMessage) {
		String retval = null;
		CSResponse response = findResponsePayload(responseMessage);
		if(response != null){
			retval = response.getInResponseTo();
		}
		
		if(retval != null){
			retval = retval.trim();
		}
		
		return retval;
	}
	
	protected CSResponse findResponsePayload(CSMessage responseMessage){

		Object payload = responseMessage.getPayload().getAny();
		if(payload instanceof CSResponse){
			return (CSResponse) payload;
		}
		if(payload instanceof JAXBElement){
			Object innerPayload = ((JAXBElement) payload).getValue();
			if(innerPayload instanceof CSResponse) {
				return (CSResponse) innerPayload;
			}
		}
		
		return null;
	}
	
	/**
	 * A request entry is used the the request map after a send message call i waiting
	 * for a response, contains a response PKI Message data.
	 * 
	 * @author Philip Vendil
	 *
	 */
	protected class RequestEntry{
		
		private CSMessage response;

		
		public CSMessage getResponse() {
			return response;
		}
		public void setResponse(CSMessage response) {
			this.response = response;
		}
	}
	


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy