AbstractBaseOpenSPCoop2MessageDynamicContent.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.message;
- import java.io.ByteArrayInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.SequenceInputStream;
- import org.apache.commons.io.input.CountingInputStream;
- import org.apache.commons.io.output.CountingOutputStream;
- import org.openspcoop2.message.constants.Costanti;
- import org.openspcoop2.message.exception.MessageException;
- import org.openspcoop2.message.exception.MessageNotSupportedException;
- import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
- import org.openspcoop2.utils.CopyStream;
- import org.openspcoop2.utils.Utilities;
- import org.openspcoop2.utils.io.DumpByteArrayOutputStream;
- import org.openspcoop2.utils.resources.Charset;
- import org.openspcoop2.utils.transport.http.ContentTypeUtilities;
- /**
- * AbstractBaseOpenSPCoop2RestMessage
- *
- * @author Andrea Poli (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public abstract class AbstractBaseOpenSPCoop2MessageDynamicContent<T> extends AbstractBaseOpenSPCoop2Message {
- protected CountingInputStream _countingInputStream;
- protected String contentType;
- protected String contentTypeCharsetName = Charset.UTF_8.getValue();
- protected boolean supportReadOnly = true;
- protected boolean contentUpdatable = false;
- protected T content;
- protected boolean hasContent = false;
- protected OpenSPCoop2MessageSoapStreamReader soapStreamReader;
- protected DumpByteArrayOutputStream contentBuffer;
- private static int soglia;
- private static File repositoryFile;
- public static void setSoglia(int soglia) {
- AbstractBaseOpenSPCoop2MessageDynamicContent.soglia = soglia;
- }
- public static void setRepositoryFile(File repositoryFile) {
- AbstractBaseOpenSPCoop2MessageDynamicContent.repositoryFile = repositoryFile;
- }
- private static boolean soapReader = false; // attivato sul gateway tramite il metodo sottostante; in modo che le
- // altre applicazioni non utilizzino questa funzionalità
- // (TestService,Console...)
- private static int soapReaderBufferThresholdKb = 10;
- public static void setSoapReader(boolean soapReader) {
- AbstractBaseOpenSPCoop2MessageDynamicContent.soapReader = soapReader;
- }
- public static void setSoapReaderBufferThresholdKb(int bufferThresholdKb) {
- AbstractBaseOpenSPCoop2MessageDynamicContent.soapReaderBufferThresholdKb = bufferThresholdKb;
- }
- /* Costruttore */
- protected AbstractBaseOpenSPCoop2MessageDynamicContent(OpenSPCoop2MessageFactory messageFactory) {
- super(messageFactory);
- this.hasContent = false;
- }
- protected AbstractBaseOpenSPCoop2MessageDynamicContent(OpenSPCoop2MessageFactory messageFactory,
- InputStream isParam, String contentType, boolean soap, OpenSPCoop2MessageSoapStreamReader soapStreamReader)
- throws MessageException {
- super(messageFactory);
- try {
- this.contentType = contentType;
- if (contentType != null) {
- String ch = ContentTypeUtilities.readCharsetFromContentType(contentType);
- if (ch != null) {
- this.contentTypeCharsetName = ch;
- }
- }
- if (isParam != null) {
- if (soap && soapStreamReader != null) {
- soapStreamReader.checkException(); // senno si entra nell'if dello stream vuoto prima
- }
- // check se esiste del contenuto nello stream, lo stream può essere diverso da
- // null però vuoto.
- InputStream normalizedIs = Utilities.normalizeStream(isParam, false);
- if (normalizedIs == null) {
- // stream vuoto
- this.hasContent = false;
- } else {
- if (soap) {
- if (soapStreamReader == null) {
- if (AbstractBaseOpenSPCoop2MessageDynamicContent.soapReader) {
- this.soapStreamReader = new OpenSPCoop2MessageSoapStreamReader(messageFactory,
- this.contentType, normalizedIs,
- AbstractBaseOpenSPCoop2MessageDynamicContent.soapReaderBufferThresholdKb);
- try {
- this.soapStreamReader.read();
- } finally {
- // anche in caso di eccezione devo cmq aggiornare is
- normalizedIs = this.soapStreamReader.getBufferedInputStream();
- }
- }
- } else {
- this.soapStreamReader = soapStreamReader;
- if (this.soapStreamReader != null) {
- this.soapStreamReader.checkException();
- }
- }
- }
- this._countingInputStream = new CountingInputStream(normalizedIs);
- this.hasContent = true;
- }
- }
- } catch (Exception e) {
- throw new MessageException(e.getMessage(), e);
- }
- }
- /* Metodi richiesti da chi implementa questa classe base */
- protected abstract T buildContent() throws MessageException;
- protected abstract T buildContent(DumpByteArrayOutputStream contentBuffer) throws MessageException;
- protected abstract String buildContentAsString() throws MessageException;
- protected abstract byte[] buildContentAsByteArray() throws MessageException;
- protected abstract void serializeContent(OutputStream os, boolean consume) throws MessageException;
- protected void setUpdatableContent() throws MessageException {
- }
- /* Informazioni SOAP (senza costruire il DOM) */
- public OpenSPCoop2MessageSoapStreamReader getSoapReader() {
- return this.soapStreamReader;
- }
- public void releaseSoapReader() {
- if (this.soapStreamReader != null) {
- this.soapStreamReader.releaseBufferedInputStream();
- this.soapStreamReader.clearHeader();
- this.soapStreamReader = null;
- }
- }
- /* Input Stream con costruzione del buffer incrementale */
-
- public boolean setInputStreamLazyBuffer(String idTransazione) throws MessageException{
-
- if(this._countingInputStream==null) {
- return false;
- }
- if(this.content != null || this.contentBuffer!=null) {
- return false;
- }
- if(! (this._countingInputStream instanceof OpenSPCoop2InputStreamDynamicContent) ) {
- DumpByteArrayOutputStream contentBuffer = new DumpByteArrayOutputStream(
- AbstractBaseOpenSPCoop2MessageDynamicContent.soglia,
- AbstractBaseOpenSPCoop2MessageDynamicContent.repositoryFile, idTransazione,
- this.getMessageRole().name());
- this._countingInputStream = new OpenSPCoop2InputStreamDynamicContent(this._countingInputStream, contentBuffer);
- }
- return true; // se è già OpenSPCoop2InputStreamDynamicContent torno true
- }
-
- /* Contenuto */
- private synchronized void initializeContent(boolean readOnly, String idTransazione) throws MessageException {
- if (this.hasContent) {
- if (this.content == null) {
- if (readOnly && this.supportReadOnly) {
- if(this._countingInputStream instanceof OpenSPCoop2InputStreamDynamicContent) {
- // se e' un OpenSPCoop2InputStreamDynamicContent dovrebbe gia' essere stato inizializzato il buffer
- this._countingInputStream = ((OpenSPCoop2InputStreamDynamicContent)this._countingInputStream).getWrappedInputStream();
- this.contentBuffer = ((OpenSPCoop2InputStreamDynamicContent)this._countingInputStream).getBuffer();
- }
- else {
- this.contentBuffer = new DumpByteArrayOutputStream(
- AbstractBaseOpenSPCoop2MessageDynamicContent.soglia,
- AbstractBaseOpenSPCoop2MessageDynamicContent.repositoryFile, idTransazione,
- this.getMessageRole().name());
- }
- try {
- CopyStream.copy(this._countingInputStream, this.contentBuffer); // se e' un OpenSPCoop2InputStreamDynamicContent riverso quello che rimane nel buffer
- this.content = this.buildContent(this.contentBuffer);
- } catch (Throwable t) {
- MessageUtils.registerParseException(this, t, true);
- throw new MessageException(t.getMessage(), t);
- } finally {
- try {
- this._countingInputStream.close();
- } catch (Exception eClose) {
- }
- }
- } else {
- try {
- this.content = this.buildContent();
- } catch (Throwable t) {
- MessageUtils.registerParseException(this, t, true);
- throw new MessageException(t.getMessage(), t);
- }
- }
- }
- }
- }
- @Override
- public boolean isContentBuilded() {
- return this.content != null;
- }
- public InputStream getInputStreamFromContentBuffer() throws MessageException {
- if(this.contentBuffer==null) {
- return null;
- }
- try {
- if(this.contentBuffer.isSerializedOnFileSystem()) {
- return new FileInputStream(this.contentBuffer.getSerializedFile());
- }
- else {
- return new ByteArrayInputStream(this.contentBuffer.toByteArray());
- }
- }catch(Exception e) {
- throw new MessageException(e.getMessage(),e);
- }
- }
- public InputStream getInputStream() {
- return this._countingInputStream;
- }
- protected InputStream _getInputStream() throws MessageException {
- if(this._countingInputStream instanceof OpenSPCoop2InputStreamDynamicContent) {
- OpenSPCoop2InputStreamDynamicContent di = ((OpenSPCoop2InputStreamDynamicContent)this._countingInputStream);
- DumpByteArrayOutputStream bf = di.getBuffer();
- if(bf!=null && bf.size()>0) {
- this._countingInputStream = di.getWrappedInputStream();
- InputStream isBuffered = bf.getInputStream();
- try {
- InputStream isRemained = Utilities.normalizeStream(this._countingInputStream, false);
- if(di.isInputStreamConsumed() || (isRemained==null) ) {
- return isBuffered;
- }
- else {
- return new SequenceInputStream(isBuffered,isRemained);
- }
- }catch(Exception e) {
- throw new MessageException(e.getMessage(),e);
- }
- }
- else {
- return this._countingInputStream;
- }
- }
- else {
- return this._countingInputStream;
- }
- }
-
- public boolean hasContent() throws MessageException, MessageNotSupportedException {
- return this.hasContent;
- }
- public void initContent() throws MessageException,MessageNotSupportedException{
- getContent();
- }
- public void initContent(boolean readOnly, String idTransazione) throws MessageException,MessageNotSupportedException{
- getContent(readOnly, idTransazione);
- }
-
- public T getContent() throws MessageException, MessageNotSupportedException {
- return getContent(false, null);
- }
- public T getContent(boolean readOnly, String idTransazione) throws MessageException, MessageNotSupportedException {
- if (this.hasContent) {
- if (!readOnly) {
- boolean aggiornaContenuto = false;
- if (this.content != null && !this.contentUpdatable) {
- aggiornaContenuto = true;
- }
- this.contentUpdatable = true;
- if (aggiornaContenuto) {
- // contenuto precedentemente già creato in modalità read-only
- // il metodo ha bisogno che contentUpdatable sia a true
- setUpdatableContent();
- }
- }
- // nota l'assegnazione di contentUpdatable viene usata poi dentro
- // l'inizializzaizone del contenuto per rilasciare le risorse
- if (this.content == null) {
- this.initializeContent(readOnly, idTransazione);
- }
- }
- return this.content; // può tornare null
- }
- public String getContentAsString() throws MessageException, MessageNotSupportedException {
- return getContentAsString(false, null);
- }
- public String getContentAsString(boolean readOnly, String idTransazione)
- throws MessageException, MessageNotSupportedException {
- try {
- if (this.hasContent) {
- if (this.content == null) {
- this.initializeContent(readOnly, idTransazione);
- }
- if (!readOnly) {
- this.contentUpdatable = true;
- }
- return this.buildContentAsString();
- }
- return null;
- } catch (MessageException e) {
- throw e;
- } catch (Exception e) {
- throw new MessageException(e.getMessage(), e);
- }
- }
- public byte[] getContentAsByteArray() throws MessageException, MessageNotSupportedException {
- return getContentAsByteArray(false, null);
- }
- public byte[] getContentAsByteArray(boolean readOnly, String idTransazione)
- throws MessageException, MessageNotSupportedException {
- try {
- if (this.hasContent) {
- if (this.content == null) {
- this.initializeContent(readOnly, idTransazione);
- }
- if (!readOnly) {
- this.contentUpdatable = true;
- }
- return this.buildContentAsByteArray();
- }
- return null;
- } catch (MessageException e) {
- throw e;
- } catch (Exception e) {
- throw new MessageException(e.getMessage(), e);
- }
- }
- public void updateContent(T content) throws MessageException, MessageNotSupportedException {
- this.content = content;
- this.contentUpdatable = true;
- if (this.contentBuffer != null) {
- this.contentBuffer.clearResources();
- this.contentBuffer = null;
- }
- if (this.content != null) {
- this.hasContent = true;
- } else {
- this.hasContent = false;
- this.contentType = null;
- }
- }
- public void setContentUpdatable() {
- this.contentUpdatable = true;
- }
- /* ContentType */
- @Override
- public void updateContentType() throws MessageException {
- // nop;
- }
- @Override
- public void setContentType(String type) {
- this.contentType = type;
- }
- @Override
- public String getContentType() {
- return this.contentType;
- }
- /* WriteTo e Save */
- @Override
- public void writeTo(OutputStream os, boolean consume) throws MessageException {
- this.writeTo(os, consume, false, null);
- }
- public void writeTo(OutputStream os, boolean consume, boolean readOnly, String idTransazione)
- throws MessageException {
- writeTo(os, consume, readOnly, idTransazione, null);
- }
- public void writeTo(OutputStream os, boolean consume, boolean readOnly, String idTransazione, StringBuilder debug)
- throws MessageException {
- try {
- if (this.hasContent) {
- if (!consume && this.content == null) {
- if (!readOnly) {
- this.contentUpdatable = true; // riverso soap header eventuale nel content che verrà costruito
- }
- this.initializeContent(readOnly, idTransazione); // per poi entrare nel ramo sotto serializeContent
- }
- CountingOutputStream cos = new CountingOutputStream(os);
- if (this.contentBuffer != null && !this.contentUpdatable) {
- if (this.soapStreamReader != null && this.soapStreamReader.isSoapHeaderModified()
- && this.contentType != null) {
- if (debug != null) {
- debug.append(Costanti.WRITE_MODE_SERIALIZE_BUFFER_WITH_HEADER);
- }
- this.soapStreamReader.writeOptimizedHeaderTo(this.contentBuffer.getInputStream(), cos, true);
- } else {
- if (debug != null) {
- debug.append(Costanti.WRITE_MODE_SERIALIZE_BUFFER);
- }
- this.contentBuffer.writeTo(cos);
- }
- } else if (this.content != null) {
- if (debug != null) {
- debug.append(Costanti.WRITE_MODE_SERIALIZE_CONTENT);
- }
- this.serializeContent(cos, consume);
- } else {
- if (this.soapStreamReader != null && this.soapStreamReader.isSoapHeaderModified()) {
- if (debug != null) {
- debug.append(Costanti.WRITE_MODE_SERIALIZE_STREAM_WITH_HEADER);
- }
- this.soapStreamReader.writeOptimizedHeaderTo(this._getInputStream(), cos, true);
- } else {
- if (debug != null) {
- debug.append(Costanti.WRITE_MODE_SERIALIZE_STREAM);
- }
- Utilities.copy(this._getInputStream(), cos);
- this._getInputStream().close();
- }
- }
- this.outgoingsize = cos.getByteCount();
- }
- } catch (MessageException e) {
- throw e;
- } catch (Exception e) {
- throw new MessageException(e.getMessage(), e);
- } finally {
- if (consume) {
- try {
- if (this.contentBuffer != null) {
- this.contentBuffer.unlock();
- this.contentBuffer.clearResources();
- this.contentBuffer = null;
- }
- } catch (Throwable t) {
- }
- }
- }
- }
- @Override
- public void saveChanges() throws MessageException {
- // nop;
- }
- @Override
- public boolean saveRequired() {
- return false;
- }
- /* Content Length */
- @Override
- public long getIncomingMessageContentLength() {
- if (this._countingInputStream != null) {
- return this._countingInputStream.getByteCount();
- } else {
- return super.getIncomingMessageContentLength();
- }
- }
- }