/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.dispatch;
import org.ws4d.java.communication.ProtocolData;
import org.ws4d.java.communication.ResponseCallback;
import org.ws4d.java.constants.DPWSMessageConstants;
import org.ws4d.java.message.Message;
import org.ws4d.java.message.discovery.ProbeMatchesMessage;
import org.ws4d.java.message.discovery.ResolveMatchesMessage;
import org.ws4d.java.structures.LockedMap;
import org.ws4d.java.types.URI;
import org.ws4d.java.util.Log;
import org.ws4d.java.util.TimedEntry;
import org.ws4d.java.util.WatchDog;
/**
* Class memorizes outgoing requests and returns callbacks to incoming
* responses.
*
* @author mspies
*/
public class RequestResponseCoordinator {
/** message id<URI> -> <TimedEntry> */
protected final LockedMap map_msgId_2_entry = new LockedMap();
/** singleton of this */
protected static RequestResponseCoordinator rrc = new RequestResponseCoordinator();
/**
* Private Constructor.
*/
private RequestResponseCoordinator() {}
/**
* Get singleton instance of request response coordinator.
*
* @return request response coordinator.
*/
public static RequestResponseCoordinator getInstance() {
return rrc;
}
// ---------------------------------------------------------------------
/**
* Registers callback for an outgoing request message. Timeouts will be
* generated by underlying communication layer.
*
* @param msg - the request message.
* @param callback - callback for responses, faults or timeouts.
* @param timeUntilTimeout
*/
public void registerResponseCallback(Message msg, ResponseCallback callback, long timeUntilTimeout) {
TimedResponseCallback timedCallback = new TimedResponseCallback(msg, callback);
WatchDog.getInstance().register(timedCallback, timeUntilTimeout);
map_msgId_2_entry.put(msg.getMessageId(), timedCallback);
}
/**
* Handle response message. Message will be sent to local callbacks.
*
* @param msg
* @param protocolData
* @return <code>true</code> - if message is exclusively handled by
* RequestResponseCoordinator
*/
public void handleResponse(Message msg, ProtocolData protocolData) {
URI requestMsgId = msg.getRelatesTo();
switch (msg.getType()) {
// DISCOVERY
case DPWSMessageConstants.PROBE_MATCHES_MESSAGE: {
// More than one responses possible.
ProbeMatchesMessage probeMatches = (ProbeMatchesMessage) msg;
TimedResponseCallback entry = getCallback(requestMsgId);
if (entry != null) {
entry.callback.handle(entry.request, probeMatches, protocolData);
}
break;
}
case DPWSMessageConstants.RESOLVE_MATCHES_MESSAGE: {
ResolveMatchesMessage resolveMatches = (ResolveMatchesMessage) msg;
TimedResponseCallback entry = getCallback(requestMsgId);
if (entry != null) {
entry.callback.handle(entry.request, resolveMatches, protocolData);
}
break;
}
default:
Log.error("Cannot determine response message type. Message = " + msg);
}
}
// /**
// * Init timeout for registered message.
// *
// * @param msgId message id of message to time out.
// */
// public void initTimeout( URI msgId ){
// TimedResponseCallback msgEntry = (TimedResponseCallback)
// map_msgId_2_entry.get(msgId);
// if( msgEntry != null ){
// msgEntry.timedOut();
// }
// }
// ------------------------------- PRIVATE ---------------------------
/**
* Returns <code>true</code> if msgId is managed by the request response
* coordinator, else <code>false</false>.
*
* @param msgId The msg id to look for.
* @return Returns <code>true</code> if msgId is managed by the request
* response coordinator, else <code>false</false>.
*/
public boolean containsMsgId(URI msgId) {
return map_msgId_2_entry.containsKey(msgId);
}
/**
* Get callback by msg id.
*
* @param msgId
* @return callback
*/
private TimedResponseCallback getCallback(URI msgId) {
return (TimedResponseCallback) map_msgId_2_entry.get(msgId);
}
private class TimedResponseCallback extends TimedEntry {
/** request message */
Message request;
/** callback to be called if response is received */
ResponseCallback callback;
// /** response was received? */
// boolean responseReceived = false;
TimedResponseCallback(Message request, ResponseCallback callback) {
super();
this.request = request;
this.callback = callback;
}
/*
* (non-Javadoc)
* @see org.ws4d.java.concurrency.TimedEntry#timedOut()
*/
public void timedOut() {
// if( responseReceived == false ){
// callback.receivedTimeout(msgId);
// }
map_msgId_2_entry.remove(request.getMessageId());
callback.handleTimeout(request);
}
}
}