/* ESXX - The friendly ECMAscript/XML Application Server Copyright (C) 2007-2010 Martin Blom <martin@blom.org> This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. PLEASE NOTE THAT THIS FILE'S LICENSE IS DIFFERENT FROM THE REST OF ESXX! */ package groovyx.net.http.thirdparty; import java.io.*; import java.net.*; import java.util.concurrent.TimeUnit; import org.apache.http.*; import org.apache.http.conn.*; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.message.BasicHttpResponse; import org.apache.http.params.*; import org.apache.http.protocol.*; import com.google.appengine.api.urlfetch.*; class GAEClientConnection implements ManagedClientConnection { public GAEClientConnection(ClientConnectionManager cm, HttpRoute route, Object state) { this.connManager = cm; this.route = route; this.state = state; this.closed = true; } // From interface ManagedClientConnection public boolean isSecure() { return route.isSecure(); } public HttpRoute getRoute() { return route; } public javax.net.ssl.SSLSession getSSLSession() { return null; } public void open(HttpRoute route, HttpContext context, HttpParams params) throws IOException { close(); this.route = route; // System.err.println(">>>>"); } public void tunnelTarget(boolean secure, HttpParams params) throws IOException { throw new IOException("tunnelTarget() not supported"); } public void tunnelProxy(HttpHost next, boolean secure, HttpParams params) throws IOException { throw new IOException("tunnelProxy() not supported"); } public void layerProtocol(HttpContext context, HttpParams params) throws IOException { throw new IOException("layerProtocol() not supported"); } public void markReusable() { reusable = true; } public void unmarkReusable() { reusable = false; } public boolean isMarkedReusable() { return reusable; } public void setState(Object state) { this.state = state; } public Object getState() { return state; } public void setIdleDuration(long duration, TimeUnit unit) { // Do nothing } // From interface HttpClientConnection public boolean isResponseAvailable(int timeout) throws IOException { return response != null; } public void sendRequestHeader(HttpRequest request) throws HttpException, IOException { try { HttpHost host = route.getTargetHost(); URI uri = new URI(host.getSchemeName() + "://" + host.getHostName() + ((host.getPort() == -1) ? "" : (":" + host.getPort())) + request.getRequestLine().getUri()); this.request = new HTTPRequest(uri.toURL(), HTTPMethod.valueOf(request.getRequestLine().getMethod()), FetchOptions.Builder.disallowTruncate().doNotFollowRedirects()); } catch (URISyntaxException ex) { throw new IOException("Malformed request URI: " + ex.getMessage(), ex); } catch (IllegalArgumentException ex) { throw new IOException("Unsupported HTTP method: " + ex.getMessage(), ex); } // System.err.println("SEND: " + this.request.getMethod() + " " + this.request.getURL()); for (Header h : request.getAllHeaders()) { // System.err.println("SEND: " + h.getName() + ": " + h.getValue()); this.request.addHeader(new HTTPHeader(h.getName(), h.getValue())); } } public void sendRequestEntity(HttpEntityEnclosingRequest request) throws HttpException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (request.getEntity() != null) { request.getEntity().writeTo(baos); } this.request.setPayload(baos.toByteArray()); } public HttpResponse receiveResponseHeader() throws HttpException, IOException { if (this.response == null) { flush(); } HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), this.response.getResponseCode(), null); // System.err.println("RECV: " + response.getStatusLine()); for (HTTPHeader h : this.response.getHeaders()) { // System.err.println("RECV: " + h.getName() + ": " + h.getValue()); response.addHeader(h.getName(), h.getValue()); } return response; } public void receiveResponseEntity(HttpResponse response) throws HttpException, IOException { if (this.response == null) { throw new IOException("receiveResponseEntity() called on closed connection"); } ByteArrayEntity bae = new ByteArrayEntity(this.response.getContent()); bae.setContentType(response.getFirstHeader("Content-Type")); response.setEntity(bae); response = null; } public void flush() throws IOException { if (request != null) { try { // System.err.println("----"); response = urlFS.fetch(request); request = null; }catch (IOException ex) { ex.printStackTrace(); throw ex; } } else { response = null; } } // From interface HttpConnection public void close() throws IOException { request = null; response = null; closed = true; // System.err.println("<<<<"); } public boolean isOpen() { return request != null || response != null; } public boolean isStale() { return !isOpen() && !closed; } public void setSocketTimeout(int timeout) { } public int getSocketTimeout() { return -1; } public void shutdown() throws IOException { close(); } public HttpConnectionMetrics getMetrics() { return null; } // From interface HttpInetConnection public InetAddress getLocalAddress() { return null; } public int getLocalPort() { return 0; } public InetAddress getRemoteAddress() { return null; } public int getRemotePort() { HttpHost host = route.getTargetHost(); return connManager.getSchemeRegistry().getScheme(host).resolvePort(host.getPort()); } // From interface ConnectionReleaseTrigger public void releaseConnection() throws IOException { connManager.releaseConnection(this, Long.MAX_VALUE, TimeUnit.MILLISECONDS); } public void abortConnection() throws IOException { unmarkReusable(); shutdown(); } private ClientConnectionManager connManager; private HttpRoute route; private Object state; private boolean reusable; private HTTPRequest request; private HTTPResponse response; private boolean closed; private static URLFetchService urlFS = URLFetchServiceFactory.getURLFetchService(); }