package org.apache.http.impl.execchain;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.conn.EofSensorInputStream;
import org.apache.http.conn.EofSensorWatcher;
import org.apache.http.entity.HttpEntityWrapper;
class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {
private final ConnectionHolder connHolder;
public static void enchance(final HttpResponse response, final ConnectionHolder connHolder) {
final HttpEntity entity = response.getEntity();
if (entity != null && entity.isStreaming() && connHolder != null) {
response.setEntity(new ResponseEntityProxy(entity, connHolder));
}
}
ResponseEntityProxy(final HttpEntity entity, final ConnectionHolder connHolder) {
super(entity);
this.connHolder = connHolder;
}
private void cleanup() throws IOException {
if (this.connHolder != null) {
this.connHolder.close();
}
}
private void abortConnection() {
if (this.connHolder != null) {
this.connHolder.abortConnection();
}
}
public void releaseConnection() {
if (this.connHolder != null) {
this.connHolder.releaseConnection();
}
}
@Override
public boolean isRepeatable() {
return false;
}
@Override
public InputStream getContent() throws IOException {
return new EofSensorInputStream(this.wrappedEntity.getContent(), this);
}
@Override
public void consumeContent() throws IOException {
releaseConnection();
}
@Override
public void writeTo(final OutputStream outStream) throws IOException {
try {
if (outStream != null) {
this.wrappedEntity.writeTo(outStream);
}
releaseConnection();
} catch (final IOException ex) {
abortConnection();
throw ex;
} catch (final RuntimeException ex) {
abortConnection();
throw ex;
} finally {
cleanup();
}
}
@Override
public boolean eofDetected(final InputStream wrapped) throws IOException {
try {
if (wrapped != null) {
wrapped.close();
}
releaseConnection();
} catch (final IOException ex) {
abortConnection();
throw ex;
} catch (final RuntimeException ex) {
abortConnection();
throw ex;
} finally {
cleanup();
}
return false;
}
@Override
public boolean streamClosed(final InputStream wrapped) throws IOException {
try {
final boolean open = connHolder != null && !connHolder.isReleased();
try {
if (wrapped != null) {
wrapped.close();
}
releaseConnection();
} catch (final SocketException ex) {
if (open) {
throw ex;
}
}
} catch (final IOException ex) {
abortConnection();
throw ex;
} catch (final RuntimeException ex) {
abortConnection();
throw ex;
} finally {
cleanup();
}
return false;
}
@Override
public boolean streamAbort(final InputStream wrapped) throws IOException {
cleanup();
return false;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ResponseEntityProxy{");
sb.append(wrappedEntity);
sb.append('}');
return sb.toString();
}
}