package org.distributeme.registry.servlet;
import org.distributeme.core.ServiceDescriptor;
import org.distributeme.core.conventions.WebOperations;
import org.distributeme.core.util.EventServiceRegistryUtil;
import org.distributeme.registry.esregistry.ChannelDescriptor;
import org.distributeme.registry.esregistry.EventServiceRegistry;
import org.distributeme.registry.esregistry.EventServiceRegistryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
/**
* Servlet that enables access to the event service registry via http protocol.
* @author lrosenberg
*
*/
public class EventServiceRegistryServlet extends BaseRegistryServlet{
/**
* SerialUID.
*/
private static final long serialVersionUID = 1L;
/**
* Registry instance.
*/
private transient EventServiceRegistry registry = EventServiceRegistryImpl.getInstance();
/**
* Logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(EventServiceRegistryServlet.class);
@Override
protected void moskitoDoGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String op = getOperation(req);
//NOTE this can throw an illegal argument exception, but since this servlet will never be exposed, its ok, and there
//is no further error handling needed.
WebOperations operation = WebOperations.valueOf(op.toUpperCase());
switch(operation){
case ADD_CONSUMER:
addConsumer(req, res);
break;
case ADD_SUPPLIER:
addSupplier(req, res);
break;
case LIST:
list(req, res);
break;
case NOTIFY_CONSUMER:
notifyConsumerUnavailable(req, res);
break;
case NOTIFY_SUPPLIER:
notifySupplierUnavailable(req, res);
break;
case RESET:
reset(req, res);
break;
default:
throw new IllegalArgumentException("Parseable but (yet) unsupported operation.");
}
}
/**
* Reads the channel parameter from the incoming request. Throws an exception if the parameter is not present.
*/
private String getChannelParameter(HttpServletRequest req){
return getRequiredParameter(req, "channel");
}
/**
* Reads the descriptor id parameter from the incoming request. Throws an exception if the parameter is not present.
*/
private String getDescriptorParameter(HttpServletRequest req){
return getRequiredParameter(req, "id");
}
private void addSupplier(HttpServletRequest req, HttpServletResponse res){
String channel = getChannelParameter(req);
String supplierAsString = getDescriptorParameter(req);
ServiceDescriptor supplier = ServiceDescriptor.fromSystemWideUniqueId(supplierAsString);
List<ServiceDescriptor> consumers = registry.addSupplier(channel, supplier);
sendResponse(res, EventServiceRegistryUtil.list2string(consumers));
}
private void addConsumer(HttpServletRequest req, HttpServletResponse res){
String channel = getChannelParameter(req);
String consumerAsString = getDescriptorParameter(req);
ServiceDescriptor consumer = ServiceDescriptor.fromSystemWideUniqueId(consumerAsString);
List<ServiceDescriptor> suppliers = registry.addConsumer(channel, consumer);
sendResponse(res, EventServiceRegistryUtil.list2string(suppliers));
}
private void notifyConsumerUnavailable(HttpServletRequest req, HttpServletResponse res){
String descriptorAsString = getDescriptorParameter(req);
ServiceDescriptor descriptor = ServiceDescriptor.fromSystemWideUniqueId(descriptorAsString);
boolean result = true;
try{
registry.notifyConsumerUnavailable(descriptor);
}catch(Exception e){
result = false;
LOG.error("notifyConsumerUnavailable", e);
}
sendBooleanResponse(res, result);
}
private void notifySupplierUnavailable(HttpServletRequest req, HttpServletResponse res){
String descriptorAsString = getDescriptorParameter(req);
ServiceDescriptor descriptor = ServiceDescriptor.fromSystemWideUniqueId(descriptorAsString);
boolean result = true;
try{
registry.notifySupplierUnavailable(descriptor);
}catch(Exception e){
result = false;
LOG.error("notifySupplierUnavailable", e);
}
sendBooleanResponse(res, result);
}
private void reset(HttpServletRequest req, HttpServletResponse res){//NOPMD
registry.reset();
sendBooleanResponse(res, Boolean.TRUE);
}
//yes, this isn't nice, but it had to be worked out fast.
private void list(HttpServletRequest req, HttpServletResponse res){
StringBuilder m = new StringBuilder();
m.append("<?xml version=\"1.0\"?>");
m.append("<channels>");
List<ChannelDescriptor> channels = registry.getChannels();
for (ChannelDescriptor channel : channels){
m.append("<channel name=\"").append(channel.getName()).append("\"");
m.append(">");
m.append('\n');
m.append("<suppliers>");
for (ServiceDescriptor supplier : channel.getSuppliers()){
m.append("<supplier>"+supplier.getSystemWideUniqueId()+"</supplier>");
m.append('\n');
}
m.append("</suppliers>");
m.append('\n');
m.append("<consumers>");
for (ServiceDescriptor consumer : channel.getConsumers()){
m.append("<consumer>"+consumer.getSystemWideUniqueId()+"</consumer>");
m.append('\n');
}
m.append("</consumers>");
m.append('\n');
m.append("</channel>");
m.append('\n');
}
m.append("</channels>");
String message = m.toString();
byte[] messageBytes = message.getBytes(Charset.forName("UTF-8"));
res.setContentLength(messageBytes.length);
res.setContentType("text/xml");
OutputStream out = null;
try{
out = res.getOutputStream();
out.write(messageBytes);
out.flush();
}catch(IOException e){
LOG.warn("sendResponse(res, "+message+")", e);
}finally{
if (out!=null){
try{
out.close();
}catch(IOException ignored){//NOPMD
}
}
}
}
}