package ilarkesto.google; import ilarkesto.io.StringOutputStream; import ilarkesto.xml.JDom; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.List; import java.util.Properties; import java.util.Map.Entry; import net.oauth.OAuth; import net.oauth.OAuthAccessor; import net.oauth.OAuthConsumer; import net.oauth.OAuthMessage; import net.oauth.OAuthServiceProvider; import net.oauth.ParameterStyle; import net.oauth.OAuth.Parameter; import net.oauth.client.OAuthClient; import net.oauth.client.OAuthResponseMessage; import net.oauth.client.httpclient4.HttpClient4; import net.oauth.client.httpclient4.HttpClientPool; import org.apache.commons.cli.ParseException; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.jdom.Document; import com.google.oacurl.dao.AccessorDao; import com.google.oacurl.dao.ConsumerDao; import com.google.oacurl.dao.ServiceProviderDao; import com.google.oacurl.options.FetchOptions; import com.google.oacurl.options.FetchOptions.Method; import com.google.oacurl.util.MultipartRelatedInputStream; import com.google.oacurl.util.PropertiesProvider; public class Oacurl { public static Document fetchXml(String url, InputStream in) { String xml = fetchString(url, in); return JDom.createDocument(xml); } public static String fetchString(String url, InputStream in) { StringOutputStream out = new StringOutputStream(); fetch(url, in, out); return out.toString(); } public static void fetch(String url, InputStream in, OutputStream out) { FetchOptions options = new FetchOptions(); try { options.parse(new String[] { url }); } catch (ParseException ex) { throw new RuntimeException(ex); } ServiceProviderDao serviceProviderDao = new ServiceProviderDao(); ConsumerDao consumerDao = new ConsumerDao(); AccessorDao accessorDao = new AccessorDao(); Properties loginProperties = null; try { loginProperties = new PropertiesProvider(options.getLoginFileName()).get(); } catch (FileNotFoundException e) { throw new RuntimeException( ".oacurl.properties file not found in homedir. Make sure you've run oacurl-login first!", e); } catch (IOException ex) { throw new RuntimeException(ex); } OAuthServiceProvider serviceProvider = serviceProviderDao.nullServiceProvider(); OAuthConsumer consumer = consumerDao.loadConsumer(loginProperties, serviceProvider); OAuthAccessor accessor = accessorDao.loadAccessor(loginProperties, consumer); OAuthClient client = new OAuthClient(new HttpClient4(SingleClient.HTTP_CLIENT_POOL)); try { OAuthMessage request; List<Entry<String, String>> related = options.getRelated(); Method method = options.getMethod(); if (method == Method.POST || method == Method.PUT) { InputStream bodyStream; if (related != null) { bodyStream = new MultipartRelatedInputStream(related); } else if (options.getFile() != null) { bodyStream = new FileInputStream(options.getFile()); } else { bodyStream = in; } request = accessor.newRequestMessage(method.toString(), url, null, bodyStream); request.getHeaders().add(new OAuth.Parameter("Content-Type", options.getContentType())); } else { request = accessor.newRequestMessage(method.toString(), url, null, null); } List<Parameter> headers = options.getHeaders(); addHeadersToRequest(request, headers); OAuthResponseMessage response = client.access(request, ParameterStyle.AUTHORIZATION_HEADER); // Dump the bytes in the response's encoding. InputStream bodyStream = response.getBodyAsStream(); byte[] buf = new byte[1024]; int count; while ((count = bodyStream.read(buf)) > -1) { out.write(buf, 0, count); } out.flush(); } catch (Exception e) { throw new RuntimeException(e); } } private static void addHeadersToRequest(OAuthMessage request, List<Parameter> headers) { // HACK(phopkins): If someone added their own Expect header, then tell // Apache not to add its own. This is a bit hacky, but gets around that // the RequestExpectContinue class doesn't check for an existing header // before adding its own. // // Fix for: http://code.google.com/p/oacurl/issues/detail?id=1 boolean hasExpect = false; for (Parameter param : headers) { if (param.getKey().equalsIgnoreCase(HTTP.EXPECT_DIRECTIVE)) { hasExpect = true; break; } } if (hasExpect) { HttpProtocolParams.setUseExpectContinue(SingleClient.HTTP_CLIENT_POOL.getHttpClient().getParams(), false); } request.getHeaders().addAll(headers); } /** * Broken out of {@link HttpClient4} so that we can get access to the underlying {@link DefaultHttpClient} * object. */ private static class SingleClient implements HttpClientPool { public static final SingleClient HTTP_CLIENT_POOL = new SingleClient(); private SingleClient() { HttpClient client = new DefaultHttpClient(); ClientConnectionManager mgr = client.getConnectionManager(); if (!(mgr instanceof ThreadSafeClientConnManager)) { HttpParams params = client.getParams(); client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params); } this.client = client; } private final HttpClient client; public HttpClient getHttpClient() { return client; } public HttpClient getHttpClient(URL server) { return client; } } }