/**
* It provides the classes for the listening HTTP Request for
* incoming and outgoing, and the request and response model
* for SFRM.
*/
package hk.hku.cecid.edi.sfrm.listener;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import javax.mail.internet.InternetHeaders;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import hk.hku.cecid.edi.sfrm.pkg.SFRMMessage;
import hk.hku.cecid.edi.sfrm.pkg.SFRMMessageException;
import hk.hku.cecid.edi.sfrm.spa.SFRMProcessor;
import hk.hku.cecid.piazza.commons.io.IOHandler;
import hk.hku.cecid.piazza.commons.servlet.RequestListenerException;
import hk.hku.cecid.piazza.commons.servlet.http.HttpRequestAdaptor;
import hk.hku.cecid.piazza.commons.security.SMimeException;
import hk.hku.cecid.piazza.commons.util.Headers;
/**
* This is the sfrm customizied HTTP Request Adaptor.
*
* @author Twinsen
* @version 1.0.0
* @since 1.0.0
*
* @see hk.hku.cecid.piazza.commons.servlet.http.HttpRequestAdaptor
*/
public abstract class SFRMRequestAdaptor extends HttpRequestAdaptor {
/**
* It process a HTTP request from the piazza corvus framework.
*
* @param request
* The HTTP Request
* @param response
* The HTTP Response
* @return
* @throws RequestListenerException
* @see hk.hku.cecid.piazza.commons.servlet.http.HttpRequestListener#processRequest(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public String processRequest(HttpServletRequest request,
HttpServletResponse response) throws RequestListenerException {
try {
Headers headers = new Headers(request, response);
// Create the HTTP headers.
InternetHeaders requestHeaders = headers.getInternetHeaders();
InputStream requestStream = request.getInputStream();
SFRMMessage requestMessage = new SFRMMessage(requestHeaders, requestStream);
if (requestMessage.getPartnershipId() == null){
// TODO: Do we need to do more validation to prevent expensive rollback?
response.sendError(HttpURLConnection.HTTP_BAD_REQUEST, "Invalid SFRM Message");
return null;
}
// Redirect request
SFRMRequest sfrmrequest = new SFRMRequest(request);
sfrmrequest.setMessage(requestMessage);
SFRMResponse sfrmresponse = new SFRMResponse(response);
this.processRequest(sfrmrequest, sfrmresponse);
SFRMMessage responseMessage = sfrmresponse.getMessage();
if (responseMessage == null) {
return null;
}
InternetHeaders responseHeaders = responseMessage.getHeaders();
headers.putInternetHeaders(responseHeaders);
InputStream contentStream= responseMessage.getContentStream();
OutputStream responseStream= response.getOutputStream();
IOHandler.pipe(contentStream, responseStream);
return null;
}
catch (Exception e) {
try{
return this.processFail(request, response, e);
}
catch(Exception ex){
throw new RequestListenerException(
"Error in processing SFRM request", ex);
}
}
}
/**
* It process a HTTP request from the piazza corvus framework
* when there is exception thrown from underlying handler.
*
* @param request
* The HTTP Request
* @param response
* The HTTP Response
* @param cause
* The exception cause to fail.
* @return
*/
public String processFail(HttpServletRequest request,
HttpServletResponse response, Exception cause) throws IOException {
if ( cause == null )
return null; // No Exception or unknown exception type.
// Get the actual exception.
Throwable actualCause = cause.getCause();
SFRMProcessor.getInstance().getLogger().error("Fail to receive: ", cause);
// -----------------------------------------------------------
// Error handling
//
// HTTP 403 (Forbidden):
// when the partnership setup is missing or invalid message
// security setup
// HTTP 401 (Unauthorized):
// when the certificate or the private key in the keystore can
// not de-crypt and unsign the message
// HTTP 412
// HTTP 500
// -----------------------------------------------------------
if (actualCause instanceof MalformedURLException ||
actualCause instanceof GeneralSecurityException)
response.sendError(HttpURLConnection.HTTP_FORBIDDEN,
actualCause.getMessage());
else
if (actualCause instanceof CertificateException ||
actualCause instanceof KeyStoreException ||
actualCause instanceof SMimeException)
response.sendError(HttpURLConnection.HTTP_UNAUTHORIZED,
actualCause.getMessage());
else
if (actualCause instanceof SFRMMessageException)
response.sendError(HttpURLConnection.HTTP_PRECON_FAILED,
actualCause.getMessage());
else
if (actualCause instanceof IOException)
response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR,
actualCause.getMessage());
else
response.sendError(HttpURLConnection.HTTP_BAD_REQUEST,
actualCause.getMessage());
// Log error.
return null;
}
/**
*
* @param request
* @param response
* @throws RequestListenerException
*/
abstract public void processRequest(SFRMRequest request, SFRMResponse response)
throws RequestListenerException;
}