From 8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 Mon Sep 17 00:00:00 2001 From: Constantin Jucovschi Date: Fri, 24 Apr 2009 07:20:22 -0400 Subject: Initial commit --- java/rasj/clientcommhttp/Makefile | 62 ++ java/rasj/clientcommhttp/Makefile.dep | 0 java/rasj/clientcommhttp/RasCommDefs.class | Bin 0 -> 753 bytes java/rasj/clientcommhttp/RasCommDefs.java | 54 ++ java/rasj/clientcommhttp/RasHttpRequest.class | Bin 0 -> 12597 bytes java/rasj/clientcommhttp/RasHttpRequest.java | 805 ++++++++++++++++++++++++++ java/rasj/clientcommhttp/RasUtils.class | Bin 0 -> 1586 bytes java/rasj/clientcommhttp/RasUtils.java | 110 ++++ 8 files changed, 1031 insertions(+) create mode 100644 java/rasj/clientcommhttp/Makefile create mode 100644 java/rasj/clientcommhttp/Makefile.dep create mode 100644 java/rasj/clientcommhttp/RasCommDefs.class create mode 100644 java/rasj/clientcommhttp/RasCommDefs.java create mode 100644 java/rasj/clientcommhttp/RasHttpRequest.class create mode 100644 java/rasj/clientcommhttp/RasHttpRequest.java create mode 100644 java/rasj/clientcommhttp/RasUtils.class create mode 100644 java/rasj/clientcommhttp/RasUtils.java (limited to 'java/rasj/clientcommhttp') diff --git a/java/rasj/clientcommhttp/Makefile b/java/rasj/clientcommhttp/Makefile new file mode 100644 index 0000000..7c9dc43 --- /dev/null +++ b/java/rasj/clientcommhttp/Makefile @@ -0,0 +1,62 @@ +# -*-Makefile-*- (for Emacs) +# +# This file is part of rasdaman community. +# +# Rasdaman community is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rasdaman community 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rasdaman community. If not, see . +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see +# or contact Peter Baumann via . # Top Level makefile. This points to the various modules that have to be build +# and/or deployed +# +# MAKEFILE FOR: +# package rasj/clientcommhttp +# +# COMMENTS: +# +################################################################## +######################### Definitions ############################ + +# standard include with general options +include $(RMANBASE)/Makefile.inc + +# directory where HTML documentation is created +DOCDIR := $(DOCBASE)/rasdaman/java/rasj/clientcommhttp + +SRCS = RasCommDefs.java RasHttpRequest.java RasUtils.java +OBJS = ${SRCS:%.java=%.class} +MISCCLEAN = *.class + +########################### Targets ############################## + +# compile everything +.PHONY : all +all: $(OBJS) + +# HTML docu +docj: + -rm -rf $(DOCDIR)/rasj/clientcommhttp + $(JAVADOC) -author -d $(DOCDIR) rasj/clientcommhttp + +# delete all object files +clean: + -rm -f $(MISCCLEAN) + +############################ Dependencies ####################### +# general rules +# FIXME: should not be used here (only for relational adapter modules in rel*/), but is needed for Java targets +include $(RMANBASE)/Makefile.rel + diff --git a/java/rasj/clientcommhttp/Makefile.dep b/java/rasj/clientcommhttp/Makefile.dep new file mode 100644 index 0000000..e69de29 diff --git a/java/rasj/clientcommhttp/RasCommDefs.class b/java/rasj/clientcommhttp/RasCommDefs.class new file mode 100644 index 0000000..19067da Binary files /dev/null and b/java/rasj/clientcommhttp/RasCommDefs.class differ diff --git a/java/rasj/clientcommhttp/RasCommDefs.java b/java/rasj/clientcommhttp/RasCommDefs.java new file mode 100644 index 0000000..f08fae3 --- /dev/null +++ b/java/rasj/clientcommhttp/RasCommDefs.java @@ -0,0 +1,54 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see . +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see +* or contact Peter Baumann via . +*/ +/** *********************************************************** + *
+ *
+ * PURPOSE:
+ *
+ *
+ *
+ * COMMENTS:
+ *
+ * 
+ *********************************************************** */ + +package rasj.clientcommhttp; + +public interface RasCommDefs +{ + static final String rcsid = "@(#)Package rasj.clientcommhttp, class RasCommDefs: $Header: /home/rasdev/CVS-repository/rasdaman/java/rasj/clientcommhttp/RasCommDefs.java,v 1.5 2003/12/10 21:04:26 rasdev Exp $"; + + final public byte RASCLIENT = 1; + final public byte BROWSER = 2; + + final public byte RESPONSE_ERROR = 0; + final public byte RESPONSE_MDDS = 1; + final public byte RESPONSE_SKALARS = 2; + final public byte RESPONSE_INT = 3; + final public byte RESPONSE_OID = 4; + final static byte RESPONSE_OK_NEGATIVE = 98; + final public byte RESPONSE_OK = 99; + + final public byte BIG_ENDIAN = 0; + final public byte LITTLE_ENDIAN = 1; +} diff --git a/java/rasj/clientcommhttp/RasHttpRequest.class b/java/rasj/clientcommhttp/RasHttpRequest.class new file mode 100644 index 0000000..43ecc52 Binary files /dev/null and b/java/rasj/clientcommhttp/RasHttpRequest.class differ diff --git a/java/rasj/clientcommhttp/RasHttpRequest.java b/java/rasj/clientcommhttp/RasHttpRequest.java new file mode 100644 index 0000000..f80a2ca --- /dev/null +++ b/java/rasj/clientcommhttp/RasHttpRequest.java @@ -0,0 +1,805 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see . +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see +* or contact Peter Baumann via . +*/ +/************************************************************* + *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ * - return type complex not yet supported.
+ * 
+ *********************************************************** */ + +package rasj.clientcommhttp; + +import rasj.*; +import org.odmg.*; +import rasj.odmg.*; +import rasj.global.*; + +import java.io.*; +import java.net.*; +import java.lang.*; +import java.util.*; + +/** + * This class handles a HTTP-request to the RasDaMan server. + * The specified RasDaMan server is contacted, the specified command is sent to + * the server, and the result of the query is retrieved and stored in a byte array. + * The specification of the communication protocol is given below. + *

+ * + * @version $Revision: 1.35 $ + * + *

+ * Request structure

    + * The rasj HTTP request to the rasdaman server uses the HTTP POST-Format with the following + * parameters: + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Parameter:Description:Required for
    CommandInteger value specifying the desired action (e.g. OpenDB, BT, CT, CloseDB ...)all requests
    DatabaseString value specifying the databaseOpenDB, CloseDB
    ClientTypeInteger value defining the type of the client (at the moment always RasClient)all requests
    ClientIDInteger value specifying the ClientID (currently set to 1 for every client)all requests
    QueryStringString value containing the RasQL queryexecuteQuery
    EndianessInteger value containing the Client Endianessonly insert queries
    NumberOfQueryParametersInteger value specifying the number of query parametersonly insert queries
    QueryParametersByte Array containing the query parameters (MDDs) using the following format:
    + * + * + * + * + * + * + *
    IntegerStringStringIntegerStringStringStringLongByte[]
    objectTypeobjectTypeNametypeStructuretypeLengthdomainstorageLayoutOIDdataSizebinary data
    + *
    only insert queries
    + *

    + *

+ * + * Result formats / internal representation:

    + * The result of a HTTP request has one of the following forms:

    + * MDD Collections:
    + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    ByteByteStringLong(4Bytes)resultElement 1 ...
    StringStringStringLong(4Bytes)Byte[]
    Result type

    1=MDDCollection

    EndianessCollection typeNumber of resultsBaseType descriptionSpatial domainOIDSize of the Binary Data BlockBinary Data Block

    + * + * Skalar Collections:
    + * + * + * + * + * + * + * + * + * + * + * + *
    ByteByteStringLong(4Bytes)resultElement 1 ...
    StringLong(4Bytes)Byte[]
    Result type

    2=SkalarCollection

    EndianessCollection typeNumber of resultsElementType descriptionSize of the Binary Data BlockBinary Data Block

    + * + * Errors:
    + * + * + * + * + * + * + * + * + * + *
    ByteByteLong(4Bytes)Long(4Bytes)Long(4Bytes)String
    Result type

    0=Error

    EndianessError numberLine numberColumn numberToken

    + * + * Single Integer Value:
    + * + * + *
    ByteInteger
    Result type

    3=Integer

    Value

    + * + * OID:
    + * + * + *
    ByteStringStringDouble
    Result type

    4=OID

    systembasenamelocalOID

    + * + * Acknowledgement:
    + * + * + *
    Byte
    Result type

    99=OK

    + * + *

+ * + */ + +public class RasHttpRequest implements RasCommDefs, RasGlobalDefs +{ + + static final String rcsid = "@(#)Package rasj.clientcommhttp, class RasRequest: $Header: /home/rasdev/CVS-repository/rasdaman/java/rasj/clientcommhttp/RasHttpRequest.java,v 1.35 2003/12/19 15:36:43 rasdev Exp $"; + +/** + * The type of this client */ + private String client = "RASCLIENT"; + +/** + * The result type ( MDD Collection, Skalar Collection, Error, Integer ). This field is set + * automatically when a query has been executed, so there's no setResultType method. + */ + private byte resultType = 0; + +/** + * The result of the query +**/ + private Object result = null; + +/** + * This method sends a query to the RasDaMan Server and retrieves the results. + * + * @param con server connection + * @param parameters the parameters for the request as name/value pairs (for example "clientID=4354351&queryString=select img from test") + */ + public void execute( String serverURL, String parameters ) + throws RasQueryExecutionFailedException, RasConnectionFailedException + { + Debug.enterVerbose( "RasHttpRequest.execute: start. serverURL=" + serverURL + ", parameters=" + parameters ); + + BenchmarkTimer httpTimer = new BenchmarkTimer("httpRequest"); + BenchmarkTimer rcvTimer = new BenchmarkTimer("receive"); + + try + { + URL url = new URL( serverURL ); + + Debug.talkVerbose( "RasHttpRequest.execute: sending to " + url + " POST request=" + parameters ); + + httpTimer.startTimer(); + + BenchmarkTimer sendTimer = new BenchmarkTimer("send"); + sendTimer.startTimer(); + + // Send the query + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestProperty("Content-type","application/octet-stream"); + con.setRequestProperty("User-Agent","RasDaMan Java Client"); + con.setRequestProperty("Version","1.0"); + con.setRequestMethod("POST"); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + + OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(),"8859_1"); + out.write(parameters,0,parameters.length()); + out.flush(); + out.close(); + + sendTimer.stopTimer(); + sendTimer.print(); + + rcvTimer.startTimer(); + + // Read response + BenchmarkTimer getInputTimer = new BenchmarkTimer("getInputStream"); + getInputTimer.startTimer(); + DataInputStream in = new DataInputStream(con.getInputStream()); + // int BuffSize = con.getContentLength(); // not used -- PB 2003-jun-14 + // Debug.talkVerbose("RasHttpRequest.execute: buffSize=" + BuffSize); + getInputTimer.stopTimer(); + getInputTimer.print(); + + + /* variables for later use */ + byte[] b1 = new byte[1]; + byte[] b4 = new byte[4]; + byte endianess = 0; + String collType = null; + int numberOfResults = 0; + int dataSize = 0; + byte[] binData = null; + int readBytes = 0; + int readBytesTmp = 0; + DBag resultBag; + RasGMArray res = null; + + in.read(b1); + + resultType = b1[0]; + Debug.talkVerbose("RasHttpRequest.execute: resultType=" + resultType ); + switch( resultType ) + { + case RESPONSE_OK: + case RESPONSE_OK_NEGATIVE: + //Nothing todo + break; + + // +++++++++++++++++++++++++++++++++++++++++++++++++ + case RESPONSE_MDDS: + Debug.talkVerbose("RasHttpRequest.execute: result type is MDD." ); + // read Endianess + while(in.read(b1) == 0) + ; + endianess = b1[0]; + + // read Collection Type + collType = RasUtils.readString(in); + Debug.talkVerbose("RasHttpRequest.execute: colltype=" + collType); + + // read NumberOfResults + while(in.available() < 4) + ; + in.read(b4); + numberOfResults = RasUtils.ubytesToInt(b4,endianess); + Debug.talkVerbose("RasHttpRequest.execute: number of results: " + numberOfResults); + + // Initialize return-set and parameters + resultBag = new RasBag(); + String mddBaseType = null; + String domain = null; + String oid = ""; + RasOID roid = null; + + // do this for each result + for(int x = 0; x < numberOfResults; x++) + { + Debug.talkVerbose("RasHttpRequest.execute: handling result #" + (x+1) ); + //read mddBaseType + mddBaseType = RasUtils.readString(in); + + // read spatialDomain + domain = RasUtils.readString(in); + + // read OID + oid = RasUtils.readString(in); + //System.err.println("OID is " + oid); + roid = new RasOID(oid); + + // read size of binData + while(in.available() < 4) + ; + in.read(b4); + + dataSize = RasUtils.ubytesToInt(b4,endianess); + + Debug.talkVerbose("RasHttpRequest.execute: mddBaseType is " + mddBaseType + ", spatialDomain=" + domain + ", size of BinData=" + dataSize ); + + // read binData + binData = new byte[dataSize]; + readBytes = 0; + readBytesTmp = 0; + + while( (readBytesTmp != -1) && (readBytes < dataSize) ) + { + readBytesTmp = in.read(binData,readBytes,dataSize-readBytes); + readBytes += readBytesTmp; + } + + Debug.talkVerbose("RasHttpRequest.execute: read " + readBytes + " bytes."); + + RasType rType = RasType.getAnyType(mddBaseType); + //System.out.println(rType); + RasBaseType rb = null; + + if(rType.getClass().getName().equals("rasj.RasMArrayType")) + { + RasMArrayType tmp = (RasMArrayType)rType; + rb = tmp.getBaseType(); + } + else + { + Debug.talkCritical("RasHttpRequest.execute: exception: element of MDD Collection is no MArray" ); + throw new RasClientInternalException("RasHttpRequest","execute()","element of MDD Collection is no MArray"); + } + + if(rb.isBaseType()) + { + if(rb.isStructType()) + { + // It is a structType + //System.err.println("It is a structType"); + RasStructureType sType = (RasStructureType)rb; + //System.out.println(sType); + res = new RasGMArray(new RasMInterval(domain), 0); + res.setTypeLength(rb.getSize()); + res.setArraySize(dataSize); + res.setArray(binData); + //insert into result set + resultBag.add(res); + break; + + } else + { + // It is a primitiveType + RasPrimitiveType pType = (RasPrimitiveType)rb; + + //System.err.println("It's a primitive type: " + pType); + switch(pType.getTypeID()) + { + case RAS_BOOLEAN: + case RAS_BYTE: + case RAS_CHAR: + //System.err.println("It's a byte array!"); + res = new RasMArrayByte(new RasMInterval(domain)); + break; + case RAS_SHORT: + //System.err.println("It's a short array!"); + res = new RasMArrayShort(new RasMInterval(domain)); + break; + + case RAS_USHORT: + //System.err.println("It's a ushort array!"); + byte[] tmData = new byte[dataSize*2]; + for(int i=0;i + * Future versions will support other types like, for example, "BROWSER", where the + * results will be coded as standard HTTP-responses of certain mime types (for example + * "image/gif"). + * + * @param clientType currently only "RASCLIENT" supported + */ + public void setClientType ( String clientType ) + { + client = clientType; + } + +/** + * main program for testing purposes + */ + +/* BEGIN experimental *********************** + public static void main( String[] args ) + { + String server = "localhost"; + String port = "7001"; + String base = "RASBASE"; + String user = "rasguest"; + String passwd = "rasguest"; + String query = "select r from RAS_COLLECTIONNAMES as r"; + int count = 1; + + System.out.println( "Query test started." ); + + for (int i=args.length-1; i>=0; i--) + { + if (args[i].equals("--server")) + server = args[i+1]; + if (args[i].equals("--port")) + port = args[i+1]; + if (args[i].equals("--database")) + base = args[i+1]; + if (args[i].equals("--user")) + user = args[i+1]; + if (args[i].equals("--passwd")) + passwd = args[i+1]; + if (args[i].equals("--query")) + query = args[i+1]; + if (args[i].equals("--count")) + count = Integer.parseInt(args[i+1]); + } + + try + { + RasImplementation myApp = new RasImplementation("http://"+server+":"+port); + myApp.setUserIdentification(user, passwd); + + System.out.println( "opening database..." ); + Database myDb = myApp.newDatabase(); + myDb.open( base, Database.OPEN_READ_ONLY ); + + System.out.println( "starting transaction..." ); + Transaction myTa = myApp.newTransaction(); + myTa.begin(); + + String parameters = "Command=8&ClientID=1&QueryString=" + query; + String serverUrl = "http://" + server + ":" + 7102; // port; + + for (int i = 0; i < count; i++) + { + System.out.println( "sending query #" + i + "..." ); + execute( serverUrl, parameters ); + } + + System.out.println( "closing transaction..." ); + myTa.abort(); + + System.out.println( "closing database..." ); + myDb.close(); + System.out.println( "all done." ); + + } + catch(Exception e) + { + System.err.println( e.getMessage() ); + } + + System.out.println( "Query test done." ); + + } // main() +END experimental ***********************/ +} + + + diff --git a/java/rasj/clientcommhttp/RasUtils.class b/java/rasj/clientcommhttp/RasUtils.class new file mode 100644 index 0000000..33c59a3 Binary files /dev/null and b/java/rasj/clientcommhttp/RasUtils.class differ diff --git a/java/rasj/clientcommhttp/RasUtils.java b/java/rasj/clientcommhttp/RasUtils.java new file mode 100644 index 0000000..1ffa049 --- /dev/null +++ b/java/rasj/clientcommhttp/RasUtils.java @@ -0,0 +1,110 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see . +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see +* or contact Peter Baumann via . +*/ +/** *********************************************************** + *
+ *
+ * PURPOSE:
+ *
+ *
+ *
+ * COMMENTS:
+ *
+ * 
+ *********************************************************** */ + +package rasj.clientcommhttp; + +import java.io.*; +import java.net.*; +import java.lang.*; + +/** + * + * This class provides some useful methods for reading binary data from a stream + * or converting objects to a byte array for transmission. + * + */ +public final class RasUtils implements RasCommDefs +{ + static final String rcsid = "@(#)Package rasj.clientcommhttp, class RasUtils: $Header: /home/rasdev/CVS-repository/rasdaman/java/rasj/clientcommhttp/RasUtils.java,v 1.5 2003/12/10 21:04:26 rasdev Exp $"; + + public RasUtils() + { + } + + /** + * This method is used for turning up to 4 unsigned bytes into signed integers. + * + * @param uBytes one to four Bytes which are interpreted as an unsigned Integer + * @param endianess determines the order of the bytes: 0 = bigendian, 1 = little endian + */ + public static int ubytesToInt( byte[] uBytes, byte endianess ) + { + int tmpi; + byte tmpb; + int retval = 0; + + for( int i = 0; i < uBytes.length; i++ ) + { + if( endianess == BIG_ENDIAN ) + tmpb = uBytes[uBytes.length-i-1]; + else + tmpb = uBytes[i]; + + tmpi = 0; + /* Byte < 0 */ + if( (int)tmpb < 0 ) + tmpi = 256 + tmpb; + else + tmpi = tmpb; + + tmpi <<= (i*8); + retval += tmpi; + } + return retval; + } + + /** + * Reads characters from a stream until a '\0' character is reached. + * + * @param in BufferedInputStream to be read from ( must have been initialized before! ) + */ + public static String readString( InputStream in ) + throws IOException + { + byte b = (byte) '\0'; + byte[] b1 = new byte[1]; + String retval = ""; + + while(in.read(b1) == 0); + while(b1[0] != b) + { + retval =retval + (char)b1[0]; + while(in.read(b1) == 0); + } + return retval; + } + + + +} -- cgit