package org.openxdm.xcap.server.slee;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.slee.ActivityContextInterface;
import javax.slee.ChildRelation;
import javax.slee.RolledBackContext;
import javax.slee.SbbContext;
import net.java.slee.resource.http.events.HttpServletRequestEvent;
import org.apache.log4j.Logger;
import org.mobicents.slee.xdm.server.ServerConfiguration;
import org.openxdm.xcap.common.error.BadRequestException;
import org.openxdm.xcap.common.error.ConflictException;
import org.openxdm.xcap.common.error.InternalServerErrorException;
import org.openxdm.xcap.common.error.MethodNotAllowedException;
import org.openxdm.xcap.common.error.NoParentConflictException;
import org.openxdm.xcap.common.error.NotFoundException;
import org.openxdm.xcap.common.error.PreconditionFailedException;
import org.openxdm.xcap.common.error.UnsupportedMediaTypeException;
import org.openxdm.xcap.common.http.HttpConstant;
import org.openxdm.xcap.common.resource.Resource;
import org.openxdm.xcap.common.uri.ParseException;
import org.openxdm.xcap.common.uri.Parser;
import org.openxdm.xcap.common.uri.ResourceSelector;
import org.openxdm.xcap.server.etag.ETagValidator;
import org.openxdm.xcap.server.etag.IfMatchETagValidator;
import org.openxdm.xcap.server.etag.IfNoneMatchETagValidator;
import org.openxdm.xcap.server.result.ReadResult;
import org.openxdm.xcap.server.result.WriteResult;
/**
*
* @author martins
* @author aayush.bhatnagar
*
*/
public abstract class AggregationProxySbb implements javax.slee.Sbb {
private SbbContext sbbContext = null;
private static final Logger logger = Logger
.getLogger(AggregationProxySbb.class);
public void setSbbContext(SbbContext context) {
this.sbbContext = context;
}
public void unsetSbbContext() {
this.sbbContext = null;
}
public void sbbCreate() throws javax.slee.CreateException {
}
public void sbbPostCreate() throws javax.slee.CreateException {
}
public void sbbActivate() {
}
public void sbbPassivate() {
}
public void sbbRemove() {
}
public void sbbLoad() {
}
public void sbbStore() {
}
public void sbbExceptionThrown(Exception exception, Object event,
ActivityContextInterface activity) {
if (logger.isDebugEnabled())
logger.debug("sbbExceptionThrown(exception=" + exception.toString()
+ ",event=" + event.toString() + ",activity="
+ activity.toString() + ")");
}
public void sbbRolledBack(RolledBackContext sbbRolledBack) {
if (logger.isDebugEnabled())
logger.debug("sbbRolledBack(sbbRolledBack="
+ sbbRolledBack.toString() + ")");
}
protected SbbContext getSbbContext() {
return sbbContext;
}
// CHILD RELATIONS & RA ABSTRACTIONS
// ################################################################
public abstract ChildRelation getRequestProcessorChildRelation();
protected RequestProcessorSbbLocalObject getRequestProcessor() {
try {
return (RequestProcessorSbbLocalObject) getRequestProcessorChildRelation()
.create();
} catch (Exception e) {
logger.error("Failed to create child sbb", e);
return null;
}
}
// added by aayush here: Child relation and child sbb creation
// for Authentication Proxy.
public abstract ChildRelation getAuthenticationProxyChildRelation();
protected AuthenticationProxySbbLocalObject getAuthenticationProxy() {
try {
return (AuthenticationProxySbbLocalObject) getAuthenticationProxyChildRelation()
.create();
} catch (Exception e) {
logger.error("Failed to create child sbb", e);
return null;
}
}
public void onDelete(HttpServletRequestEvent event,
ActivityContextInterface aci) {
// detach from the activity
aci.detach(sbbContext.getSbbLocalObject());
HttpServletRequest request = event.getRequest();
HttpServletResponse response = event.getResponse();
try {
PrintWriter responseWriter = response.getWriter();
try {
// get xcap root from config
String xcapRoot = ServerConfiguration.XCAP_ROOT;
// create resource selector from request's uri & query
// string
ResourceSelector resourceSelector = Parser
.parseResourceSelector(xcapRoot, request
.getRequestURI(), request.getQueryString());
// user authentication
String user = getAuthenticationProxy().authenticate(request, response);
if (user == null) {
// authentication failed, stop processing request
return;
}
// check conditional request headers
// get ifMatch eTag
ETagValidator eTagValidator = null;
String eTag = request.getHeader(HttpConstant.HEADER_IF_MATCH);
if (eTag != null) {
eTagValidator = new IfMatchETagValidator(eTag);
} else {
eTag = request.getHeader(HttpConstant.HEADER_IF_NONE_MATCH);
if (eTag != null) {
eTagValidator = new IfNoneMatchETagValidator(eTag);
}
}
// delete in data source
if (logger.isInfoEnabled()) {
logger.info("delete(resourceSelector=" + resourceSelector
+ ",eTagValidator=" + eTagValidator + ",xcapRoot="
+ xcapRoot + ")");
}
WriteResult result = getRequestProcessor().delete(
resourceSelector, eTagValidator, xcapRoot,user);
// set response status
response.setStatus(result.getResponseStatus());
// set response entity tag if provided
if (result.getResponseEntityTag() != null) {
response.setHeader(HttpConstant.HEADER_ETAG, result
.getResponseEntityTag());
}
} catch (ParseException e) {
NotFoundException ne = new NotFoundException();
if (logger.isDebugEnabled())
logger.debug("invalid xcap uri, replying , replying "
+ ne.getResponseStatus());
response.setStatus(ne.getResponseStatus());
} catch (NotFoundException e) {
if (logger.isDebugEnabled())
logger.debug("doc/elem/attrib not found, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (ConflictException e) {
if (logger.isDebugEnabled())
logger.debug("conflict exception, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
responseWriter.print(e.getResponseContent());
} catch (MethodNotAllowedException e) {
if (logger.isDebugEnabled())
logger.debug("method not allowed, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
// add all exception headers
Map<String, String> exceptionHeaders = e.getResponseHeaders();
for (Iterator<String> i = exceptionHeaders.keySet().iterator(); i
.hasNext();) {
String headerName = i.next();
String headerValue = exceptionHeaders.get(headerName);
response.setHeader(headerName, headerValue);
}
} catch (PreconditionFailedException e) {
if (logger.isDebugEnabled())
logger.debug("precondition failed on etags, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (InternalServerErrorException e) {
logger.warn("internal server error: " + e.getMessage()
+ ", replying " + e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (BadRequestException e) {
if (logger.isDebugEnabled())
logger.debug("bad request, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
}
// send to client
responseWriter.close();
} catch (Exception e) {
logger.error("Error processing onDelete()", e);
}
}
public void onGet(HttpServletRequestEvent event,
ActivityContextInterface aci) {
// detach from the activity
aci.detach(sbbContext.getSbbLocalObject());
HttpServletRequest request = event.getRequest();
HttpServletResponse response = event.getResponse();
try {
PrintWriter responseWriter = response.getWriter();
try {
// create jxcap resource selector from request's uri & query
// string
ResourceSelector resourceSelector = Parser
.parseResourceSelector(ServerConfiguration.XCAP_ROOT,
request.getRequestURI(), request
.getQueryString());
// read result from data source
if (logger.isInfoEnabled()) {
logger.info("get(resourceSelector=" + resourceSelector
+ ")");
}
// user authentication
String user = getAuthenticationProxy().authenticate(request, response);
if (user == null) {
// authentication failed, stop processing request
return;
}
ReadResult result = getRequestProcessor().get(resourceSelector,user);
// get data object from result
Resource dataObject = result.getResponseDataObject();
// set response content type
response.setContentType(dataObject.getMimetype());
// set response entity tag
response.setHeader(HttpConstant.HEADER_ETAG, result
.getResponseEntityTag());
// add response content
responseWriter.println(dataObject.toXML());
} catch (ParseException e) {
NotFoundException ne = new NotFoundException();
logger.warn("invalid xcap uri, replying "
+ ne.getResponseStatus());
response.setStatus(ne.getResponseStatus());
} catch (NotFoundException e) {
if (logger.isDebugEnabled())
logger.debug("doc/elem/attrib not found, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (InternalServerErrorException e) {
logger.warn("internal server error: ");
response.setStatus(e.getResponseStatus());
} catch (BadRequestException e) {
if (logger.isDebugEnabled())
logger.debug("bad request, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
}
// send to client
responseWriter.close();
} catch (Exception e) {
logger.error("Error processing onGet()", e);
}
}
public void onPut(HttpServletRequestEvent event,
ActivityContextInterface aci) {
// detach from the activity
aci.detach(sbbContext.getSbbLocalObject());
HttpServletRequest request = event.getRequest();
HttpServletResponse response = event.getResponse();
try {
PrintWriter responseWriter = response.getWriter();
try {
// create resource selector from request's uri & query
// string
ResourceSelector resourceSelector = Parser
.parseResourceSelector(ServerConfiguration.XCAP_ROOT,
request.getRequestURI(), request
.getQueryString());
// user authentication
String user = getAuthenticationProxy().authenticate(request, response);
if (user == null) {
// authentication failed, stop processing request
return;
}
// check conditional request headers
// get ifMatch eTag
ETagValidator eTagValidator = null;
String eTag = request.getHeader(HttpConstant.HEADER_IF_MATCH);
if (eTag != null) {
eTagValidator = new IfMatchETagValidator(eTag);
} else {
eTag = request.getHeader(HttpConstant.HEADER_IF_NONE_MATCH);
if (eTag != null) {
eTagValidator = new IfNoneMatchETagValidator(eTag);
}
}
// get content mimetype
String mimetype = request.getContentType();
if (logger.isInfoEnabled()) {
logger.info("put(resourceSelector=" + resourceSelector
+ ",mimetype=" + mimetype + ",eTagValidator="
+ eTagValidator + ",xcapRoot="
+ ServerConfiguration.XCAP_ROOT + ")");
}
// put object in data source
WriteResult result = getRequestProcessor().put(
resourceSelector, mimetype, request.getInputStream(),
eTagValidator, ServerConfiguration.XCAP_ROOT,user);
// set response status
response.setStatus(result.getResponseStatus());
// set response entity tag with new one on result
response.setHeader(HttpConstant.HEADER_ETAG, result
.getResponseEntityTag());
} catch (ParseException e) {
// invalid resource selector
BadRequestException bre = new BadRequestException();
if (logger.isDebugEnabled())
logger.debug("invalid xcap uri, replying "
+ bre.getResponseStatus());
response.setStatus(bre.getResponseStatus());
} catch (IOException e) {
InternalServerErrorException ie = new InternalServerErrorException(
e.getMessage());
logger.warn("internal server error: " + e.getMessage()
+ ", replying " + ie.getResponseStatus());
response.setStatus(ie.getResponseStatus());
} catch (NoParentConflictException e) {
// add base uri
e
.setSchemeAndAuthorityURI(ServerConfiguration.SCHEME_AND_AUTHORITY_URI);
// add query string if exists
if (request.getQueryString() != null) {
e.setQueryComponent(request.getQueryString());
}
if (logger.isDebugEnabled())
logger.debug("no parent conflict exception, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
responseWriter.print(e.getResponseContent());
} catch (ConflictException e) {
if (logger.isDebugEnabled())
logger.debug("conflict exception, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
responseWriter.print(e.getResponseContent());
} catch (MethodNotAllowedException e) {
if (logger.isDebugEnabled())
logger.debug("method not allowed, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
// add all exception headers
Map<String, String> exceptionHeaders = e.getResponseHeaders();
for (Iterator<String> i = exceptionHeaders.keySet().iterator(); i
.hasNext();) {
String headerName = i.next();
String headerValue = exceptionHeaders.get(headerName);
response.setHeader(headerName, headerValue);
}
} catch (UnsupportedMediaTypeException e) {
if (logger.isDebugEnabled())
logger.debug("unsupported media exception, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (InternalServerErrorException e) {
logger.warn("internal server error: " + e.getMessage()
+ ", replying " + e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (PreconditionFailedException e) {
if (logger.isDebugEnabled())
logger.debug("precondition failed on etags, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
} catch (BadRequestException e) {
if (logger.isDebugEnabled())
logger.debug("invalid xcap uri, replying "
+ e.getResponseStatus());
response.setStatus(e.getResponseStatus());
}
// send to client
responseWriter.close();
} catch (Exception e) {
logger.error("Error processing onPut()", e);
}
}
// ######################################## NOT SUPPORTED METHODS
public void onPost(HttpServletRequestEvent event,
ActivityContextInterface aci) {
sendUnsupportedRequestErrorResponse(event, aci);
}
public void onHead(HttpServletRequestEvent event,
ActivityContextInterface aci) {
sendUnsupportedRequestErrorResponse(event, aci);
}
public void onOptions(HttpServletRequestEvent event,
ActivityContextInterface aci) {
sendUnsupportedRequestErrorResponse(event, aci);
}
public void onTrace(HttpServletRequestEvent event,
ActivityContextInterface aci) {
sendUnsupportedRequestErrorResponse(event, aci);
}
private void sendUnsupportedRequestErrorResponse(
HttpServletRequestEvent event, ActivityContextInterface aci) {
// detach from the activity
aci.detach(sbbContext.getSbbLocalObject());
// method not allowed, set right sc and allow header then send response
try {
HttpServletResponse response = event.getResponse();
response.setStatus(MethodNotAllowedException.RESPONSE_STATUS);
response.setHeader(HttpConstant.HEADER_ALLOW, "GET, PUT, DELETE");
response.flushBuffer();
} catch (Exception e) {
logger.error("unable to send response", e);
}
}
}