package it.corenet.j2ee.servlet;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;
import org.w3c.dom.Document;
import it.corenet.j2ee.common.LogUtils;
/**
* Classe di base per l'implementazione di una applicazione servlet in cui e' necessario richiamano piu' servizi per
* creare la pagina. Questa classe fornisce i servizi di base per le comunicazioni con i servizi di back office.
* Le servlet che estendono questa non devono preoccuparsi di gestire le comunicazioni con i servizi che possono
* avvenire in quattro modi: a) per mezzo delle Porte Di Dominio; b) per mezzo di comunicazioni RMI/IIOP generiche (per
* soddisfare questa tipologia di canali di accesso il Servizio deve essere un EJB che espone una home interface di tipo
* {@link it.corenet.j2ee.servizi.ServizioRemoteHome ServizioRemoteHome}
(o una sottoclasse) e di
* conseguenza una remote interface di tipo {@link it.corenet.j2ee.servizi.ServizioRemote ServizioRemote}
* (o una sottoclasse)). c) per mezzo di una connessione HTTP con una servlet che espone dei servizi. d) per mezzo di
* comunicazioni SOAP di tipo messaging Inotre e' possibile richiamare, specificandolo nel parametro
* resourcesXMLURL
*
* , una risorsa XML su un server in modo da renderne disponibili i dati per la creazione della
* pagina della servlet
* La servlet permette la chiamata ai servizi con tipologie di comunicazione diversa. Ogni servizio da utilizzare deve
* essere specificato insieme al suo inputStylesheet ed, eventualmente, alla propria soapAction separati da un carattere
* ',' (<path_servizio>,<path_xsl>,<soapAction>); dato che possono essere specificati piu' servizi per
* ogni tipo di comunicazione le varie coppie/triple (<path_servizio>,<path_xsl>,<soapAction>) devono
* essere separate da ';'
* (<path_servizio>,<path_xsl>,<soapAction>;<path_servizio>,<path_xsl>;...). Alla stessa
* maniera e' possibile richiamare piu' risorse XML come URL separate da ';' (<URL_XML>;<URL_XML>;...).
* Le servlet che estendono da questa devono definire, nel deployment descriptor, i seguenti parametri (oltre a quelli
* previsti dalla {@link AbstractGeneralServlet} :
*
Nome | *Descrizione | *Tipo | *Obbligatorio | *
portaDelegataID |
* La stringa (<path_servizio>,<path_xsl>;<path_servizio>,<path_xsl>;...) che identifica
* i servizi, da richiamare con la Porta Delegata, e i rispettivi inputStylesheet. Il nome del parametro per uso
* applicativo, e' definito nella costante {@link #PNAME_PORTA_DELEGATA_ID} . |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: soapURL ,
* sessionBeanID , ,serviceHttpURL e resourceXMLURL |
*
sessionBeanID |
* La stringa (<path_servizio>,<path_xsl>;<path_servizio>,<path_xsl>;...) che identifica
* i servizi, da richiamare con RMI/IIOP, e i rispettivi inputStylesheet. Questo ID serve 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. Il nome del parametro,
* per uso applicativo, e' definito nella costante {@link #PNAME_SESSION_BEAN_ID} . |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID ,
* soapURL , ,serviceHttpURL e resourceXMLURL |
*
serviceHttpURL |
* La stringa (<path_servizio>,<path_xsl>;<path_servizio>,<path_xsl>;...) che identifica
* i servizi, da richiamare per mezzo di una connessione HTTP, e i rispettivi inputStylesheet. Il nome del
* parametro, per uso applicativo, e' definito nella costante {@link #PNAME_SERVICE_HTTP_URL} . |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID ,
* sessionBeanID , ,soapURL e resourceXMLURL |
*
soapURL |
* La stringa
* (<path_servizio>,<path_xsl>,<soapAction>;<path_servizio>,<path_xsl>;...) che
* identifica i servizi, da richiamare per mezzo di una connessione SOAP, e i rispettivi inputStylesheet. Il nome
* del parametro, per uso applicativo, e' definito nella costante {@link #PNAME_SERVICE_SOAP_URL} .
* |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID ,
* sessionBeanID , ,serviceHttpURL e resourceXMLURL |
*
resourceXMLURL |
* Identifica una risorsa (file in formato XML disponibile su qualunque server) i cui dati vogliono essere
* inseriti nella pagina di output. Il nome del parametro, per uso applicativo, e' definito nella costante
* {@link #PNAME_SERVICE_XML_URL} . |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID ,
* sessionBeanID , ,serviceHttpURL e soapURL |
*
paginaNamespace |
* Identifica il namespace da usare per gli elementi della risposta xml generata dalla servlet, se non viene
* impostato nessun namespace viene utilizzato http://www.corenet.it Il nome del parametro, per uso applicativo,
* e' definito nella costante {@link #PNAME_NAMESPACE_ELEMENT} . |
* String |
* Si, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID ,
* sessionBeanID , ,serviceHttpURL e soapURL |
*
super.init(config)
.
*
* @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);
initPortaDelegata(config);
initServletURL(config);
initSoapURL(config);
initXMLResources(config);
/* in initStylesheets vengono inizializzati solo gli Stylesheets di output e FOP
* l'inizializzazione degli shylesheets di input e demandata ai metodi diinizializzazione dei singoli metodi di
* comunicazione */
initStylesheets(config);
// inizializza il namespace da usare con gli elementi della risposta xml
// generati dalla servlet
String namespace = config.getInitParameter(PNAME_NAMESPACE_ELEMENT);
if (namespace != null)
{
paginaNamespace = namespace;
}
}
/**
* Processa la richiesta e produce un documento XML da passare al servizio.
*
* @param source la richiesta da processare
* @param rootName il nome dell'elemento radice
* @param inputStylesheetTemplate lo stylesheet di input da applicare
*
* @return il documento di richiesta da inviare al servizio
*
* @throws ServletException in caso di errore
*/
protected Document transformDataRequest(HttpServletRequest source, String rootName,
Templates inputStylesheetTemplate)
throws ServletException
{
try
{
Document intermediateDoc = ServletToolBox.createRequestDocument(source, rootName);
LogUtils.logXMLDocument("Documento intermedio", intermediateDoc, logger);
Document serviceReq = ServletToolBox.transformDataRequest(source, rootName,
((rootName != XML_ELEMENT_PRECOMPILAZIONE_ROOT) ? inputStylesheetTemplate : null));
LogUtils.logXMLDocument("Richiesta Servizio", serviceReq, logger);
return serviceReq;
}
catch (ServletException se)
{
logger.error("ECCEZIONE COMPLETA: " + LogUtils.getCompleteExceptionString(se));
throw se;
}
catch (ParserConfigurationException parsEx)
{
logger.error("ECCEZIONE COMPLETA: " + LogUtils.getCompleteExceptionString(parsEx));
throw new ServletException(parsEx);
}
}
/**
* Processa la richiesta e produce un documento XML da passare al servizio.
*
* @param source la richiesta da processare
* @param rootName il nome dell'elemento radice
* @param inputStylesheetTemplate lo stylesheet di input da applicare
*
* @return il reader da cui ottenere il documento di richiesta da inviare al servizio
*
* @throws ServletException in caso di errore
*/
protected Reader transformDataRequestUseStream(HttpServletRequest source, String rootName,
Templates inputStylesheetTemplate)
throws ServletException
{
try
{
Document intermediateDoc = ServletToolBox.createRequestDocument(source, rootName);
LogUtils.logXMLDocument("Documento intermedio", intermediateDoc, logger);
return ServletToolBox.transformDataRequestUseStream(source, rootName,
((rootName != XML_ELEMENT_PRECOMPILAZIONE_ROOT) ? inputStylesheetTemplate : null));
}
catch (ServletException se)
{
logger.error("ECCEZIONE COMPLETA: " + LogUtils.getCompleteExceptionString(se));
throw se;
}
catch (ParserConfigurationException parsEx)
{
logger.error("ECCEZIONE COMPLETA: " + LogUtils.getCompleteExceptionString(parsEx));
throw new ServletException(parsEx);
}
}
/**
* Recupera gli ID dei session bean che rappresentano i servizi e gli inputShylesheet da utilizzare per la creazione
* della richiesta.
*
* @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
{
String globalConfString = config.getInitParameter(PNAME_SESSION_BEAN_ID);
if ((globalConfString != null) && !("".equals(globalConfString)))
{
String[] singleConfString = globalConfString.split(SEPARATORE_COPPIE_SERVIZIO_XSL);
for (int i = 0; i < singleConfString.length; i++)
{
String[] temporalArray = singleConfString[i].split(SEPARATORE_SERVIZIO_XSL);
if (temporalArray.length == 2)
{
ServiceConf serviceC = new ServiceConf();
serviceC.setComunicationType(ServletToolBox.EJB_COMMUNICATION_MODE_NAME);
serviceC.setServiceID(temporalArray[0]);
logger.debug("Il bean utilizzato e' " + temporalArray[0]);
serviceC.setInputStylesheetTemplate(compileStylesheet(config, temporalArray[1]));
logger.debug("Lo stylesheet utilizzato e'" + temporalArray[1]);
services.add(serviceC);
}
else
{
throw new ServletException(
"Impossibile determinare l'id e l'inputStylesheet di un dei session bean dalla configurazione corrente. Controllare il parametro '" +
PNAME_SESSION_BEAN_ID + "'");
}
}
}
}
/**
* Recupera gli ID delle Porta Delegata che rappresentano i servizi e gli inputShylesheet da utilizzare per la
* creazione della richiesta.
*
* @param config la configurazione della servlet
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
*/
private void initPortaDelegata(ServletConfig config)
throws ServletException
{
String globalConfString = config.getInitParameter(PNAME_PORTA_DELEGATA_ID);
if ((globalConfString != null) && !("".equals(globalConfString)))
{
String[] singleConfString = globalConfString.split(SEPARATORE_COPPIE_SERVIZIO_XSL);
for (int i = 0; i < singleConfString.length; i++)
{
String[] temporalArray = singleConfString[i].split(SEPARATORE_SERVIZIO_XSL);
if (temporalArray.length == 2)
{
ServiceConf serviceC = new ServiceConf();
serviceC.setComunicationType(ServletToolBox.PDD_COMMUNICATION_MODE_NAME);
serviceC.setServiceID(temporalArray[0]);
logger.debug("La porta applicativa utilizzata e' " + temporalArray[0]);
serviceC.setInputStylesheetTemplate(compileStylesheet(config, temporalArray[1]));
logger.debug("Lo stylesheet utilizzato e'" + temporalArray[1]);
services.add(serviceC);
}
else
{
throw new ServletException(
"Impossibile determinare l'id e l'inputStylesheet di un delle porte delegata dalla configurazione corrente. Controllare il parametro '" +
PNAME_PORTA_DELEGATA_ID + "'");
}
}
}
}
/**
* Recupera gli URL delle servlet e e gli inputShylesheet da utilizzare per la creazione della richiesta.
*
* @param config la configurazione della servlet
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
*/
private void initServletURL(ServletConfig config)
throws ServletException
{
String globalConfString = config.getInitParameter(PNAME_SERVICE_HTTP_URL);
if ((globalConfString != null) && !("".equals(globalConfString)))
{
String[] singleConfString = globalConfString.split(SEPARATORE_COPPIE_SERVIZIO_XSL);
for (int i = 0; i < singleConfString.length; i++)
{
String[] temporalArray = singleConfString[i].split(SEPARATORE_SERVIZIO_XSL);
if (temporalArray.length == 2)
{
ServiceConf serviceC = new ServiceConf();
serviceC.setComunicationType(ServletToolBox.HTTP_COMMUNICATION_MODE_NAME);
serviceC.setServiceID(temporalArray[0]);
logger.debug("L'URL utilizzato e' " + temporalArray[0]);
serviceC.setInputStylesheetTemplate(compileStylesheet(config, temporalArray[1]));
logger.debug("Lo stylesheet utilizzato e'" + temporalArray[1]);
services.add(serviceC);
}
else
{
throw new ServletException(
"Impossibile determinare l'URL e l'inputStylesheet di un delle servlet dalla configurazione corrente. Controllare il parametro '" +
PNAME_SERVICE_HTTP_URL + "'");
}
}
}
}
/**
* Inizializza gli URL dei servizi SOAP da utilizzare e gli inputShylesheet da utilizzare per la creazione della
* richiesta.
*
* @param config la configurazione della servlet
*
* @throws ServletException se la configurazione non e' corretta o manca di dati essenziali.
*/
private void initSoapURL(ServletConfig config)
throws ServletException
{
String globalConfString = config.getInitParameter(PNAME_SERVICE_SOAP_URL);
if ((globalConfString != null) && !("".equals(globalConfString)))
{
String[] singleConfString = globalConfString.split(SEPARATORE_COPPIE_SERVIZIO_XSL);
// L'array soapActionArray, se presenta degli elementi, deve avere la stessa dimensione di singleConfString
for (int i = 0; i < singleConfString.length; i++)
{
String[] temporalArray = singleConfString[i].split(SEPARATORE_SERVIZIO_XSL);
if ((temporalArray.length == 2) || (temporalArray.length == 3))
{
ServiceConf serviceC = new ServiceConf();
serviceC.setComunicationType(ServletToolBox.SOAP_COMMUNICATION_MODE_NAME);
serviceC.setServiceID(temporalArray[0]);
logger.debug("Il servizio SOAP utilizzato e' " + temporalArray[0]);
serviceC.setInputStylesheetTemplate(compileStylesheet(config, temporalArray[1]));
logger.debug("Lo stylesheet utilizzato e'" + temporalArray[1]);
// Impostiamo la SOAPAction, se necessario
if (temporalArray.length == 3)
{
serviceC.setSoapAction(temporalArray[2]);
logger.debug("La soapAction impostata e' " + temporalArray[2]);
}
services.add(serviceC);
}
else
{
throw new ServletException(
"Impossibile determinare l'URL e l'inputStylesheet di uno dei servizi SOAP dalla configurazione corrente. Controllare il parametro '" +
PNAME_SERVICE_SOAP_URL + "'");
}
}
}
}
/**
* Inizializza gli URL delle risorse XML che si vuole inserire nella pagina.
*
* @param config la configurazione della servlet
*/
private void initXMLResources(ServletConfig config)
{
String globalConfString = config.getInitParameter(PNAME_RESOURCE_XML_URL);
if ((globalConfString != null) && !("".equals(globalConfString)))
{
resourceXMLURL = globalConfString.split(SEPARATORE_COPPIE_SERVIZIO_XSL);
for (int i = 0; i < resourceXMLURL.length; i++)
{
logger.debug("L'URL della risorsa XML utilizzata e' " + resourceXMLURL[i]);
}
}
}
/**
* Classe contenitore, mantiene le informazioni legate al servizio: id del servizio, inputStylesheet, tipo di
* comunicazione e SOAP action
*
* @author Simone Casciaroli
*/
protected class ServiceConf
{
/** tipologia di comunicazione EJB,PDD,HTTP,SOAP. */
private String comunicationType = null;
/** template da utilizzare per la creazione della richiesta del servizio. */
private Templates inputStylesheetTemplate = null;
/** id del servizio. */
private String serviceID = null;
/** SOAPAction per il servizio web da richiamare. */
private String soapAction = null;
/**
* Default constructor.
*/
protected ServiceConf()
{
super();
}
/**
* Returns the comunicationType.
*
* @return Returns the comunicationType.
*/
public String getComunicationType()
{
return comunicationType;
}
/**
* Returns the inputStylesheetTemplate.
*
* @return Returns the inputStylesheetTemplate.
*/
public Templates getInputStylesheetTemplate()
{
return inputStylesheetTemplate;
}
/**
* Returns the serviceID.
*
* @return Returns the serviceID.
*/
public String getServiceID()
{
return serviceID;
}
/**
* Returns the soapAction.
*
* @return Returns the soapAction.
*/
public String getSoapAction()
{
return soapAction;
}
/**
* Sets the comunicationType.
*
* @param comunicationType The comunicationType to set.
*/
public void setComunicationType(String comunicationType)
{
this.comunicationType = comunicationType;
}
/**
* Sets the inputStylesheetTemplate.
*
* @param inputStylesheetTemplate The inputStylesheetTemplate to set.
*/
public void setInputStylesheetTemplate(Templates inputStylesheetTemplate)
{
this.inputStylesheetTemplate = inputStylesheetTemplate;
}
/**
* Sets the serviceID.
*
* @param serviceID The serviceID to set.
*/
public void setServiceID(String serviceID)
{
this.serviceID = serviceID;
}
/**
* Sets the soapAction.
*
* @param soapAction The soapAction to set.
*/
public void setSoapAction(String soapAction)
{
this.soapAction = soapAction;
}
}
}