UrlInvocazioneAPI.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 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.pdd.config;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openspcoop2.core.config.ConfigurazioneUrlInvocazione;
import org.openspcoop2.core.config.ConfigurazioneUrlInvocazioneRegola;
import org.openspcoop2.core.config.constants.CostantiConfigurazione;
import org.openspcoop2.core.config.constants.RuoloContesto;
import org.openspcoop2.core.config.constants.StatoFunzionalita;
import org.openspcoop2.core.config.driver.DriverConfigurazioneException;
import org.openspcoop2.core.constants.CostantiLabel;
import org.openspcoop2.core.id.IDSoggetto;
import org.openspcoop2.message.constants.ServiceBinding;
import org.openspcoop2.protocol.engine.constants.Costanti;
import org.openspcoop2.protocol.manifest.Context;
import org.openspcoop2.protocol.manifest.WebEmptyContext;
import org.openspcoop2.protocol.sdk.IProtocolFactory;
import org.openspcoop2.protocol.utils.PorteNamingUtils;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.regexp.RegExpNotFoundException;
import org.openspcoop2.utils.regexp.RegularExpressionEngine;
/**
* UrlInvocazioneAPI
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class UrlInvocazioneAPI implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String baseUrl;
private String context;
public String getBaseUrl() {
return this.baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getContext() {
return this.context;
}
public void setContext(String context) {
this.context = context;
}
public String getUrl() {
if(this.baseUrl==null) {
return null;
}
return Utilities.buildUrl(this.baseUrl, this.context);
}
// *** STATIC UTILITIES **
public static UrlInvocazioneAPI getConfigurazioneUrlInvocazione(ConfigurazioneUrlInvocazione configurazioneUrlInvocazione,
IProtocolFactory<?> protocolFactory, RuoloContesto ruolo, ServiceBinding serviceBinding,
String interfaceName, IDSoggetto soggettoOperativo,
List<String> tags, String canale) throws DriverConfigurazioneException{
return getConfigurazioneUrlInvocazione(configurazioneUrlInvocazione,
protocolFactory, ruolo, serviceBinding,
interfaceName, soggettoOperativo,
tags, canale, true);
}
public static UrlInvocazioneAPI getConfigurazioneUrlInvocazione(ConfigurazioneUrlInvocazione configurazioneUrlInvocazione,
IProtocolFactory<?> protocolFactory, RuoloContesto ruolo, ServiceBinding serviceBinding,
String interfaceName, IDSoggetto soggettoOperativo,
List<String> tags, String canale, boolean analizeProxyPassRules) throws DriverConfigurazioneException{
if(configurazioneUrlInvocazione==null) {
configurazioneUrlInvocazione = new ConfigurazioneUrlInvocazione();
initConfigurazioneProtocolloUrlInvocazione(configurazioneUrlInvocazione);
}
// normalizzo interfaceName
String interfaceNameNormalizzata = interfaceName;
if(interfaceNameNormalizzata!=null) {
try {
PorteNamingUtils utils = new PorteNamingUtils(protocolFactory);
if( RuoloContesto.PORTA_DELEGATA.equals(ruolo) ) {
interfaceNameNormalizzata = utils.normalizePD(interfaceName);
}
else {
interfaceNameNormalizzata = utils.normalizePA(interfaceName);
}
}catch(Exception e){
protocolFactory.getLogger().debug("Normalizzazione interface name '"+interfaceName+"' non riuscita: "+e.getMessage(),e);
}
}
// Regola di default
ConfigurazioneUrlInvocazioneRegola regolaDefault = getConfigurazioneUrlInvocazioneDefault(configurazioneUrlInvocazione, protocolFactory, ruolo, serviceBinding, interfaceNameNormalizzata); // default
// Colleziono regole compatibili
ConfigurazioneUrlInvocazioneRegola regola = null;
if(analizeProxyPassRules) {
Map<String, ConfigurazioneUrlInvocazioneRegola> regole = new HashMap<>();
for (ConfigurazioneUrlInvocazioneRegola check : configurazioneUrlInvocazione.getRegolaList()) {
regole.put(check.getPosizione()+"", check);
}
if(regole.size()>0) {
List<String> posizioni = new ArrayList<>();
posizioni.addAll(regole.keySet());
Collections.sort(posizioni);
for (String posizione : posizioni) {
ConfigurazioneUrlInvocazioneRegola check = regole.get(posizione);
try {
/**System.out.println("ESAMINO REGOLA ALLA POSIZIONE '"+posizione+"'");*/
String contesto = getContext(protocolFactory, ruolo, serviceBinding, interfaceNameNormalizzata);
if(isMatchRegolaUrlInvocazione(check, protocolFactory, ruolo, serviceBinding, contesto, soggettoOperativo)) {
regola = processMatchRegolaUrlInvocazione(check, contesto,
tags, canale); // risolve eventuale match di espressioni regolari.
break;
}
}catch(Exception e) {
protocolFactory.getLogger().error("Errore durante il processamento della regola-"+posizione+" '"+check.getNome()+"': "+e.getMessage(),e);
}
}
}
}
if(regola==null) {
regola = regolaDefault;
}
UrlInvocazioneAPI url = new UrlInvocazioneAPI();
if(regola.getBaseUrl()!=null) {
url.setBaseUrl(regola.getBaseUrl());
}
else {
if( RuoloContesto.PORTA_DELEGATA.equals(ruolo) && configurazioneUrlInvocazione.getBaseUrlFruizione()!=null ) {
url.setBaseUrl(configurazioneUrlInvocazione.getBaseUrlFruizione());
}
else {
url.setBaseUrl(configurazioneUrlInvocazione.getBaseUrl());
}
}
url.setContext(regola.getContestoEsterno());
return url;
}
private static void initConfigurazioneProtocolloUrlInvocazione(ConfigurazioneUrlInvocazione configurazioneUrlInvocazione) throws DriverConfigurazioneException {
try {
if(configurazioneUrlInvocazione.getBaseUrl()==null) {
configurazioneUrlInvocazione.setBaseUrl(CostantiConfigurazione.DEFAULT_VALUE_PARAMETRO_CONFIGURAZIONE_URL_INVOCAZIONE_PREFIX);
}
}catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
private static ConfigurazioneUrlInvocazioneRegola getConfigurazioneUrlInvocazioneDefault(ConfigurazioneUrlInvocazione configurazioneUrlInvocazione,
IProtocolFactory<?> protocolFactory, RuoloContesto ruolo, ServiceBinding serviceBinding, String interfaceNameNormalizzata) throws DriverConfigurazioneException {
try {
if(configurazioneUrlInvocazione!=null) {
// nop
}
ConfigurazioneUrlInvocazioneRegola regola = new ConfigurazioneUrlInvocazioneRegola();
regola.setNome(CostantiConfigurazione.DEFAULT_VALUE_PARAMETRO_CONFIGURAZIONE_URL_INVOCAZIONE_DEFAULT_RULE_NAME);
regola.setPosizione(-1); // non serve, verrà usata questa regola
regola.setStato(StatoFunzionalita.ABILITATO);
regola.setDescrizione(CostantiConfigurazione.DEFAULT_VALUE_PARAMETRO_CONFIGURAZIONE_URL_INVOCAZIONE_DEFAULT_RULE_DESCRIPTION);
regola.setRegexpr(false);
regola.setRegola(""); // non serve, verrà usata questa regola per produrre la url di invocazione
regola.setContestoEsterno(getContext(protocolFactory, ruolo, serviceBinding, interfaceNameNormalizzata));
regola.setBaseUrl(null); // viene usata quella di default
regola.setProtocollo(protocolFactory.getProtocol());
regola.setRuolo(ruolo);
if(serviceBinding!=null) {
regola.setServiceBinding(ServiceBinding.REST.equals(serviceBinding) ? org.openspcoop2.core.config.constants.ServiceBinding.REST : org.openspcoop2.core.config.constants.ServiceBinding.SOAP);
}
return regola;
}catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
private static boolean isMatchRegolaUrlInvocazione(ConfigurazioneUrlInvocazioneRegola check,
IProtocolFactory<?> protocolFactory, RuoloContesto ruolo, ServiceBinding serviceBinding,
String contesto, IDSoggetto soggettoOperativoInterfaccia) throws DriverConfigurazioneException {
if(StatoFunzionalita.DISABILITATO.equals(check.getStato())) {
return false;
}
if(check.getProtocollo()!=null) {
if(protocolFactory==null) {
return false;
}
if(!check.getProtocollo().equals(protocolFactory.getProtocol())) {
return false;
}
}
if(check.getRuolo()!=null) {
if(ruolo==null) {
return false;
}
if(!check.getRuolo().equals(ruolo)) {
return false;
}
}
if(check.getServiceBinding()!=null) {
if(serviceBinding==null) {
return false;
}
if(!check.getServiceBinding().name().equals(serviceBinding.name())) {
return false;
}
}
if(check.getSoggetto()!=null && check.getSoggetto().getTipo()!=null && check.getSoggetto().getNome()!=null) {
if(soggettoOperativoInterfaccia==null) {
return false;
}
try {
if(!check.getSoggetto().toIDSoggetto().equals(soggettoOperativoInterfaccia)) {
return false;
}
}catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
if(contesto==null) {
return false;
}
if(check.isRegexpr()) {
try {
boolean isMatch = RegularExpressionEngine.isMatch(contesto, check.getRegola());
if(isMatch) {
return true;
}
if(contesto.startsWith("/") && contesto.length()>1) {
isMatch = RegularExpressionEngine.isMatch(contesto.substring(1), check.getRegola());
if(isMatch) {
return true;
}
}
return false;
}catch(RegExpNotFoundException notFound) {
return false;
}catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
else {
String contestDaVerificare = contesto;
if(contesto.startsWith("/")) {
if(!check.getRegola().startsWith("/")) {
if(contesto.length()==1) {
contestDaVerificare = "";
}
else {
contestDaVerificare = contestDaVerificare.substring(1);
}
}
}
else {
if(check.getRegola().startsWith("/")) {
contestDaVerificare = "/"+contestDaVerificare;
}
}
return contestDaVerificare.startsWith(check.getRegola());
}
}
private static ConfigurazioneUrlInvocazioneRegola processMatchRegolaUrlInvocazione(ConfigurazioneUrlInvocazioneRegola regolaParam, String contestoParam,
List<String> tags, String canale) throws DriverConfigurazioneException {
ConfigurazioneUrlInvocazioneRegola regola = (ConfigurazioneUrlInvocazioneRegola) regolaParam.clone();
if(regola.isRegexpr()) {
try {
String contestoDaUsarePerVerifica = contestoParam;
boolean isMatch = RegularExpressionEngine.isMatch(contestoDaUsarePerVerifica, regola.getRegola());
if(!isMatch &&
contestoDaUsarePerVerifica.startsWith("/") && contestoDaUsarePerVerifica.length()>1) {
contestoDaUsarePerVerifica = contestoDaUsarePerVerifica.substring(1);
}
List<String> list = null;
try {
list = RegularExpressionEngine.getAllStringMatchPattern(contestoDaUsarePerVerifica, regola.getRegola());
}catch(RegExpNotFoundException notFound) {
if(!RegularExpressionEngine.isMatch(contestoDaUsarePerVerifica, regola.getRegola())) {
throw notFound; // altrimenti l'espressione regolare ha un match senza però avere condizioni () per estrarre informazioni tramite gruppi.
}
}
String newContesto = regola.getContestoEsterno();
if(newContesto==null) {
newContesto = "";
}
String baseUrl = regola.getBaseUrl();
if(list!=null) {
for (int i = 0; i < list.size(); i++) {
String found = list.get(i);
if(found==null) {
found = "";
}
String key = "${"+i+"}";
while(newContesto.contains(key)) {
newContesto = newContesto.replace(key, found);
}
if(baseUrl!=null) {
while(baseUrl.contains(key)) {
baseUrl = baseUrl.replace(key, found);
}
}
}
}
regola.setContestoEsterno(newContesto);
regola.setBaseUrl(baseUrl);
}
/**catch(RegExpNotFoundException notFound) { NON dovrebbe succedere, gestito prima con l'if
return null;
}*/
catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
// tags
if(tags!=null && !tags.isEmpty()) {
String newContesto = regola.getContestoEsterno();
if(newContesto==null) {
newContesto = "";
}
String baseUrl = regola.getBaseUrl();
for (int i = 0; i < tags.size(); i++) {
String found = tags.get(i);
if(found==null) {
found = "";
}
if(i==0) {
String key = "${tag}";
while(newContesto.contains(key)) {
newContesto = newContesto.replace(key, found);
}
if(baseUrl!=null) {
while(baseUrl.contains(key)) {
baseUrl = baseUrl.replace(key, found);
}
}
}
String key = "${tag["+i+"]}";
while(newContesto.contains(key)) {
newContesto = newContesto.replace(key, found);
}
if(baseUrl!=null) {
while(baseUrl.contains(key)) {
baseUrl = baseUrl.replace(key, found);
}
}
}
regola.setContestoEsterno(newContesto);
regola.setBaseUrl(baseUrl);
}
// canale
if(canale!=null) {
String newContesto = regola.getContestoEsterno();
if(newContesto==null) {
newContesto = "";
}
String baseUrl = regola.getBaseUrl();
String key = "${canale}";
while(newContesto.contains(key)) {
newContesto = newContesto.replace(key, canale);
}
if(baseUrl!=null) {
while(baseUrl.contains(key)) {
baseUrl = baseUrl.replace(key, canale);
}
}
regola.setContestoEsterno(newContesto);
regola.setBaseUrl(baseUrl);
}
return regola;
}
private static String getContext(IProtocolFactory<?> protocolFactory, RuoloContesto ruolo, ServiceBinding serviceBinding, String interfaceNameNormalizzata) throws DriverConfigurazioneException {
try {
boolean trasparente = false;
if(protocolFactory!=null) {
trasparente = Costanti.TRASPARENTE_PROTOCOL_NAME.equals(protocolFactory.getProtocol());
}
boolean forceContextWithoutBinding = false;
if(trasparente) {
forceContextWithoutBinding = true; // altrimenti vengono usati api-rest e api-soap
}
String contextWithoutBinding = null;
String contextWithRestBinding = null;
String contextWithSoapBinding = null;
if(protocolFactory!=null && protocolFactory.getManifest().getWeb().getEmptyContext()!=null) {
WebEmptyContext ctx = protocolFactory.getManifest().getWeb().getEmptyContext();
if(ctx.getBinding()==null) {
if(contextWithoutBinding==null) {
contextWithoutBinding = "";
}
}
else if(org.openspcoop2.protocol.manifest.constants.ServiceBinding.REST.equals(ctx.getBinding())) {
if(contextWithRestBinding==null) {
contextWithRestBinding = "";
}
}
else if(org.openspcoop2.protocol.manifest.constants.ServiceBinding.SOAP.equals(ctx.getBinding()) &&
contextWithSoapBinding==null) {
contextWithSoapBinding = "";
}
}
if(protocolFactory!=null && protocolFactory.getManifest().getWeb().sizeContextList()>0) {
for (Context ctx : protocolFactory.getManifest().getWeb().getContextList()) {
if(ctx.getBinding()==null) {
if(contextWithoutBinding==null) {
contextWithoutBinding = ctx.getName();
}
}
else if(org.openspcoop2.protocol.manifest.constants.ServiceBinding.REST.equals(ctx.getBinding())) {
if(contextWithRestBinding==null) {
contextWithRestBinding = ctx.getName();
}
}
else if(org.openspcoop2.protocol.manifest.constants.ServiceBinding.SOAP.equals(ctx.getBinding()) &&
contextWithSoapBinding==null) {
contextWithSoapBinding = ctx.getName();
}
}
}
// Assegno i contesti se non trovati altri.
if(contextWithRestBinding==null || (forceContextWithoutBinding && contextWithoutBinding!=null)) {
contextWithRestBinding = contextWithoutBinding;
}
if(contextWithSoapBinding==null || (forceContextWithoutBinding && contextWithoutBinding!=null)) {
contextWithSoapBinding = contextWithoutBinding;
}
if(contextWithoutBinding==null) {
throw new DriverConfigurazioneException("Contesto senza uno specifico binding non indicato");
}
String contestoEsterno = null;
if(serviceBinding!=null) {
switch (serviceBinding) {
case REST:
contestoEsterno = RuoloContesto.PORTA_DELEGATA.equals(ruolo) ?
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePd(contextWithRestBinding) :
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePa(contextWithRestBinding);
break;
case SOAP:
contestoEsterno = RuoloContesto.PORTA_DELEGATA.equals(ruolo) ?
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePd(contextWithSoapBinding) :
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePa(contextWithSoapBinding);
break;
}
}
else {
contestoEsterno = RuoloContesto.PORTA_DELEGATA.equals(ruolo) ?
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePd(contextWithoutBinding) :
CostantiConfigurazione.getDefaultValueParametroConfigurazioneProtocolloPrefixUrlInvocazionePa(contextWithoutBinding);
}
if(contestoEsterno!=null) {
if(CostantiLabel.TRASPARENTE_PROTOCOL_NAME.equalsIgnoreCase(protocolFactory.getProtocol())) {
if(RuoloContesto.PORTA_APPLICATIVA.equals(ruolo)) {
if(contestoEsterno.endsWith("in/")) {
contestoEsterno = contestoEsterno.substring(0, contestoEsterno.length()-"in/".length());
}
else if(contestoEsterno.endsWith("in")) {
contestoEsterno = contestoEsterno.substring(0, contestoEsterno.length()-"in".length());
}
}
}
else if(CostantiLabel.SDI_PROTOCOL_NAME.equalsIgnoreCase(protocolFactory.getProtocol()) &&
RuoloContesto.PORTA_DELEGATA.equals(ruolo)) {
if(contestoEsterno.endsWith("out/")) {
contestoEsterno = contestoEsterno + "xml2soap/";
}
else if(contestoEsterno.endsWith("out")) {
contestoEsterno = contestoEsterno + "/xml2soap/";
}
}
}
boolean useInterfaceName = false;
if(RuoloContesto.PORTA_APPLICATIVA.equals(ruolo)) {
useInterfaceName = protocolFactory.createProtocolIntegrationConfiguration().useInterfaceNameInImplementationInvocationURL(serviceBinding);
}
else {
useInterfaceName = protocolFactory.createProtocolIntegrationConfiguration().useInterfaceNameInSubscriptionInvocationURL(serviceBinding);
}
if(useInterfaceName && interfaceNameNormalizzata!=null && !"".equals(interfaceNameNormalizzata)) {
if(contestoEsterno!=null) {
contestoEsterno = contestoEsterno + "/" +interfaceNameNormalizzata;
}
else {
contestoEsterno = interfaceNameNormalizzata;
}
}
if(contestoEsterno!=null) {
while(contestoEsterno.contains("//")) {
contestoEsterno = contestoEsterno.replace("//", "/");
}
}
if(contestoEsterno!=null &&
!contestoEsterno.startsWith("/")) {
contestoEsterno = "/"+contestoEsterno;
}
return contestoEsterno;
}catch(Exception e) {
throw new DriverConfigurazioneException(e.getMessage(),e);
}
}
}