package org.jboss.resteasy.specimpl;
import org.jboss.resteasy.core.Headers;
import org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext;
import org.jboss.resteasy.core.interception.jaxrs.ClientReaderInterceptorContext;
import org.jboss.resteasy.plugins.providers.sse.EventInput;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.spi.HttpResponseCodes;
import org.jboss.resteasy.spi.MarshalledEntity;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.util.Types;
import org.jboss.resteasy.util.InputStreamToByteArray;
import org.jboss.resteasy.util.ReadFromStream;
import org.reactivestreams.Publisher;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ReaderInterceptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
public class BuiltResponse extends AbstractBuiltResponse
{
public BuiltResponse()
{
super();
}
public (final int status, final Headers<Object> metadata,
final Object entity, final Annotation[] entityAnnotations)
{
this(status, null, metadata, entity, entityAnnotations);
}
public (final int status, final String reason,
final Headers<Object> metadata, final Object entity,
final Annotation[] entityAnnotations)
{
super(status, reason, metadata, entity, entityAnnotations);
}
@SuppressWarnings("unchecked")
@Override
public <T> T readEntity(Class<T> type, Type genericType, Annotation[] anns)
{
abortIfClosed();
if (entity != null)
{
if (type.isInstance((this.entity)))
{
return (T)entity;
}
else if (entity instanceof InputStream)
{
setInputStream((InputStream)entity);
entity = null;
}
else if (bufferedEntity == null)
{
throw new RuntimeException(Messages.MESSAGES.entityAlreadyRead(entity.getClass()));
}
else
{
entity = null;
}
}
if (entity == null)
{
if (status == HttpResponseCodes.SC_NO_CONTENT)
return null;
try
{
entity = readFrom(type, genericType, getMediaType(), anns);
if (entity == null || (entity != null
&& !InputStream.class.isInstance(entity)
&& !Reader.class.isInstance(entity)
&& bufferedEntity == null))
{
try
{
if (!Publisher.class.isInstance(entity) && !EventInput.class.isInstance(entity))
{
close();
}
}
catch (Exception ignored)
{
}
}
}
catch (RuntimeException e)
{
try
{
close();
}
catch (Exception ignored)
{
}
LogMessages.LOGGER.clientReceiveProcessingFailure(e);
throw e;
}
}
return (T) entity;
}
protected synchronized <T> Object readFrom(Class<T> type, Type genericType,
MediaType media, Annotation[] annotations)
{
Type useGeneric = genericType == null ? type : genericType;
Class<?> useType = type;
media = media == null ? MediaType.WILDCARD_TYPE : media;
annotations = annotations == null ? this.annotations : annotations;
boolean isMarshalledEntity = false;
if (type.equals(MarshalledEntity.class))
{
isMarshalledEntity = true;
ParameterizedType param = (ParameterizedType) useGeneric;
useGeneric = param.getActualTypeArguments()[0];
useType = Types.getRawType(useGeneric);
}
try
{
InputStream is = getEntityStream();
if (is == null)
{
throw new IllegalStateException(Messages.MESSAGES.inputStreamWasEmpty());
}
if (isMarshalledEntity)
{
is = new InputStreamToByteArray(is);
}
ResteasyProviderFactory providerFactory = ResteasyProviderFactory.getInstance();
ReaderInterceptor[] readerInterceptors = providerFactory
.getServerReaderInterceptorRegistry()
.postMatch(null, null);
final Object finalObj;
AbstractReaderInterceptorContext context = new ClientReaderInterceptorContext(
readerInterceptors, providerFactory, useType,
useGeneric, annotations, media, getStringHeaders(), is,
new HashMap<String, Object>(), null);
finalObj = context.proceed();
if (isMarshalledEntity)
{
InputStreamToByteArray isba = (InputStreamToByteArray) is;
final byte[] bytes = isba.toByteArray();
return new MarshalledEntity<Object>()
{
@Override
public byte[] getMarshalledBytes()
{
return bytes;
}
@Override
public Object getEntity()
{
return finalObj;
}
};
}
else
{
return finalObj;
}
}
catch (ProcessingException pe)
{
throw pe;
}
catch (Exception ex)
{
throw new ProcessingException(ex);
}
}
protected InputStream getEntityStream()
{
if (bufferedEntity != null) {
return new ByteArrayInputStream(bufferedEntity);
}
if (isClosed()) {
throw new ProcessingException(Messages.MESSAGES.streamIsClosed());
}
InputStream is = getInputStream();
return is != null ? new AbstractBuiltResponse.InputStreamWrapper<BuiltResponse>(is, this) : null;
}
protected void setInputStream(InputStream is)
{
this.is = is;
resetEntity();
}
protected InputStream getInputStream()
{
if (is == null && entity != null && entity instanceof InputStream) {
is = (InputStream) entity;
}
return is;
}
@Override
public void releaseConnection() throws IOException
{
releaseConnection(false);
}
@Override
public void releaseConnection(boolean consumeInputStream) throws IOException
{
try
{
if (is != null)
{
if (consumeInputStream)
{
while (is.read() > 0)
{
}
}
is.close();
is = null;
}
}
catch (IOException e)
{
}
}
@Override
public boolean bufferEntity()
{
abortIfClosed();
if (bufferedEntity != null) return true;
if (streamRead) return false;
InputStream is = getInputStream();
if (is == null) return false;
try
{
bufferedEntity = ReadFromStream.readFromStream(1024, is);
}
catch (IOException e)
{
throw new ProcessingException(e);
}
finally
{
try {
releaseConnection();
}
catch (IOException e) {
throw new ProcessingException(e);
}
}
return true;
}
}