package org.jboss.resteasy.client.core.executors;
import org.jboss.resteasy.client.ClientExecutor;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.client.core.BaseClientResponse;
import org.jboss.resteasy.client.core.BaseClientResponse.BaseClientResponseStreamFactory;
import org.jboss.resteasy.util.CaseInsensitiveMap;
import org.jboss.resteasy.util.CommitHeaderOutputStream;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import static org.jboss.resteasy.util.HttpHeaderNames.*;
public class URLConnectionClientExecutor implements ClientExecutor
{
public ClientResponse<?> execute(ClientRequest request) throws Exception
{
HttpURLConnection connection = createConnection(request);
return execute(request, connection);
}
private void commitHeaders(ClientRequest request, HttpURLConnection connection)
{
for (Entry<String, List<String>> entry : request.getHeaders().entrySet())
{
String value = null;
if (entry.getValue().size() == 1)
value = entry.getValue().get(0);
else
{
StringBuilder b = new StringBuilder();
String add = "";
for (String v : entry.getValue())
{
b.append(add).append(v);
add = ",";
}
value = b.toString();
}
connection.addRequestProperty(entry.getKey(), value);
}
}
public ClientRequest createRequest(String uriTemplate)
{
return new ClientRequest(uriTemplate, this);
}
public ClientRequest createRequest(UriBuilder uriBuilder)
{
return new ClientRequest(uriBuilder, this);
}
protected HttpURLConnection createConnection(ClientRequest request) throws Exception
{
String uri = request.getUri();
String httpMethod = request.getHttpMethod();
HttpURLConnection connection = (HttpURLConnection) new URL(uri).openConnection();
connection.setRequestMethod(httpMethod);
return connection;
}
private <T> ClientResponse<T> execute(ClientRequest request, final HttpURLConnection connection) throws IOException
{
outputBody(request, connection);
final int status = connection.getResponseCode();
BaseClientResponse<T> response = new BaseClientResponse<T>(new BaseClientResponseStreamFactory()
{
public InputStream getInputStream() throws IOException
{
return (status < 300) ? connection.getInputStream() : connection.getErrorStream();
}
public void performReleaseConnection()
{
try
{
getInputStream().close();
}
catch (IOException e)
{
}
connection.disconnect();
}
}, this);
response.setProviderFactory(request.getProviderFactory());
response.setStatus(status);
response.setHeaders(getHeaders(connection));
response.setAttributes(request.getAttributes());
return response;
}
public void close()
{
// empty
}
private MultivaluedMap<String, String> getHeaders(
final HttpURLConnection connection)
{
MultivaluedMap<String, String> headers = new CaseInsensitiveMap<String>();
for (Entry<String, List<String>> header : connection.getHeaderFields()
.entrySet())
{
if (header.getKey() != null)
for (String value : header.getValue())
headers.add(header.getKey(), value);
}
return headers;
}
private void outputBody(final ClientRequest request, final HttpURLConnection connection)
{
if (request.getBody() != null)
{
// System.out.println(request.getBody());
if (connection.getRequestProperty(CONTENT_TYPE) == null)
{
String type = request.getBodyContentType().toString();
connection.addRequestProperty(CONTENT_TYPE, type);
}
try
{
final CommitHeaderOutputStream commit = new CommitHeaderOutputStream();
CommitHeaderOutputStream.CommitCallback callback = new CommitHeaderOutputStream.CommitCallback()
{
@Override
public void commit()
{
connection.setDoOutput(true);
commitHeaders(request, connection);
OutputStream os = null;
try
{
os = connection.getOutputStream();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
commit.setDelegate(os);
}
};
commit.setHeaders(callback);
try
{
request.writeRequestBody(request.getHeadersAsObjects(), commit);
}
finally
{
commit.getDelegate().flush();
commit.getDelegate().close();
}
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
else
{
commitHeaders(request, connection);
}
}
}