/* Copyright (c) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.wave.api.oauth.impl;
import net.oauth.http.HttpMessage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
/**
* A small implementation of HttpClient to serve the needs of the OAuth library
* rather than requiring org.apache.http.client as a dependency.
*
* @author api.dwh@google.com (Dan Holevoet)
* @author davidbyttow@google.com (David Byttow)
*/
public class OpenSocialHttpClient implements net.oauth.http.HttpClient {
/** Size of data stream buffer. */
private static final int BUF_SIZE = 0x1000; // 4K
/**
* Executes the request, sending the request body if applicable.
*
* @param request
* @return Response message
* @throws IOException
*/
@Override
public OpenSocialHttpResponseMessage execute(HttpMessage request,
Map<String,Object> parameters) throws IOException {
// If a POST message, translates the body into a string.
String body = null;
if (request.getBody() != null) {
body = new String(toByteArray(request.getBody()));
}
OpenSocialHttpMessage openSocialRequest = new OpenSocialHttpMessage(
request.method, new OpenSocialUrl(request.url.toExternalForm()), body);
return execute(openSocialRequest);
}
/**
* Executes the request, sending the request body if applicable.
*
* @param request
* @return Response message
* @throws IOException
*/
private OpenSocialHttpResponseMessage execute(OpenSocialHttpMessage request)
throws IOException {
final String method = request.method;
final boolean isPut = PUT.equalsIgnoreCase(method);
final boolean isPost = POST.equalsIgnoreCase(method);
final boolean isDelete = DELETE.equalsIgnoreCase(method);
final String bodyString = request.getBodyString();
final String contentType = request.getHeader(HttpMessage.CONTENT_TYPE);
final OpenSocialUrl url = request.getUrl();
OpenSocialHttpResponseMessage response = null;
if (isPut) {
response = send("PUT", url, contentType, bodyString);
} else if (isPost) {
response = send("POST", url, contentType, bodyString);
} else if (isDelete) {
response = send("DELETE", url, contentType);
} else {
response = send("GET", url, contentType);
}
return response;
}
/**
* Executes a request without writing any data in the request's body.
*
* @param method
* @param url
* @return Response message
*/
private OpenSocialHttpResponseMessage send(String method, OpenSocialUrl url,
String contentType) throws IOException {
return send(method, url, contentType, null);
}
/**
* Executes a request and writes all data in the request's body to the
* output stream.
*
* @param method
* @param url
* @param body
* @return Response message
*/
private OpenSocialHttpResponseMessage send(String method, OpenSocialUrl url,
String contentType, String body) throws IOException {
HttpURLConnection connection = null;
try {
connection = getConnection(method, url, contentType);
if (body != null) {
OutputStreamWriter out =
new OutputStreamWriter(connection.getOutputStream());
out.write(body);
out.flush();
out.close();
}
return new OpenSocialHttpResponseMessage(method, url,
connection.getInputStream(), connection.getResponseCode());
} catch (IOException e) {
throw new IOException("Container returned status " +
connection.getResponseCode() + " \"" + e.getMessage() + "\"");
}
}
/**
* Opens a new HTTP connection for the URL associated with this object.
*
* @param method
* @param url
* @return Opened connection
* @throws IOException if URL is invalid, or unsupported
*/
private HttpURLConnection getConnection(String method, OpenSocialUrl url,
String contentType) throws IOException {
HttpURLConnection connection =
(HttpURLConnection) new URL(url.toString()).openConnection();
if (contentType != null && !contentType.equals("")) {
connection.setRequestProperty(HttpMessage.CONTENT_TYPE, contentType);
}
connection.setRequestMethod(method);
connection.setDoOutput(true);
connection.connect();
return connection;
}
private static long copy(InputStream from, OutputStream to) throws IOException {
byte[] buf = new byte[BUF_SIZE];
long total = 0;
while (true) {
int r = from.read(buf);
if (r == -1) {
break;
}
to.write(buf, 0, r);
total += r;
}
return total;
}
private static byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(in, out);
return out.toByteArray();
}
}