package com.dbxml.labrador.http;
/*
* The dbXML Labrador Software License, Version 1.0
*
*
* Copyright (c) 2003 The dbXML Group, L.L.C. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by The
* dbXML Group, L.L.C. (http://www.dbxml.com/)."
* Alternately, this acknowledgment may appear in the software
* itself, if and wherever such third-party acknowledgments normally
* appear.
*
* 4. The names "Labrador" and "dbXML Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* info@dbxml.com
*
* 5. Products derived from this software may not be called "Labrador",
* nor may "Labrador" appear in their name, without prior written
* permission of The dbXML Group, L.L.C..
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE DBXML GROUP, L.L.C. OR ITS
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* $Id: HTTPProxyInstance.java,v 1.8 2003/12/15 06:43:10 bradford Exp $
*/
import com.dbxml.labrador.Endpoint;
import com.dbxml.labrador.Handler;
import com.dbxml.labrador.Request;
import com.dbxml.labrador.Response;
import com.dbxml.labrador.broker.Broker;
import com.dbxml.labrador.broker.BrokerContext;
import com.dbxml.labrador.rest.RESTHandler;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;
/**
* HTTPProxyInstance
*/
public final class HTTPProxyInstance {
public static final String REST_DEFAULT_METHOD = "get";
private static final byte[] EmptyBytes = new byte[0];
private static final int BUFFER_SIZE = 4096;
private static final String[] PASSTHRU_REQUEST_HEADERS = new String[] {
HTTP.HEADER_AUTHORIZATION,
HTTP.HEADER_IF_MODIFIED_SINCE,
HTTP.HEADER_COOKIE,
};
private static final String[] PASSTHRU_RESPONSE_HEADERS = new String[] {
HTTP.HEADER_WWW_AUTHENTICATE,
HTTP.HEADER_SET_COOKIE,
HTTP.HEADER_LAST_MODIFIED
};
private String uri;
private Map headers;
public HTTPProxyInstance(String uri, Map headers) {
this.uri = uri;
this.headers = headers;
}
public byte[] get() throws Exception {
try {
// Let's see if we can interact with Labrador's HTTP Server for REST calls
BrokerContext context = Broker.getInstance().getBrokerContext();
Handler handler = context.getHandler();
Endpoint endpoint = context.getRequestEndpoint();
URL url = new URL(uri);
URLConnection conn = url.openConnection();
conn.setUseCaches(true);
conn.setDoInput(true);
conn.setDoOutput(false);
String modSince = null;
String lastMod = null;
boolean browserClient = handler instanceof RESTHandler && endpoint instanceof HTTPServerBase;
// Yank some request headers from the client and pass them through
if ( browserClient ) {
Request request = context.getRequest();
for ( int i = 0; i < PASSTHRU_REQUEST_HEADERS.length; i++ ) {
String key = PASSTHRU_REQUEST_HEADERS[i];
String value = request.getHeader(key);
if ( value != null && value.length() > 0 ) {
if ( key == HTTP.HEADER_IF_MODIFIED_SINCE )
modSince = value;
else
conn.setRequestProperty(key, value);
}
}
}
// Set or override Headers
Iterator iter = headers.keySet().iterator();
while ( iter.hasNext() ) {
String key = (String)iter.next();
String value = (String)headers.get(key);
conn.setRequestProperty(key, value);
}
// Connect to the server and make the request
conn.connect();
// Yank some reponse headers from the server and pass them through
if ( browserClient ) {
Response response = context.getResponse();
for ( int i = 0; i < PASSTHRU_RESPONSE_HEADERS.length; i++ ) {
String key = PASSTHRU_RESPONSE_HEADERS[i];
String value = conn.getHeaderField(key);
if ( value != null && value.length() > 0 ) {
response.setHeader(key, value);
if ( key == HTTP.HEADER_LAST_MODIFIED ) {
lastMod = value;
response.setHeader(HTTP.HEADER_CACHE_CONTROL, HTTP.VALUE_CACHE);
}
}
}
// If we get a doc that hasn't been modified just short curcuit
if ( modSince != null && lastMod != null && modSince.equals(lastMod) )
throw new HTTPException(HTTP.CODE_NOT_MODIFIED, HTTP.STATUS_NOT_MODIFIED);
}
byte[] buffer;
if ( conn.getContentLength() > 0 ) {
// Time to actually pass through the content
InputStream is = conn.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE);
buffer = new byte[BUFFER_SIZE];
int count = 0;
do {
count = is.read(buffer);
if ( count > 0 )
bos.write(buffer, 0, count);
}
while ( count != -1 );
is.close();
buffer = bos.toByteArray();
}
else
buffer = EmptyBytes;
return buffer;
}
catch ( HTTPException e ) {
throw e;
}
catch ( Exception e ) {
e.printStackTrace(System.err);
throw e;
}
}
}