PreInRequestHandlerGestioneControlloTraffico.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.core.controllo_traffico.handler;
import org.openspcoop2.core.commons.CoreException;
import org.openspcoop2.core.constants.TipoPdD;
import org.openspcoop2.core.controllo_traffico.ConfigurazioneGenerale;
import org.openspcoop2.core.controllo_traffico.constants.TipoErrore;
import org.openspcoop2.core.eventi.constants.CodiceEventoControlloTraffico;
import org.openspcoop2.core.eventi.constants.TipoEvento;
import org.openspcoop2.message.constants.ServiceBinding;
import org.openspcoop2.pdd.config.ConfigurazionePdDManager;
import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
import org.openspcoop2.pdd.core.controllo_traffico.CostantiControlloTraffico;
import org.openspcoop2.pdd.core.controllo_traffico.GeneratoreMessaggiErrore;
import org.openspcoop2.pdd.core.controllo_traffico.GestoreControlloTraffico;
import org.openspcoop2.pdd.core.handlers.HandlerException;
import org.openspcoop2.pdd.core.handlers.PreInRequestContext;
import org.openspcoop2.pdd.logger.MsgDiagnosticiProperties;
import org.openspcoop2.pdd.logger.MsgDiagnostico;
import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
import org.openspcoop2.pdd.services.connector.messages.ConnectorInMessage;
import org.openspcoop2.utils.transport.Credential;
import org.slf4j.Logger;
/**
* PreInRequestHandler_GestioneControlloTraffico
*
* @author Poli Andrea (poli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class PreInRequestHandlerGestioneControlloTraffico {
public void process(PreInRequestContext context) throws HandlerException{
ConfigurazioneGenerale configurazioneGenerale = null;
GestoreControlloTraffico gestore = null;
Boolean maxThreadsEnabled = false;
Boolean maxThreadsWarningOnly = false;
Long maxThreads = null;
Integer threshold = null;
TipoErrore tipoErrore = TipoErrore.FAULT;
boolean includiDescrizioneErrore = true;
Logger logControlloTraffico = null;
ServiceBinding serviceBinding = ServiceBinding.REST;
try{
// Prelevo la configurazione del Controllo del Traffico
OpenSPCoop2Properties propertiesReader = OpenSPCoop2Properties.getInstance();
logControlloTraffico = OpenSPCoop2Logger.getLoggerOpenSPCoopControlloTraffico(propertiesReader.isControlloTrafficoDebug());
ConfigurazionePdDManager configPdDManager = ConfigurazionePdDManager.getInstance();
if(configPdDManager==null) {
throw new CoreException("configPdDManager is null");
}
configurazioneGenerale = configPdDManager.getConfigurazioneControlloTraffico(context!=null ? context.getRequestInfo() : null);
if(configurazioneGenerale.getControlloTraffico()==null){
throw new CoreException("Impostazione maxThreads non corretta?? ControlloTraffico is null");
}
if(context!=null && context.getTipoPorta()!=null && context.getRequestInfo()!=null) {
if(TipoPdD.DELEGATA.equals(context.getTipoPorta())) {
if(context.getRequestInfo().getIntegrationServiceBinding()!=null) {
serviceBinding = context.getRequestInfo().getIntegrationServiceBinding();
}
}else {
if(context.getRequestInfo().getProtocolServiceBinding()!=null) {
serviceBinding = context.getRequestInfo().getProtocolServiceBinding();
}
}
}
// Indicazione se il sistema di controllo dei max threads risulta attivo
maxThreadsEnabled = configurazioneGenerale.getControlloTraffico().isControlloMaxThreadsEnabled();
maxThreadsWarningOnly = configurazioneGenerale.getControlloTraffico().isControlloMaxThreadsWarningOnly();
if(maxThreadsEnabled!=null && maxThreadsEnabled.booleanValue()) {
// Numero Massimo di richieste simultanee
maxThreads = configurazioneGenerale.getControlloTraffico().getControlloMaxThreadsSoglia();
if(maxThreads==null || maxThreads<=0l){
throw new CoreException("Impostazione maxThreads non corretta?? ["+maxThreads+"]");
}
// Indicazione se abilitare o meno il controllo del traffico ed eventuale threshold
if(configurazioneGenerale.getControlloTraffico()!=null &&
configurazioneGenerale.getControlloTraffico().isControlloCongestioneEnabled()){
threshold = configurazioneGenerale.getControlloTraffico().getControlloCongestioneThreshold();
}
// Tipo di errore in caso di superamento del max numero di threads
if(configurazioneGenerale.getControlloTraffico()!=null) {
if(configurazioneGenerale.getControlloTraffico().getControlloMaxThreadsTipoErrore()!=null) {
TipoErrore tipoErrorTmp = TipoErrore.toEnumConstant(configurazioneGenerale.getControlloTraffico().getControlloMaxThreadsTipoErrore());
if(tipoErrorTmp!=null) {
tipoErrore = tipoErrorTmp;
}
}
includiDescrizioneErrore = configurazioneGenerale.getControlloTraffico().isControlloMaxThreadsTipoErroreIncludiDescrizione();
}
// Gestore del Controllo del Traffico
gestore = GestoreControlloTraffico.getInstance();
}
}catch(Exception e){
throw new HandlerException("Configurazione non disponibile: "+e.getMessage(), e);
}
MsgDiagnostico msgDiag = this.buildMsgDiagnostico(context);
try{
// salvataggio informazioni lette
if(maxThreadsEnabled!=null && maxThreadsEnabled.booleanValue()) {
context.getPddContext().addObject(GeneratoreMessaggiErrore.PDD_CONTEXT_MAX_THREADS_THRESHOLD, maxThreads);
if(threshold!=null){
context.getPddContext().addObject(GeneratoreMessaggiErrore.PDD_CONTEXT_CONTROLLO_TRAFFICO_THRESHOLD, threshold);
}
// registro nuovo in thread in ingresso
gestore.addThread(serviceBinding, maxThreads,threshold,maxThreadsWarningOnly,context.getPddContext(),msgDiag,tipoErrore,includiDescrizioneErrore,logControlloTraffico);
// se il metodo precedente non ha sollevato una eccezione registro nel contesto che è stato registrato il thread
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_THREAD_REGISTRATO, true);
}
}catch(Exception e){
// il metodo gestore.addThread((..) ha sollevato una eccezione.
if(maxThreadsWarningOnly!=null && maxThreadsWarningOnly.booleanValue()) {
// Devo comunque impostare questa variabile nel contesto, in modo che l'handler di uscita rimuovi il thread.
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_THREAD_REGISTRATO, true);
// salvo nel contesto che è stato violato il parametro max-threads e salvo anche l'evento 'LIMITE_RICHIESTE_SIMULTANEE_VIOLAZIONE' con severita' warning only
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_VIOLATED_EVENTO,
TipoEvento.CONTROLLO_TRAFFICO_NUMERO_MASSIMO_RICHIESTE_SIMULTANEE.getValue()+"_"+CodiceEventoControlloTraffico.VIOLAZIONE_WARNING_ONLY.getValue());
}
else {
// salvo nel contesto che è stato violato il parametro max-threads in modo che l'handler di uscita sappia che non deve decrementare il numero di threads,
// essendo stato bloccato in questa fase
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_THREAD_REGISTRATO, false);
// salvo nel contesto che è stato violato il parametro max-threads e salvo anche l'evento 'LIMITE_RICHIESTE_SIMULTANEE_VIOLAZIONE' con violazione effettiva
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_VIOLATED_EVENTO,
TipoEvento.CONTROLLO_TRAFFICO_NUMERO_MASSIMO_RICHIESTE_SIMULTANEE.getValue()+"_"+CodiceEventoControlloTraffico.VIOLAZIONE.getValue());
// Per registrare nel database anche le transazioni che vengono bloccate per maxThreads (default è false)
// viene salvato nel contesto le informazioni riguardanti la url invocata e le credenziali
// tali informazioni sono utili per aggiungerle come informazioni avanzate nella transazione.
ConnectorInMessage req = null;
try{
req = (ConnectorInMessage) context.getTransportContext().get(PreInRequestContext.SERVLET_REQUEST);
}catch(Exception eIgnore){
// ignore
}
if(req!=null){
try{
String urlInvocazione = req.getURLProtocolContext().getUrlInvocazione_formBased();
if(urlInvocazione!=null){
if(req.getURLProtocolContext().getFunction()!=null){
urlInvocazione = "["+req.getURLProtocolContext().getFunction()+"] "+urlInvocazione;
}
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_VIOLATED_URL_INVOCAZIONE, urlInvocazione);
}
}catch(Exception eIgnore){
// ignore
}
try{
Credential credenziali = req.getCredential();
String credenzialiFornite = "";
if(credenziali!=null){
credenzialiFornite = credenziali.toString();
context.getPddContext().addObject(CostantiControlloTraffico.PDD_CONTEXT_MAX_REQUEST_VIOLATED_CREDENZIALI, credenzialiFornite);
}
}catch(Exception eIgnore){
// ignore
}
}
// Se l'eccezione è di tipo 'HandlerException' posso risollevarla immediatamente essendo stata generata dal metodo gestore.addThread((..)
// Altrimenti la faccio trattatare dal Gestore dei Messaggi di Errore.
if(e instanceof HandlerException){
throw (HandlerException)e;
}
else{
try{
logControlloTraffico.error(e.getMessage(),e);
}catch(Exception eLog){
context.getLogCore().error(e.getMessage(),e);
}
GeneratoreMessaggiErrore.addPddContextInfo_ControlloTrafficoGenericError(context.getPddContext());
throw GeneratoreMessaggiErrore.getErroreProcessamento(e,context.getPddContext());
}
}
}
}
// Ritorna un MsgDiagnostico generator
private MsgDiagnostico buildMsgDiagnostico(PreInRequestContext context) throws HandlerException{
try{
String nomePorta = null;
if(context.getRequestInfo()!=null && context.getRequestInfo().getProtocolContext()!=null) {
nomePorta = context.getRequestInfo().getProtocolContext().getInterfaceName();
}
MsgDiagnostico msgDiag = MsgDiagnostico.newInstance(context.getTipoPorta(),context.getIdModulo(),nomePorta, context.getRequestInfo());
msgDiag.setPddContext(context.getPddContext(), context.getProtocolFactory());
if(org.openspcoop2.core.constants.TipoPdD.DELEGATA.equals(context.getTipoPorta())){
msgDiag.setPrefixMsgPersonalizzati(MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_CONTENUTI_APPLICATIVI);
}
else{
msgDiag.setPrefixMsgPersonalizzati(MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_BUSTE);
}
return msgDiag;
}catch(Exception e){
throw new HandlerException("Generazione Messaggio Diagnostico non riuscita: "+e.getMessage(), e);
}
}
}