OperationFinder.java
- /*
- * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 Link.it srl (https://link.it).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3, as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package org.openspcoop2.protocol.engine.mapping;
- import org.openspcoop2.core.config.driver.DriverConfigurazioneException;
- import org.openspcoop2.core.config.driver.DriverConfigurazioneNotFound;
- import org.openspcoop2.core.id.IDServizio;
- import org.openspcoop2.core.id.IDSoggetto;
- import org.openspcoop2.core.registry.Operation;
- import org.openspcoop2.core.registry.PortType;
- import org.openspcoop2.core.registry.Resource;
- import org.openspcoop2.core.registry.driver.DriverRegistroServiziException;
- import org.openspcoop2.core.registry.driver.DriverRegistroServiziNotFound;
- import org.openspcoop2.core.registry.wsdl.WSDLValidatorConfig;
- import org.openspcoop2.message.MessageUtils;
- import org.openspcoop2.message.OpenSPCoop2Message;
- import org.openspcoop2.message.constants.MessageType;
- import org.openspcoop2.message.constants.ServiceBinding;
- import org.openspcoop2.message.rest.RestUtilities;
- import org.openspcoop2.message.soap.SoapUtils;
- import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
- import org.openspcoop2.protocol.engine.constants.ModalitaIdentificazioneAzione;
- import org.openspcoop2.protocol.registry.RegistroServiziManager;
- import org.openspcoop2.protocol.sdk.Busta;
- import org.openspcoop2.protocol.sdk.IProtocolFactory;
- import org.openspcoop2.protocol.sdk.constants.InformationApiSource;
- import org.openspcoop2.protocol.sdk.state.RequestInfo;
- import org.openspcoop2.protocol.utils.PorteNamingUtils;
- import org.openspcoop2.utils.regexp.RegularExpressionEngine;
- import org.openspcoop2.utils.rest.api.ApiOperation;
- import org.openspcoop2.utils.transport.TransportRequestContext;
- import org.openspcoop2.utils.transport.http.HttpRequestMethod;
- import org.openspcoop2.utils.xml.AbstractXPathExpressionEngine;
- import org.openspcoop2.utils.xml2json.JsonXmlPathExpressionEngine;
- import org.slf4j.Logger;
- import org.w3c.dom.Element;
- /**
- * OperationFinder
- *
- * @author Andrea Poli (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class OperationFinder {
-
- private OperationFinder() {}
- private static String getPrefixIdentificazione(ModalitaIdentificazioneAzione modalitaIdentificazione) {
- return "Identificazione '"+modalitaIdentificazione.getValue()+"' ";
- }
-
- public static String getAzione(RegistroServiziManager registroServiziManager,TransportRequestContext transportContext, RequestInfo requestInfo,
- OpenSPCoop2Message message, OpenSPCoop2MessageSoapStreamReader soapStreamReader,
- IDSoggetto soggettoErogatore, IDServizio idServizio,
- boolean readFirstHeaderIntegrazione, String azioneHeaderIntegrazione,
- IProtocolFactory<?> protocolFactory,
- ModalitaIdentificazioneAzione modalitaIdentificazione, String pattern,
- boolean forceRegistryBased, boolean forcePluginBased,
- Logger log, boolean portaApplicativa,
- boolean bufferMessageReadOnly , String idTransazione,
- WSDLValidatorConfig config) throws DriverConfigurazioneException, IdentificazioneDinamicaException {
-
- try{
- if(soggettoErogatore!=null) {
- // nop
- }
-
- // Recupero Lista di Azioni
- /**
- List<String> listaAzioni = new ArrayList<>();
- boolean rest = false;
- try {
- AccordoServizioParteSpecifica asps = registroServiziManager.getAccordoServizioParteSpecifica(idServizio, null, false);
- AccordoServizioParteComune aspc = registroServiziManager.getAccordoServizioParteComune(IDAccordoFactory.getInstance().getIDAccordoFromUri(asps.getAccordoServizioParteComune()), null, false);
- if(org.openspcoop2.core.registry.constants.ServiceBinding.REST.equals(aspc.getServiceBinding())) {
- rest = true;
- for (Resource r : aspc.getResourceList()) {
- listaAzioni.add(r.getNome());
- }
- }
- else {
- if(asps.getPortType()==null) {
- for (Azione a : aspc.getAzioneList()) {
- listaAzioni.add(a.getNome());
- }
- }
- else {
- for (PortType pt: aspc.getPortTypeList()) {
- if(pt.getNome().equals(asps.getPortType())) {
- for (Operation a : pt.getAzioneList()) {
- listaAzioni.add(a.getNome());
- }
- break;
- }
- }
- }
- }
- }catch(Throwable t) {
- // ignoro errori, li sollevo in altri posti
- }*/
-
- boolean registryBased = false;
- boolean pluginBased = false;
-
- String azione = null;
- Exception eAzione = null;
- try{
- if(ModalitaIdentificazioneAzione.STATIC.equals(modalitaIdentificazione)){
- // STATIC-BASED
- azione = idServizio.getAzione();
- }
- else{
- if(readFirstHeaderIntegrazione && azioneHeaderIntegrazione!=null){
- // INTEGRATIONMANAGER INPUT
- azione = azioneHeaderIntegrazione;
- }
- else{
- if(ModalitaIdentificazioneAzione.URL_BASED.equals(modalitaIdentificazione)){
- // URL-BASED
- String urlInvocazionePD = transportContext.getUrlInvocazione_formBased();
- azione = RegularExpressionEngine.getStringFindPattern(urlInvocazionePD, pattern); // Sostituito Match con Find per applicare l'espressione regolare che risolve il bug OP-1590
- if(ServiceBinding.REST.equals(message.getServiceBinding())){
- throw new DriverConfigurazioneNotFound(getPrefixIdentificazione(modalitaIdentificazione)+
- "non supportata per il service binding '"+ServiceBinding.REST+"'");
- }
- }
- else if(ModalitaIdentificazioneAzione.HEADER_BASED.equals(modalitaIdentificazione)){
- // HEADER-BASED
- azione = transportContext.getHeaderFirstValue(pattern);
- }
- else if(ModalitaIdentificazioneAzione.CONTENT_BASED.equals(modalitaIdentificazione)){
- // CONTENT-BASED
- if(message==null){
- throw new DriverConfigurazioneNotFound("Messaggio non fornito");
- }
- AbstractXPathExpressionEngine xPathEngine = null;
- Element element = null;
- String elementJson = null;
- boolean checkSoapBodyEmpty = false; // devo poter fare xpath anche su soapBody empty
- if(message!=null) {
- element = MessageUtils.getContentElement(message, checkSoapBodyEmpty, bufferMessageReadOnly, idTransazione);
- elementJson = MessageUtils.getContentString(message, bufferMessageReadOnly, idTransazione);
- }
- if(element!=null) {
- xPathEngine = new org.openspcoop2.message.xml.XPathExpressionEngine(message.getFactory());
- azione = AbstractXPathExpressionEngine.extractAndConvertResultAsString(element, xPathEngine, pattern, log);
- }
- else if(elementJson!=null){
- azione = JsonXmlPathExpressionEngine.extractAndConvertResultAsString(elementJson, pattern, log);
- }
- else{
- throw new DriverConfigurazioneNotFound(getPrefixIdentificazione(modalitaIdentificazione)+"non supportata per il message-type '"+message.getMessageType()+"'");
- }
- }
- else if(ModalitaIdentificazioneAzione.INPUT_BASED.equals(modalitaIdentificazione)){
- // INPUT-BASED
- if(azioneHeaderIntegrazione!=null){
- azione = azioneHeaderIntegrazione;
- }
- else{
- throw new DriverConfigurazioneNotFound("Azione non indicata negli header di integrazione");
- }
- }
- else if(ModalitaIdentificazioneAzione.SOAP_ACTION_BASED.equals(modalitaIdentificazione)){
- // SOAP-ACTION-BASED
- if(message!=null && ServiceBinding.REST.equals(message.getServiceBinding())){
- throw new DriverConfigurazioneNotFound(getPrefixIdentificazione(modalitaIdentificazione)+
- "non supportata per il service binding '"+ServiceBinding.REST+"'");
- }
- if(message!=null){
- azione = message.castAsSoap().getSoapAction();
- }
- else{
- // provo una soluzione veloce di vedere se è presente nell'header di trasporto o nel content-type
- // non so che tipo di message type possiedo
- azione = getSoapAction(transportContext);
- }
- String azioneNonRipulita = azione;
- if(azione!=null){
- azione = azione.trim();
- // Nota: la soap action potrebbe essere quotata con ""
- if(azione.startsWith("\"")){
- azione = azione.substring(1);
- }
- if(azione.endsWith("\"")){
- azione = azione.substring(0,(azione.length()-1));
- }
- }
-
- // Provo a fare la traduzione tramite soapAction registrata nell'accordo
- if(azioneNonRipulita!=null || azione!=null) {
- org.openspcoop2.core.registry.wsdl.AccordoServizioWrapper wrapper = registroServiziManager.getWsdlAccordoServizio(idServizio,InformationApiSource.SAFE_SPECIFIC_REGISTRY,false,false, requestInfo);
- if(wrapper!=null){
- for (int i = 0; i < wrapper.sizePortTypeList(); i++) {
- PortType pt = wrapper.getPortType(i);
- if(wrapper.getNomePortType()!=null &&
- !pt.getNome().equals(wrapper.getNomePortType())){
- continue;
- }
- for (int j = 0; j < pt.sizeAzioneList(); j++) {
- Operation op = pt.getAzione(j);
- if(
- (azioneNonRipulita!=null && azioneNonRipulita.equals(op.getSoapAction()))
- ||
- (azione!=null && azione.equals(op.getSoapAction()))
- ) {
- /**System.out.println("RESOLVE 1 ["+azioneNonRipulita+"]");*/
- /**System.out.println("RESOLVE 2 ["+azione+"]");*/
- azione = op.getNome();
- break;
- }
- }
- }
- }
- }
-
- if(azione!=null &&
- "".equals(azione)){
- azione = null;
- throw new DriverConfigurazioneNotFound("SoapAction vuota ("+message.castAsSoap().getSoapAction()+") non è utilizzabile con una identificazione '"+
- ModalitaIdentificazioneAzione.SOAP_ACTION_BASED.getValue()+"'");
- }
-
- }
- else if(ModalitaIdentificazioneAzione.INTERFACE_BASED.equals(modalitaIdentificazione)){
- // INTERFACE-BASED
- registryBased = true;
- OperationFinder.checkIDServizioPerRiconoscimentoAzione(idServizio, modalitaIdentificazione);
- org.openspcoop2.core.registry.constants.ServiceBinding serviceBinding = registroServiziManager.getServiceBinding(idServizio, requestInfo);
- if(org.openspcoop2.core.registry.constants.ServiceBinding.SOAP.equals(serviceBinding)){
- azione = OperationFinder.searchOperationByWsdlInRequestMessage(message, soapStreamReader, requestInfo, registroServiziManager, idServizio, log,
- config);
- }
- else {
- azione = OperationFinder.searchOperationByRestInRequestMessage(transportContext, requestInfo, registroServiziManager, idServizio, log,
- protocolFactory, portaApplicativa);
- }
- }
- else if(ModalitaIdentificazioneAzione.PROTOCOL_BASED.equals(modalitaIdentificazione)){
- // PROTOCOL-BASED
- pluginBased = true;
- if(idServizio.getAzione()!=null){
- // gia localizzata in precedenza
- azione = idServizio.getAzione();
- }
- else{
- OpenSPCoop2Message msgAnalizyProtocol = message;
- if(message==null && soapStreamReader!=null) {
- msgAnalizyProtocol=soapStreamReader.getHeader_OpenSPCoop2Message();
- }
- if(msgAnalizyProtocol==null){
- throw new DriverConfigurazioneNotFound("Messaggio non fornito");
- }
- Busta busta = protocolFactory.createValidazioneSintattica(null).getBusta_senzaControlli(msgAnalizyProtocol);
- if(busta!=null){
- azione = busta.getAzione();
- }
- }
- }
- }
- }
- }catch(Exception e){
- eAzione = e;
- }
-
- // Se non ho riconosciuto una azione, provo con la modalita' wsdlBased se e' abilitata.
- if(azione==null && forceRegistryBased && !registryBased ){
- azione = getActionByInterface(log,
- transportContext, idServizio, modalitaIdentificazione,
- registroServiziManager, requestInfo,
- message, soapStreamReader,
- protocolFactory,
- portaApplicativa,
- config);
- }
- // Se non ho riconosciuto una azione, provo con la modalita' pluginBased se e' abilitata.
- if(azione==null && forcePluginBased && !pluginBased ){
- azione = getActionByPlugin(log,
- idServizio,
- message, soapStreamReader,
- protocolFactory);
- }
- // Se non ho riconosciuto una azione a questo punto, e durante il processo standard di riconoscimento era stato sollevata una eccezione
- // viene rilanciato
- if(azione==null && eAzione!=null)
- throw new IdentificazioneDinamicaException(eAzione.getMessage(),eAzione);
-
- return azione;
- }catch(IdentificazioneDinamicaException e){
- throw e;
- }
- catch(Exception e){
- throw new DriverConfigurazioneException(e.getMessage(),e);
- }
- }
-
- private static String getSoapAction(TransportRequestContext transportContext) {
- String azione = null;
- try{
- azione = SoapUtils.getSoapAction(transportContext, MessageType.SOAP_11, transportContext.getContentType());
- }catch(Exception e){
- // ignore
- }
- if(azione==null){
- try{
- azione = SoapUtils.getSoapAction(transportContext, MessageType.SOAP_12, transportContext.getContentType());
- }catch(Exception e){
- // ignore
- }
- }
- return azione;
- }
-
- private static String getActionByInterface(Logger log,
- TransportRequestContext transportContext, IDServizio idServizio, ModalitaIdentificazioneAzione modalitaIdentificazione,
- RegistroServiziManager registroServiziManager, RequestInfo requestInfo,
- OpenSPCoop2Message message, OpenSPCoop2MessageSoapStreamReader soapStreamReader,
- IProtocolFactory<?> protocolFactory,
- boolean portaApplicativa,
- WSDLValidatorConfig config) {
- String azione = null;
- try{
- OperationFinder.checkIDServizioPerRiconoscimentoAzione(idServizio, modalitaIdentificazione);
- org.openspcoop2.core.registry.constants.ServiceBinding serviceBinding = registroServiziManager.getServiceBinding(idServizio, requestInfo);
- if(org.openspcoop2.core.registry.constants.ServiceBinding.SOAP.equals(serviceBinding)){
- azione = OperationFinder.searchOperationByWsdlInRequestMessage(message, soapStreamReader, requestInfo, registroServiziManager, idServizio, log,
- config);
- }
- else{
- azione = OperationFinder.searchOperationByRestInRequestMessage(transportContext, requestInfo, registroServiziManager, idServizio, log,
- protocolFactory, portaApplicativa);
- }
- }catch(Exception eForceRegistry){
- log.debug("Riconoscimento forzato dell'azione non riuscito: "+eForceRegistry.getMessage(),eForceRegistry);
- }
- return azione;
- }
-
- public static String searchOperationByWsdlInRequestMessage(OpenSPCoop2Message msg, OpenSPCoop2MessageSoapStreamReader soapStreamReaderParam, RequestInfo requestInfo, RegistroServiziManager registroServiziReader,IDServizio idServizio,Logger log,
- WSDLValidatorConfig config) throws DriverRegistroServiziException, DriverRegistroServiziNotFound{
- return searchOperationByWsdl(true, msg, soapStreamReaderParam, requestInfo, registroServiziReader, idServizio, log,
- config);
- }
- /**public static String searchOperationByWsdlInResponseMessage(OpenSPCoop2Message msg, RequestInfo requestInfo, RegistroServiziManager registroServiziReader,IDServizio idServizio,Logger log,
- boolean rpcAcceptRootElementUnqualified) throws DriverRegistroServiziException, DriverRegistroServiziNotFound{
- return searchOperationByWsdl(false, msg, requestInfo, registroServiziReader, idServizio, log,
- rpcAcceptRootElementUnqualified);
- }*/
- private static String searchOperationByWsdl(boolean isRichiesta,OpenSPCoop2Message msg, OpenSPCoop2MessageSoapStreamReader soapStreamReaderParam, RequestInfo requestInfo, RegistroServiziManager registroServiziReader,IDServizio idServizio,Logger log,
- WSDLValidatorConfig config) throws DriverRegistroServiziException, DriverRegistroServiziNotFound{
- org.openspcoop2.core.registry.wsdl.AccordoServizioWrapper wrapper = registroServiziReader.getWsdlAccordoServizio(idServizio,InformationApiSource.SAFE_SPECIFIC_REGISTRY,false,false,requestInfo);
- org.openspcoop2.core.registry.wsdl.AccordoServizioWrapperUtilities wrapperUtilities =
- new org.openspcoop2.core.registry.wsdl.AccordoServizioWrapperUtilities(log,wrapper);
- return wrapperUtilities.searchOperationName(isRichiesta, wrapper.getNomePortType(), msg, soapStreamReaderParam, config);
- }
-
- public static String searchOperationByRestInRequestMessage(TransportRequestContext transportContext, RequestInfo requestInfo, RegistroServiziManager registroServiziReader,IDServizio idServizio,Logger log,
- IProtocolFactory<?> protocolFactory, boolean portaApplicativa) throws DriverRegistroServiziException, DriverRegistroServiziNotFound{
-
- String normalizedInterfaceName = null;
- try {
- if(transportContext.getInterfaceName()!=null) {
- PorteNamingUtils namingUtils = new PorteNamingUtils(protocolFactory);
- if(portaApplicativa){
- normalizedInterfaceName = namingUtils.normalizePA(transportContext.getInterfaceName());
- }
- else {
- normalizedInterfaceName = namingUtils.normalizePD(transportContext.getInterfaceName());
- }
- }
- }catch(Exception e) {
- throw new DriverRegistroServiziException(e.getMessage(),e);
- }
- String path = RestUtilities.getUrlWithoutInterface(transportContext, normalizedInterfaceName);
- HttpRequestMethod httpMethod = HttpRequestMethod.valueOf(transportContext.getRequestType());
-
- try {
- org.openspcoop2.core.registry.rest.AccordoServizioWrapper wrapper = registroServiziReader.getRestAccordoServizio(idServizio,InformationApiSource.SAFE_SPECIFIC_REGISTRY,false,false,false, requestInfo);
- ApiOperation op = wrapper.getApi().findOperation(httpMethod, path);
- if(op!=null) {
- // Il path nella 'ApiOperation è normalizzato come sul registro
- for (int i = 0; i < wrapper.getAccordoServizio().sizeResourceList(); i++) {
- Resource r = wrapper.getAccordoServizio().getResource(i);
-
- if(r.getMethod()==null) {
- if(op.getHttpMethod()!=null) {
- continue;
- }
- }
- else {
- if(op.getHttpMethod()==null) {
- continue;
- }
- if(!r.getMethod().name().equals(op.getHttpMethod().name())){
- continue;
- }
- }
-
- if(r.getPath()==null) {
- if(op.getPath()!=null) {
- continue;
- }
- }
- else {
- String rPath = r.getPath();
- String opPath = op.getPath();
- if(rPath!=null && rPath.length()>1 && rPath.endsWith("/")) {
- rPath = rPath.substring(0,rPath.length()-1);
- }
- if(opPath!=null && opPath.length()>1 && opPath.endsWith("/")) {
- opPath = opPath.substring(0,opPath.length()-1);
- }
- if(rPath!=null && !rPath.equals(opPath)){
- continue;
- }
- }
-
- return r.getNome();
-
- }
- }
- }catch(Exception e) {
- throw new DriverRegistroServiziException(e.getMessage(),e);
- }
-
- return null;
- }
-
- private static String getActionByPlugin(Logger log,
- IDServizio idServizio,
- OpenSPCoop2Message message, OpenSPCoop2MessageSoapStreamReader soapStreamReader,
- IProtocolFactory<?> protocolFactory) {
- String azione = null;
- try{
- if(idServizio.getAzione()!=null){
- // gia localizzata in precedenza
- azione = idServizio.getAzione();
- }
- else{
- OpenSPCoop2Message msgAnalizyProtocol = message;
- if(message==null && soapStreamReader!=null) {
- msgAnalizyProtocol=soapStreamReader.getHeader_OpenSPCoop2Message();
- }
- if(msgAnalizyProtocol!=null){
- Busta busta = protocolFactory.createValidazioneSintattica(null).getBusta_senzaControlli(msgAnalizyProtocol);
- if(busta!=null){
- azione = busta.getAzione();
- }
- }
- }
- }catch(Exception eForcePlugin){
- log.debug("Riconoscimento forzato dell'azione non riuscito: "+eForcePlugin.getMessage(),eForcePlugin);
- }
- return azione;
- }
-
- private static void checkIDServizioPerRiconoscimentoAzione(IDServizio idServizio, ModalitaIdentificazioneAzione modalitaIdentificazione) throws DriverConfigurazioneException{
- String suffixError = " (necessari per procedere con la modalità di identificazione "+modalitaIdentificazione+" dell'azione)";
- if(idServizio==null){
- throw new DriverConfigurazioneException("Dati del servizio non trovati"+suffixError);
- }
- if(idServizio.getSoggettoErogatore()==null){
- throw new DriverConfigurazioneException("Dati del soggetto erogatore del servizio non trovati"+suffixError);
- }
- if(idServizio.getSoggettoErogatore().getTipo()==null){
- throw new DriverConfigurazioneException("Tipo soggetto erogatore del servizio non trovato"+suffixError);
- }
- if(idServizio.getSoggettoErogatore().getNome()==null){
- throw new DriverConfigurazioneException("Nome soggetto erogatore del servizio non trovato"+suffixError);
- }
- if(idServizio.getTipo()==null){
- throw new DriverConfigurazioneException("Tipo servizio non trovato"+suffixError);
- }
- if(idServizio.getNome()==null){
- throw new DriverConfigurazioneException("Nome servizio non trovato"+suffixError);
- }
- if(idServizio.getVersione()==null){
- throw new DriverConfigurazioneException("Versione servizio non trovata"+suffixError);
- }
- }
-
- }