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} :
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NomeDescrizioneTipoObbligatorio
portaDelegataIDLa 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}.StringSi, a meno che non venga specificato nessuno dei seguenti parametri: soapURL, * sessionBeanID , ,serviceHttpURL e resourceXMLURL
sessionBeanIDLa 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}.StringSi, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID, * soapURL, ,serviceHttpURL e resourceXMLURL
serviceHttpURLLa 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}.StringSi, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID, * sessionBeanID , ,soapURL e resourceXMLURL
soapURLLa 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}. * StringSi, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID, * sessionBeanID , ,serviceHttpURL e resourceXMLURL
resourceXMLURLIdentifica 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}.StringSi, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID, * sessionBeanID , ,serviceHttpURL e soapURL
paginaNamespaceIdentifica 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}.StringSi, a meno che non venga specificato nessuno dei seguenti parametri: portaDelegataID, * sessionBeanID , ,serviceHttpURL e soapURL
* * @author Simone Casciaroli */ public abstract class AbstractMultiServiceServlet extends AbstractGeneralServlet { /** Il nome del parametro che definisce l'id della porta delegata da utilizzare. */ public static final String PNAME_PORTA_DELEGATA_ID = "portaDelegataID"; /** Il nome del parametro che definisce l'id del session bean da utilizzare come Servizio. */ public static final String PNAME_SESSION_BEAN_ID = "sessionBeanID"; /** Il nome del parametro che definisce l'URL della servlet remota da invocare. */ public static final String PNAME_SERVICE_HTTP_URL = "serviceHttpURL"; /** Il nome del parametro che definisce l'URL del servizio SOAP da richiamare. */ public static final String PNAME_SERVICE_SOAP_URL = "soapURL"; /** Il nome del parametro che definisce l'URL della risorsa XML da includere. */ public static final String PNAME_RESOURCE_XML_URL = "resourceXMLURL"; /** Il nome del parametro che definisce il namespace dell'elemento pagina. */ public static final String PNAME_NAMESPACE_ELEMENT = "paginaNamespace"; /** Il nome del parametro che definisce la SOAPAction per il servizio web. */ // public static final String PNAME_SOAP_ACTION = "soapAction"; /** Carattere che separa le coppie <path_servizio>:<path_xsl>. */ public static final String SEPARATORE_COPPIE_SERVIZIO_XSL = ";"; /** Carattere che separa il <path_servizio> dal <path_xsl> e da <soapAction>. */ public static final String SEPARATORE_SERVIZIO_XSL = ","; /** * Namespace del TAG Pagina, se non viene specificato nella configurazione verra' utilizzato il suo valore di * default (http://www.corenet.it). */ protected String paginaNamespace = "http://www.corenet.it"; /** L'array degli URL delle risorse (file XML) che si vuole parserizzare. */ protected String[] resourceXMLURL = null; /** * Contiene le informazioni necessarie alla gestione della chiamata ai servizi: id del servizio, inputstylesheet e */ protected List services = new ArrayList(); /** * Costruttore di default. */ public AbstractMultiServiceServlet() { super(); } /** * Provvede alla configurazione della servlet. Le servlet che ereditano da questa possono fare l'override di questo * metodo ma devo sempre invocare 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; } } }