package it.corenet.j2ee.servlet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.StringTokenizer;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
// import javax.xml.messaging.JAXMServlet;
// import javax.xml.messaging.ReqRespListener;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.apache.log4j.Logger;
import it.corenet.j2ee.common.LogUtils;
import it.corenet.j2ee.consumer.SOAPConsumer;
import it.corenet.j2ee.messages.Message;
/**
* Servlet che si occupa di ricevere messaggi SOAP, leggerne il body e spedire quest'ultimo ai servizi di back-end
* (EJB). Le risposte ricevute dai servizi vengono analogamente reimbustate e spedite al client nel body di un altro
* messaggio SOAP.
*
*
La servlet che deve definire, nel deployment descriptor, i seguenti parametri:
*
*
*
*
* Nome |
* Descrizione |
* Tipo |
* Obbligatorio |
*
*
* sessionBeanID |
* L'identificativo del session bean da utilizzare per le comunicazioni con il servizio . Questo ID server per
* fare il lookup sul JNDI context per recuperare la home interface del bean. La home interface deve essere una
* {@link it.corenet.j2ee.servizi.ServizioRemoteHome ServizioRemoteHome} o una sottoclasse. |
* String |
* Si |
*
*
*
* @author Federico Lelli
* @cvsauthor $Author: flelli $
* @cvsdate $Date: 2008/03/18 11:20:25 $
* @cvsrevision $Revision: 1.5 $
*/
// public class SOAPDispatcherServlet extends JAXMServlet implements ReqRespListener
public class SOAPDispatcherServlet extends HttpServlet
{
/** Il nome del parametro che definisce l'id del session bean da utilizzare come Servizio. */
public static final String PNAME_SESSION_BEAN_ID = "sessionBeanID";
/** L'ID della home interface del bean utilizzato come servizio. */
private String beanID = null;
/** Il logger di log4j. */
private Logger logger = null;
/** L'istanza della message factory. */
private MessageFactory msgFactory = null;
/**
* Inizializza il logger.
*/
public SOAPDispatcherServlet()
{
super();
logger = Logger.getLogger(this.getClass());
}
/**
* Interpreta la richiesta http e scrive la risposta.
*
* @param request la richiesta
* @param response la risposta
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
* @throws IOException in caso di errori di IO o di comunicazione remota
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// logger.debug("Ricevuto messaggio SOAP");
try
{
MimeHeaders headers = getHeaders(request);
ServletInputStream sis = request.getInputStream();
SOAPMessage soapReq = msgFactory.createMessage(headers, sis);
logMessage("Ricevuto il messaggio SOAP di richiesta", soapReq);
Message req = SOAPConsumer.fromSOAPMessage(soapReq);
Message resp = ServletToolBox.performRequest(req, beanID, "EJB");
SOAPMessage soapResp = SOAPConsumer.toSOAPMessage(resp);
logMessage("Istanziato il messaggio SOAP di risposta", soapResp);
if (soapResp.saveRequired())
{
soapResp.saveChanges();
}
response.setStatus(200);
putHeaders(soapResp.getMimeHeaders(), response);
ServletOutputStream sos = response.getOutputStream();
soapResp.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
if (soapResp.countAttachments() > 0) {
// Workaround JBWS-1620 (https://issues.jboss.org/browse/JBWS-1620)
response.setHeader("Content-Length", Integer.toString(Integer.parseInt(soapResp.getMimeHeaders().getHeader("Content-Length")[0]) + 2));
sos.write(13);
sos.write(10);
}
soapResp.writeTo(sos);
sos.flush();
}
catch (SOAPException se)
{
logger.error("ECCEZIONE COMPLETA: " + LogUtils.getCompleteExceptionString(se));
throw new ServletException(se);
}
}
/**
* Provvede alla configurazione della servlet.
*
* @param config la configurazione della servlet
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
*/
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
initEJB(config);
try
{
msgFactory = MessageFactory.newInstance();
}
catch (SOAPException se)
{
throw new ServletException("Unable to create message factory", se);
}
}
/**
* Stampa il messaggio di log.
*
* @param arg0 la stringa da stampare
*
* @see javax.servlet.GenericServlet#log(String)
*/
public void log(String arg0)
{
logger.debug(arg0);
}
/**
* Stampa il messaggio di log.
*
* @param arg0 la stringa da stampare
* @param arg1 l'eccezione o errore da stampare
*
* @see javax.servlet.GenericServlet#log(String, Throwable)
*/
public void log(String arg0, Throwable arg1)
{
logger.debug(arg0, arg1);
}
/**
* Recupera le header MIME dalla richiesta.
*
* @param request la richiesta http
*
* @return le header MIME
*/
private static MimeHeaders getHeaders(HttpServletRequest request)
{
Enumeration en = request.getHeaderNames();
MimeHeaders headers = new MimeHeaders();
while (en.hasMoreElements())
{
String s = (String)en.nextElement();
String s1 = request.getHeader(s);
for (StringTokenizer st = new StringTokenizer(s1, ","); st.hasMoreTokens();
headers.addHeader(s, st.nextToken().trim()))
{
;
}
}
return headers;
}
/**
* Imposta le header MIME sulla risposta.
*
* @param headers le headers
* @param response la risposta http
*/
private static void putHeaders(MimeHeaders headers, HttpServletResponse response)
{
for (Iterator it = headers.getAllHeaders(); it.hasNext();)
{
MimeHeader header = (MimeHeader)it.next();
String[] as = headers.getHeader(header.getName());
if (as.length == 1)
{
response.setHeader(header.getName(), header.getValue());
}
else
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < as.length; i++)
{
if (i != 0)
{
sb.append(',');
}
sb.append(as[i]);
}
response.setHeader(header.getName(), sb.toString());
}
}
}
/**
* Recupera il session bean che rappresenta il servizio .
*
* @param config la configurazione della servlet
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
*/
private void initEJB(ServletConfig config)
throws ServletException
{
beanID = config.getInitParameter(PNAME_SESSION_BEAN_ID);
logger.debug("Il bean utilizzato e' " + beanID);
if ((beanID == null) || ("".equals(beanID)))
{
throw new ServletException(
"Impossibile determinare l'id del session bean dalla configurazione corrente. Definire il parametro '" +
PNAME_SESSION_BEAN_ID + "'");
}
}
/**
* Stampa il messaggio SOAP.
*
* @param commento commento al messaggio da stampare
* @param mesg il messaggio da stampare
*/
private void logMessage(String commento, SOAPMessage mesg)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mesg.writeTo(baos);
logger.debug(commento + ": " + new String(baos.toByteArray()));
}
catch (IOException ioe)
{
logger.debug("Si e' verificato un errore di I/O durante il dump del messaggio SOAP", ioe);
}
catch (SOAPException se)
{
logger.debug("Si e' verificato un errore SOAP durante il dump del messaggio SOAP", se);
}
}
}