package br.ufms.dct.simplerep.httpprocessors;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.ParseException;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import br.ufms.dct.simplerep.SimpleRepConfiguration;
import br.ufms.dct.simplerep.ar.MessageContext;
import br.ufms.dct.simplerep.ar.SystemContext;
import br.ufms.dct.simplerep.enums.SimpleRepConstants;
import br.ufms.dct.simplerep.exceptions.SimpleRepConfException;
import br.ufms.dct.simplerep.kernels.AbstractKernel;
import br.ufms.dct.simplerep.kernels.SamoaKernel;
public class ABCastInterceptor implements HttpRequestInterceptor {
static Logger logger = Logger.getLogger(ABCastInterceptor.class.getName());
// the queue from which the HttpProxy will wait
// for the response and then send the id to the client
private BlockingQueue<MessageContext> in;
public static final String AppServerInQueueId = "SIMPLEREP_AppServerQueue";
HttpEntity entity;
public ABCastInterceptor(BlockingQueue<MessageContext> inQueue) {
this.in = inQueue;
}
public void process(HttpRequest request, HttpContext context) {
SystemContext sysContext;
BasicHttpEntityEnclosingRequest basicRequest = (BasicHttpEntityEnclosingRequest) request;
entity = basicRequest.getEntity();
try {
sysContext = SimpleRepConfiguration.getConfiguration()
.getSystemContext();
BlockingQueue<MessageContext> abcastInQueue = (BlockingQueue<MessageContext>) sysContext
.get(SamoaKernel.SAMOA_ABCAST_IN_QUEUE);
MessageContext msgContext = MessageContext.buildMessageContext(EntityUtils.toString(entity));
String messageId = msgContext.getMessageId();
if (messageId == null || messageId.equals("")) {
System.err.println("[ABCastInterceptor] FATAL ERROR: wsa:MessageID could not be retrieved. Aborting!");
return;
}
context.setAttribute(AbstractKernel.MESSAGE_ID, messageId);
// ABCast output queue
SynchronousQueue<MessageContext> myQueue = new SynchronousQueue<MessageContext>();
// this one will be read by the Abcast Callback
sysContext.set(messageId, myQueue);
// The Transport Component will wait on this queue to send the response to the client
HashMap<String, SynchronousQueue<String>> backChannelQueue = (HashMap<String, SynchronousQueue<String>>) sysContext.get(SamoaKernel.TRANSPORT_OUT_QUEUES);
// this one will be fed by the producers (UDPCallback and Proxy) and read by the Transport Component
backChannelQueue.put(msgContext.getMessageId(), new SynchronousQueue<String>());
// this one will be read by the ABCastRunner
msgContext.setProperty(AppServerInQueueId, messageId);
// TODO find the original URL
msgContext.setProperty(SimpleRepConstants.ORIGINAL_URL, basicRequest.getRequestLine().getUri());
abcastInQueue.put(msgContext);
synchronized (myQueue) {
// waiting for the ABcast, then releasing resources
logger.debug("Waiting for the abcast and inflow to complete.");
MessageContext processedContext = myQueue.take();
logger.debug("Message was abcasted and processed in the inflow. Invoking my AppServer.");
((BasicHttpEntity) entity).setContent(new ByteArrayInputStream(processedContext.getEnvelope().toString().getBytes()));
}
} catch (InterruptedException e) {
logger.error("ABCast could not be done. Error when trying to enqueue the message.");
} catch (ParseException e) {
logger.error("ParseException; ABCast could not be done. Envelope could not be parsed.");
} catch (IOException e) {
logger.error("IOException; ABCast could not be done. Envelope could not be parsed.");
}
}
}