SignalHubPushInProtocolRequestHandler.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */
  20. package org.openspcoop2.protocol.modipa.handlers;

  21. import java.lang.reflect.InvocationTargetException;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.Objects;
  26. import java.util.Optional;
  27. import java.util.stream.Collectors;

  28. import org.openspcoop2.core.commons.CoreException;
  29. import org.openspcoop2.core.constants.CostantiDB;
  30. import org.openspcoop2.core.constants.TipoPdD;
  31. import org.openspcoop2.core.id.IDAccordo;
  32. import org.openspcoop2.core.id.IDServizio;
  33. import org.openspcoop2.core.id.IDSoggetto;
  34. import org.openspcoop2.core.registry.AccordoServizioParteSpecifica;
  35. import org.openspcoop2.core.registry.Fruitore;
  36. import org.openspcoop2.core.registry.ProtocolProperty;
  37. import org.openspcoop2.core.registry.driver.DriverRegistroServiziException;
  38. import org.openspcoop2.core.registry.driver.IDAccordoFactory;
  39. import org.openspcoop2.core.registry.driver.IDServizioFactory;
  40. import org.openspcoop2.core.registry.driver.IDriverRegistroServiziGet;
  41. import org.openspcoop2.pdd.core.dynamic.DynamicException;
  42. import org.openspcoop2.pdd.core.dynamic.DynamicUtils;
  43. import org.openspcoop2.pdd.core.handlers.HandlerException;
  44. import org.openspcoop2.pdd.core.handlers.InRequestContext;
  45. import org.openspcoop2.pdd.core.handlers.InRequestHandler;
  46. import org.openspcoop2.protocol.basic.registry.RegistryReader;
  47. import org.openspcoop2.protocol.modipa.config.ModIProperties;
  48. import org.openspcoop2.protocol.modipa.config.ModISignalHubConfig;
  49. import org.openspcoop2.protocol.modipa.config.ModISignalHubParamConfig;
  50. import org.openspcoop2.protocol.modipa.constants.ModICostanti;
  51. import org.openspcoop2.protocol.modipa.constants.ModISignalHubOperation;
  52. import org.openspcoop2.protocol.modipa.properties.ModIDynamicConfigurationAccordiParteComuneUtilities;
  53. import org.openspcoop2.protocol.modipa.utils.ModIUtilities;
  54. import org.openspcoop2.protocol.registry.RegistroServiziReader;
  55. import org.openspcoop2.protocol.sdk.Context;
  56. import org.openspcoop2.protocol.sdk.ProtocolException;
  57. import org.openspcoop2.protocol.sdk.constants.IntegrationFunctionError;
  58. import org.openspcoop2.protocol.sdk.properties.ProtocolProperties;
  59. import org.openspcoop2.protocol.sdk.properties.ProtocolPropertiesUtils;
  60. import org.openspcoop2.protocol.sdk.registry.IRegistryReader;
  61. import org.openspcoop2.protocol.sdk.registry.ProtocolFiltroRicercaServizi;
  62. import org.openspcoop2.protocol.sdk.registry.RegistryException;
  63. import org.openspcoop2.protocol.sdk.registry.RegistryNotFound;
  64. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  65. import org.openspcoop2.utils.BooleanNullable;
  66. import org.openspcoop2.utils.service.beans.ProfiloEnum;
  67. import org.openspcoop2.utils.service.beans.utils.ProfiloUtils;
  68. import org.slf4j.Logger;

  69. /**
  70.  * SignalHubPushInRequestHandler
  71.  *
  72.  * @author Tommaso Burlon (tommaso.burlon@link.it)
  73.  * @author $Author$
  74.  * @version $Rev$, $Date$
  75.  */
  76. public class SignalHubPushInProtocolRequestHandler implements InRequestHandler {
  77.    
  78.     @Override
  79.     public void invoke(InRequestContext context) throws HandlerException {
  80.         try {
  81.             if (checkSignalHubPushConditions(context)) {
  82.                 List<ProtocolProperty> props = getSignalHubPushProperty(context);
  83.                 parseSignalHubPushProperty(context, props);
  84.             }
  85.         } catch (ProtocolException
  86.                 | DriverRegistroServiziException
  87.                 | DynamicException
  88.                 | RegistryNotFound
  89.                 | RegistryException e) {
  90.             throw new HandlerException(e);
  91.         }
  92.     }
  93.    
  94.     private boolean checkSignalHubPushConditions(InRequestContext context) throws ProtocolException, DriverRegistroServiziException, RegistryNotFound, RegistryException {
  95.         Logger logger = context.getLogCore();
  96.        
  97.        
  98.         // controllo che signalhub sia abilitato
  99.         ModIProperties modiProperties = ModIProperties.getInstance();
  100.         if(!modiProperties.isSignalHubEnabled()) {
  101.             return false;
  102.         }
  103.        
  104.         // controllo che sia una fruizione ModI
  105.         if (context.getTipoPorta() == null
  106.                 || !context.getTipoPorta().equals(TipoPdD.DELEGATA)
  107.                 || context.getPddContext() == null)
  108.             return false;
  109.        
  110.         IRegistryReader registryReader = this.getIRegistryReader(context);

  111.        
  112.         // controllo che l'id dell'accordo sia raggiungibile
  113.         AccordoServizioParteSpecifica asps = registryReader.getAccordoServizioParteSpecifica(this.getRequestInfo(context).getIdServizio());
  114.         IDAccordo idAccordo = IDAccordoFactory.getInstance().getIDAccordoFromUri(asps.getAccordoServizioParteComune());
  115.         if (idAccordo == null)
  116.             return false;
  117.        
  118.        
  119.         // controllo che l'accordo sia l'accordo built-in per la registrazione dei segnali
  120.         boolean isApiSignalHubPushAPI = false;
  121.            
  122.         Map<String, IDriverRegistroServiziGet> readers = RegistroServiziReader.getDriverRegistroServizi();

  123.         for (Map.Entry<String, IDriverRegistroServiziGet> entry : readers.entrySet()) {
  124.             IRegistryReader reader;
  125.             try {
  126.                 reader = new RegistryReader(entry.getValue(), logger);
  127.                 isApiSignalHubPushAPI |= ModIDynamicConfigurationAccordiParteComuneUtilities.isApiSignalHubPushAPI(idAccordo, reader, ModIProperties.getInstance(), logger);
  128.             } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
  129.                     | InvocationTargetException | NoSuchMethodException | SecurityException e) {
  130.                 // ignore
  131.             }
  132.         }
  133.        
  134.         if (!isApiSignalHubPushAPI)
  135.             return false;
  136.        
  137.         logger.debug("Nuova richiesta di deposito di segnali SignalHub");
  138.        
  139.         return true;
  140.     }
  141.    
  142.    
  143.     private RequestInfo getRequestInfo(InRequestContext context) {
  144.         return (RequestInfo) context.getPddContext().getObject(org.openspcoop2.core.constants.Costanti.REQUEST_INFO);
  145.     }
  146.    
  147.     private IRegistryReader getIRegistryReader(InRequestContext context) throws ProtocolException {
  148.         return context.getProtocolFactory().getCachedRegistryReader(context.getStato(), this.getRequestInfo(context));
  149.     }
  150.    
  151.     private IDSoggetto getFruitore(InRequestContext context) {
  152.         return this.getRequestInfo(context).getFruitore();
  153.     }
  154.    
  155.     private List<ProtocolProperty> getSignalHubPushProperty(InRequestContext context) throws ProtocolException, RegistryNotFound, RegistryException {
  156.         IRegistryReader reader = this.getIRegistryReader(context);
  157.         IDServizio servizio = this.getRequestInfo(context).getIdServizio();
  158.         IDSoggetto idFruitore = this.getFruitore(context);
  159.        
  160.         AccordoServizioParteSpecifica asps = reader.getAccordoServizioParteSpecifica(servizio, false);
  161.         List<Fruitore> fruitori = Objects.requireNonNullElseGet(asps.getFruitoreList(), ArrayList::new);
  162.        
  163.         Optional<Fruitore> fruitore = fruitori
  164.                 .stream().filter(f -> f.getNome().equals(idFruitore.getNome()) && f.getTipo().equals(idFruitore.getTipo()))
  165.                 .findAny();
  166.                
  167.         if (fruitore.isEmpty())
  168.             return List.of();
  169.        
  170.         List<ProtocolProperty> props = fruitore.get().getProtocolPropertyList();
  171.         if (props != null && !props.isEmpty())
  172.             return props;
  173.            
  174.         return List.of();
  175.     }

  176.     private String getDynamicProperty(List<ProtocolProperty> props, ModISignalHubParamConfig param, Context context, Map<String, Object> dynamicMap, boolean useDefault) throws ProtocolException {
  177.         try {
  178.             String key = CostantiDB.MODIPA_API_IMPL_PUSH_SIGNAL_HUB_PARAM_VALUE_ID_PREFIX + param.getPropertyId();
  179.             String mode = ProtocolPropertiesUtils.getRequiredStringValuePropertyRegistry(props, CostantiDB.MODIPA_API_IMPL_PUSH_SIGNAL_HUB_PARAM_MODE_ID_PREFIX + param.getPropertyId());
  180.             String ridefinedValue = ProtocolPropertiesUtils.getOptionalStringValuePropertyRegistry(props, CostantiDB.MODIPA_API_IMPL_PUSH_SIGNAL_HUB_PARAM_VALUE_ID_PREFIX + param.getPropertyId());
  181.             List<String> values = null;
  182.                    
  183.             // se il campo e' stato ridefinito uso il template ridefinito altrimenti quello di default
  184.             if (!useDefault && mode.equals(CostantiDB.MODIPA_PROFILO_RIDEFINISCI)) {
  185.                 values = List.of(ridefinedValue);
  186.             } else {
  187.                 values = param.getRules();
  188.             }
  189.    
  190.             return ModIUtilities.getDynamicValue(key, values, dynamicMap, context);
  191.         } catch (ProtocolException e) {
  192.             return null;
  193.         }
  194.     }
  195.    
  196.     private void parseSignalHubPushProperty(InRequestContext context, List<ProtocolProperty> props) throws ProtocolException, DynamicException, HandlerException, RegistryNotFound, RegistryException, NumberFormatException, DriverRegistroServiziException {
  197.         ModIProperties modiProperties = ModIProperties.getInstance();
  198.         ModISignalHubConfig signalHubConfig = modiProperties.getSignalHubConfig();
  199.         Logger logger = context.getLogCore();

  200.         Map<String, ModISignalHubParamConfig> claims = signalHubConfig.getClaims()
  201.                 .stream()
  202.                 .collect(Collectors.toMap(v -> v.getPropertyId(), v -> v));
  203.        
  204.         Map<String, Object> dynamicMap = DynamicUtils.buildDynamicMap(context.getMessaggio(), context.getPddContext(), null, logger, modiProperties.isReadByPathBufferEnabled());

  205.         // controllo se il segnale e' un segnale di SEEDUPDATE in tal caso le informazioni saranne messe da govway negli header di default
  206.         boolean isSeedUpdate = false;
  207.         String signalTypeRaw = getDynamicProperty(props, claims.get(ModICostanti.MODIPA_SIGNAL_HUB_ID_SIGNAL_TYPE), context.getPddContext(), dynamicMap, true);
  208.         ModISignalHubOperation signalType = ModISignalHubOperation.fromString(signalTypeRaw);
  209.        
  210.         if (signalType != null && signalType.equals(ModISignalHubOperation.SEEDUPDATE))
  211.             isSeedUpdate = true;
  212.        
  213.         // ottengo le varie informaizoni di deposito del segnale (nel caso di seedupdate usero i template di default)
  214.         String objectId = getDynamicProperty(props, claims.get(ModICostanti.MODIPA_SIGNAL_HUB_ID_OBJECT_ID), context.getPddContext(), dynamicMap, isSeedUpdate);
  215.         String objectType = getDynamicProperty(props, claims.get(ModICostanti.MODIPA_SIGNAL_HUB_ID_OBJECT_TYPE), context.getPddContext(), dynamicMap, isSeedUpdate);
  216.         signalTypeRaw = getDynamicProperty(props, claims.get(ModICostanti.MODIPA_SIGNAL_HUB_ID_SIGNAL_TYPE), context.getPddContext(), dynamicMap, isSeedUpdate);

  217.         if (objectId == null) {
  218.             throw newHandlerException("Parametro obbligatorio 'objectId' non rilevato", IntegrationFunctionError.BAD_REQUEST);
  219.         }
  220.         if (objectType == null) {
  221.             throw newHandlerException("Parametro obbligatorio 'objectType' non rilevato", IntegrationFunctionError.BAD_REQUEST);
  222.         }
  223.         if (signalTypeRaw == null) {
  224.             throw newHandlerException("Parametro obbligatorio 'signalType' non rilevato", IntegrationFunctionError.BAD_REQUEST);
  225.         }
  226.        
  227.         signalType = ModISignalHubOperation.fromString(signalTypeRaw);
  228.         if (signalType == null) {
  229.             throw newHandlerException("Parametro 'signalType' con valore errato '"+signalTypeRaw+"'; valori supportati: UPDATE, CREATE, DELETE", IntegrationFunctionError.BAD_REQUEST);
  230.         }
  231.        
  232.         String service = null;
  233.         String serviceVersion = null;
  234.         String serviceId = null;
  235.        
  236.         service = getDynamicProperty(props, claims.get("service"), context.getPddContext(), dynamicMap, isSeedUpdate);
  237.         serviceVersion = getDynamicProperty(props, claims.get("serviceVersion"), context.getPddContext(), dynamicMap, isSeedUpdate);
  238.         serviceId = getDynamicProperty(props, claims.get("serviceId"), context.getPddContext(), dynamicMap, isSeedUpdate);
  239.        
  240.        
  241.         IRegistryReader reader = this.getIRegistryReader(context);
  242.        
  243.         IDServizio idServizio = null;
  244.         List<ProtocolProperty> eServiceProperties = null;
  245.        
  246.         if (serviceId == null && (service == null || serviceVersion == null)) {
  247.             throw newHandlerException("Un serviceId o in alternativa il nome e la versione devono essere obbligatoriamente indicati per poter individuare il servizio", IntegrationFunctionError.BAD_REQUEST);
  248.         }
  249.        
  250.         // se tutte le informazioni sono presenti ottengo il serviceId a partire dall'id del servizio
  251.         if (serviceId == null) {
  252.            
  253.             int versioneServizio = -1;
  254.             try {
  255.                 versioneServizio = Integer.valueOf(serviceVersion);
  256.                 if(versioneServizio<=0) {
  257.                     throw new CoreException("Valore deve essere maggiore di zero");
  258.                 }
  259.             }catch(Exception e) {
  260.                 String msg = "Parametro 'serviceVersion' presenta un valore '"+serviceVersion+"' non valido; deve essere un numero intero maggiore di zero";
  261.                 logger.error(msg+": "+e.getMessage(), e);
  262.                 throw newHandlerException(msg, IntegrationFunctionError.BAD_REQUEST);
  263.             }
  264.            
  265.             try {
  266.                 idServizio = IDServizioFactory.getInstance().getIDServizioFromValues(
  267.                         ProfiloUtils.toProtocollo(ProfiloEnum.MODIPA),
  268.                         service,
  269.                         this.getFruitore(context),
  270.                         versioneServizio);
  271.                         AccordoServizioParteSpecifica asps = reader.getAccordoServizioParteSpecifica(idServizio);
  272.                         eServiceProperties = asps.getProtocolPropertyList();
  273.             }catch(RegistryNotFound notFound) {
  274.                 String nomeSoggetto = idServizio!=null && idServizio.getSoggettoErogatore()!=null && idServizio.getSoggettoErogatore().getNome()!=null ? idServizio.getSoggettoErogatore().getNome() : "Non identificato";
  275.                 throw newHandlerException("Il soggetto '"+nomeSoggetto+"' non risulta erogare un servizio con nome '"+service+"'  e versione '"+versioneServizio+"'", IntegrationFunctionError.BAD_REQUEST);
  276.             }
  277.         } else {
  278.             // altrimenti ottengo l'id sdel servizio partendo dal serviceId
  279.             ProtocolFiltroRicercaServizi filter = new ProtocolFiltroRicercaServizi();
  280.             ProtocolProperties filterProps = new ProtocolProperties();
  281.             filterProps.addProperty(ModICostanti.MODIPA_API_IMPL_INFO_ESERVICE_ID, serviceId);
  282.             filter.setProtocolPropertiesServizi(filterProps);
  283.            
  284.             List<IDServizio> idServices = null;
  285.             try {
  286.                 idServices = reader.findIdAccordiServizioParteSpecifica(filter);
  287.             }catch(RegistryNotFound notFound) {
  288.                 // ignore
  289.             }
  290.             logger.debug("id servizi: {}", idServices);
  291.            
  292.             if (idServices==null || idServices.isEmpty() || idServices.get(0)==null) {
  293.                 throw newHandlerException("Non esiste una erogazione di servizio registrato con l'id servizio '"+serviceId+"' indicato", IntegrationFunctionError.BAD_REQUEST);
  294.             }
  295.            
  296.             idServizio = idServices.get(0);
  297.            
  298.             IDSoggetto soggettoFruitore = this.getFruitore(context);
  299.             if (!idServizio.getSoggettoErogatore().equals(soggettoFruitore)) {
  300.                 context.getPddContext().addObject(org.openspcoop2.core.constants.Costanti.ERRORE_AUTORIZZAZIONE, "true");
  301.                 throw newHandlerException("L'erogazione di servizio individuata con l'id servizio '"+serviceId+"' appartiene ad un soggetto '"+idServizio.getSoggettoErogatore().getNome()+"' differente dal soggetto pubblicatore '"+soggettoFruitore.getNome()+"'",
  302.                         IntegrationFunctionError.AUTHORIZATION_DENY);
  303.             }

  304.             AccordoServizioParteSpecifica asps = reader.getAccordoServizioParteSpecifica(idServizio);
  305.             eServiceProperties = asps.getProtocolPropertyList();
  306.         }
  307.        
  308.         try {
  309.             serviceId = ProtocolPropertiesUtils.getRequiredStringValuePropertyRegistry(eServiceProperties, ModICostanti.MODIPA_API_IMPL_INFO_ESERVICE_ID);
  310.         }catch(Exception e) {
  311.             // succede nel caso di name e version
  312.             throw newHandlerException("L'erogazione del servizio indicato non contiene la configurazione relativa al serviceId", IntegrationFunctionError.BAD_REQUEST);
  313.         }
  314.        
  315.         try {
  316.             BooleanNullable signalHub = ProtocolPropertiesUtils.getOptionalBooleanValuePropertyRegistry(eServiceProperties, ModICostanti.MODIPA_API_IMPL_INFO_SIGNAL_HUB_ID);
  317.             if(signalHub==null || signalHub.getValue()==null || !signalHub.getValue().booleanValue()) {
  318.                 throw new CoreException("Non Attiva");
  319.             }
  320.         }catch(Exception e) {
  321.             // succede nel caso non sia stata attuata la configurazione
  322.             String msg = "Nell'erogazione del servizio indicato non risulta attiva la funzionalità Signal Hub";
  323.             logger.error(msg+": "+e.getMessage(), e);
  324.             throw newHandlerException(msg, IntegrationFunctionError.BAD_REQUEST);
  325.         }
  326.        
  327.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_OBJECT_ID, objectId);
  328.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_ESERVICE_ID, serviceId);
  329.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_SERVICE, idServizio);
  330.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_OBJECT_TYPE, objectType);
  331.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_SIGNAL_TYPE, signalType);
  332.         context.getPddContext().addObject(ModICostanti.MODIPA_KEY_INFO_SIGNAL_HUB_PROPERTIES, eServiceProperties);
  333.     }

  334.     private HandlerException newHandlerException(String msg, IntegrationFunctionError error) {
  335.         HandlerException he = new HandlerException(msg);
  336.         he.setIntegrationFunctionError(error);
  337.         return he;
  338.     }
  339. }