ConnettoreHTTPCORETransactionThreadContextSwitchEntityProducer.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.pdd.core.connettori.httpcore5.nio;
import java.io.IOException;
import java.util.Set;
import org.apache.hc.core5.http.nio.AsyncEntityProducer;
import org.apache.hc.core5.http.nio.DataStreamChannel;
import org.openspcoop2.pdd.core.transazioni.TransactionContext;
import org.openspcoop2.utils.BooleanNullable;
import org.openspcoop2.utils.UtilsRuntimeException;
/**
* AbstractConnettoreHTTPCOREInputStreamEntityProducer
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class ConnettoreHTTPCORETransactionThreadContextSwitchEntityProducer<T extends AsyncEntityProducer> implements AsyncEntityProducer{
protected T wrapped;
private ConnettoreHTTPCORE connettore;
private boolean switchThreadContext = false;
private String function;
private BooleanNullable switchThreadLocalContextDoneHolder = BooleanNullable.FALSE();
protected ConnettoreHTTPCORETransactionThreadContextSwitchEntityProducer(ConnettoreHTTPCORE connettore, T wrapped) {
this.wrapped = wrapped;
// L'inizializzazione avviene nel worker thread del webserver o nel worker thread della richiesta a seconda della configurazione (vedi org.openspcoop2.pdd.services.connector.ConnectorApplicativeThreadPool)
// Se viene usato il thread local per gestire il contesto, gli oggetti devono essere riportati sul thread local del thread della libreria client nio che effettuerà la spedizione (metodi successivi)
if(TransactionContext.isUseThreadLocal()) {
this.switchThreadContext = true;
this.connettore = connettore;
this.function = "EntityProducer-"+this.wrapped.getClass().getName();
}
}
@Override
public int available() {
if(this.switchThreadContext) {
try {
this.connettore.checkThreadLocalContext(this.function, this.switchThreadLocalContextDoneHolder);
}catch(Exception e) {
throw new UtilsRuntimeException(e.getMessage(),e);
}
}
return this.wrapped.available();
}
@Override
public void produce(DataStreamChannel channel) throws IOException {
if(this.switchThreadContext) {
this.connettore.checkThreadLocalContext(this.function, this.switchThreadLocalContextDoneHolder);
}
this.wrapped.produce(channel);
}
private boolean released = false;
@Override
public void releaseResources() {
if(this.switchThreadContext && !this.released) {
this.connettore.removeThreadLocalContext(this.function, this.switchThreadLocalContextDoneHolder);
this.released = true;
}
this.wrapped.releaseResources();
}
@Override
public void failed(Exception e) {
if(this.switchThreadContext && !this.released) {
this.connettore.removeThreadLocalContext(this.function, this.switchThreadLocalContextDoneHolder);
this.released = true;
}
this.wrapped.failed(e);
}
// proxy only
@Override
public String getContentEncoding() {
return this.wrapped.getContentEncoding();
}
@Override
public long getContentLength() {
return this.wrapped.getContentLength();
}
@Override
public String getContentType() {
return this.wrapped.getContentType();
}
@Override
public Set<String> getTrailerNames() {
return this.wrapped.getTrailerNames();
}
@Override
public boolean isChunked() {
return this.wrapped.isChunked();
}
@Override
public boolean isRepeatable() {
return this.wrapped.isRepeatable();
}
}