package org.jboss.resteasy.client.jaxrs.engines;
import org.jboss.resteasy.client.jaxrs.ClientHttpEngine;
import org.jboss.resteasy.client.jaxrs.i18n.Messages;
import org.jboss.resteasy.client.jaxrs.internal.ClientInvocation;
import org.jboss.resteasy.client.jaxrs.internal.ClientResponse;
import org.jboss.resteasy.client.jaxrs.internal.FinalizedClientResponse;
import org.jboss.resteasy.tracing.RESTEasyTracingLogger;
import org.jboss.resteasy.util.CaseInsensitiveMap;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.Map;
public class URLConnectionEngine implements ClientHttpEngine
{
protected SSLContext sslContext;
protected HostnameVerifier hostnameVerifier;
protected Integer readTimeout;
protected Integer connectTimeout;
protected String proxyHost;
protected Integer proxyPort;
protected String proxyScheme;
protected boolean followRedirects;
@Override
public Response invoke(Invocation inv)
{
ClientInvocation request = (ClientInvocation) inv;
final HttpURLConnection connection;
final int status;
try
{
connection = createConnection(request);
executeRequest(request, connection);
status = connection.getResponseCode();
} catch (IOException e)
{
throw new ProcessingException(Messages.MESSAGES.unableToInvokeRequest(e.toString()), e);
}
ClientResponse response = new FinalizedClientResponse(request.getClientConfiguration(), RESTEasyTracingLogger.empty())
{
private InputStream stream;
@Override
protected InputStream getInputStream()
{
if (stream == null)
{
try
{
stream = (status < 300) ? connection.getInputStream() : connection.getErrorStream();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
return stream;
}
@Override
protected void setInputStream(InputStream is)
{
stream = is;
resetEntity();
}
@Override
public void releaseConnection() throws IOException
{
releaseConnection(false);
}
@Override
public void releaseConnection(boolean consumeInputStream) throws IOException
{
InputStream is = getInputStream();
if (is != null)
{
if (consumeInputStream)
{
while (is.read() > 0)
{
}
}
is.close();
}
connection.disconnect();
}
};
response.setStatus(status);
response.setHeaders(getHeaders(connection));
return response;
}
protected MultivaluedMap<String, String> (
final HttpURLConnection connection)
{
MultivaluedMap<String, String> headers = new CaseInsensitiveMap<String>();
for (Map.Entry<String, List<String>> header : connection.getHeaderFields()
.entrySet())
{
if (header.getKey() != null)
{
for (String value : header.getValue())
{
headers.add(header.getKey(), value);
}
}
}
return headers;
}
@Override
public void close()
{
}
protected HttpURLConnection createConnection(final ClientInvocation request) throws IOException
{
Proxy proxy = null;
if (this.proxyHost != null && this.proxyPort != null) {
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(this.proxyHost, this.proxyPort));
} else {
proxy = Proxy.NO_PROXY;
}
HttpURLConnection connection = (HttpURLConnection) request.getUri().toURL().openConnection(proxy);
connection.setRequestMethod(request.getMethod());
if (this.connectTimeout != null)
{
connection.setConnectTimeout(this.connectTimeout);
}
if (this.readTimeout != null)
{
connection.setReadTimeout(this.readTimeout);
}
return connection;
}
protected void executeRequest(final ClientInvocation request, HttpURLConnection connection)
{
connection.setInstanceFollowRedirects(request.getMethod().equals("GET"));
if (request.getEntity() != null)
{
if (request.getMethod().equals("GET")) throw new ProcessingException(Messages.MESSAGES.getRequestCannotHaveBody());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
request.getDelegatingOutputStream().setDelegate(baos);
try
{
request.writeRequestBody(request.getEntityStream());
baos.close();
commitHeaders(request, connection);
connection.setDoOutput(true);
OutputStream os = connection.getOutputStream();
os.write(baos.toByteArray());
os.flush();
os.close();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
else
{
commitHeaders(request, connection);
}
}
protected void (ClientInvocation request, HttpURLConnection connection)
{
MultivaluedMap<String, String> headers = request.getHeaders().asMap();
for (Map.Entry<String, List<String>> header : headers.entrySet())
{
List<String> values = header.getValue();
for (String value : values)
{
connection.addRequestProperty(header.getKey(), value);
}
}
}
@Override
public SSLContext getSslContext()
{
return sslContext;
}
@Override
public HostnameVerifier getHostnameVerifier()
{
return hostnameVerifier;
}
public void setSslContext(SSLContext sslContext)
{
this.sslContext = sslContext;
}
public void setHostnameVerifier(HostnameVerifier hostnameVerifier)
{
this.hostnameVerifier = hostnameVerifier;
}
public void setConnectTimeout(Integer connectTimeout)
{
this.connectTimeout = connectTimeout;
}
public void setReadTimeout(Integer readTimeout)
{
this.readTimeout = readTimeout;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public void setProxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
}
public void setProxyScheme(String proxyScheme) {
this.proxyScheme = proxyScheme;
}
public void setFollowRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
}
public boolean isFollowRedirects() {
return this.followRedirects;
}
}