rlubke 01/12/17 18:31:01
Modified: src/tools/org/apache/tomcat/task GTest.java
Log:
Cleaned up/enhanced GTest processing logic.
Added the following functionality:
- The ability to specify headers that shouldn't
be found in the server's response.
- The ability to handle response headers
in the format of:
TestHeader: 2
TestHeader: 3
-or-
TestHeader: 2,3
- If using strong comparison ( exactMatch="true" in gtest target )
and a byte mismatch occurs, a hex dump of the server's response
and the goldenfile are displayed to the user.
Corrected the following:
- HTTP header fields are now compared so that case is ignored while
fields are compared in a case sensitive manner.
Still to do:
- Add logic so that a gtest target can be configured to expect
multiple headers from the server -> expectHeader="name:val|name2:val2"
- Continue cleanup where needed.
Revision Changes Path
1.4 +1206 -539 jakarta-watchdog-4.0/src/tools/org/apache/tomcat/task/GTest.java
Index: GTest.java
===================================================================
RCS file:
/home/cvs/jakarta-watchdog-4.0/src/tools/org/apache/tomcat/task/GTest.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- GTest.java 2001/09/28 04:09:56 1.3
+++ GTest.java 2001/12/18 02:31:01 1.4
@@ -1,8 +1,8 @@
/**
- *
- * @Author Costin, Ramesh.Mandava
- *
- */
+*
+* @Author Costin, Ramesh.Mandava
+*
+*/
package org.apache.tomcat.task;
import java.net.*;
@@ -14,594 +14,999 @@
// derived from Jsp
+
public class GTest extends Task {
- String prefix="http://localhost:8080/test";
- String host="localhost";
- int port=8080;
- int debug=0;
+
+ private static final String ZEROS = "00000000";
+ private static final int SHORTPADSIZE = 4;
+ private static final int BYTEPADSIZE = 2;
+ private static final int CARRIAGE_RETURN = 13;
+ private static final int LINE_FEED = 10;
+
+ String prefix = "http";
+ String host = "localhost";
+ int port = 8080;
+ int debug = 0;
- String description="No description";
+ String description = "No description";
String request;
- Hashtable requestHeaders;
+ HashMap requestHeaders = new HashMap();
String content;
-
+
// Expected response
- boolean magnitude=true;
- boolean exactMatch=false;
+ boolean magnitude = true;
+ boolean exactMatch = false;
+
+ // expect a response body
+ boolean expectResponseBody = true;
+
// Match the body against a golden file
String goldenFile;
// Match the body against a string
String responseMatch;
// the response should include the following headers
- Hashtable expectHeaders;
+ HashMap expectHeaders = new HashMap();
+
+ // Headers that should not be found in response
+ HashMap unexpectedHeaders = new HashMap();
+
// Match request line
- String returnCode="";
+ String returnCode = "";
+ String returnCodeMsg = "";
// Actual response
String responseLine;
- String responseBody;
- Hashtable headers;
+ byte[] responseBody;
+ HashMap headers;
// For Report generation
- static String resultFileName=null;
- static FileOutputStream resultOut=null;
- boolean firstTask=false;
- boolean lastTask=false;
- String expectedString;
- String actualString;
-
- String testName;
- String assertion;
- String testStrategy;
-
- // For Session Tracking
- static Hashtable sessionHash;
- static Hashtable cookieHash;
-
- String testSession;
- Vector cookieVector;
- URL requestURL;
- CookieController cookieController ;
+ static String resultFileName = null;
+ static FileOutputStream resultOut = null;
+ boolean firstTask = false;
+ boolean lastTask = false;
+ String expectedString;
+ String actualString;
+
+ String testName;
+ String assertion;
+ String testStrategy;
+
+ // For Session Tracking
+ static Hashtable sessionHash;
+ static Hashtable cookieHash;
+
+ String testSession;
+ Vector cookieVector;
+ URL requestURL;
+ CookieController cookieController ;
+ /**
+ * Creates a new <code>GTest</code> instance.
+ *
+ */
+ public GTest() {}
+ /**
+ * <code>setTestSession</code> adds a
+ * CookieController for the value of sessionName
+ *
+ * @param sessionName a <code>String</code> value
+ */
+ public void setTestSession( String sessionName ) {
+ testSession = sessionName;
+ if ( sessionHash == null ) {
+ sessionHash = new Hashtable();
+ } else if ( sessionHash.get( sessionName ) == null ) {
+ sessionHash.put ( sessionName, new CookieController() );
+ }
+ }
- public void setTestSession( String sessionName )
- {
- testSession= sessionName;
- if ( sessionHash==null)
- {
- sessionHash= new Hashtable();
- }
- else if ( sessionHash.get( sessionName) == null )
- {
- sessionHash.put ( sessionName, new CookieController() );
- }
- }
-
- public void setTestName ( String tn )
- throws IOException
- {
- testName=tn;
- }
+ /**
+ * <code>setTestName</code> sets the current test name.
+ *
+ * @param tn current testname.
+ */
+ public void setTestName ( String tn ) {
+ testName = tn;
+ }
- public void setAssertion ( String assertion )
- throws IOException
- {
- this.assertion = assertion;
- }
- public void setTestStrategy ( String strategy )
- throws IOException
- {
- testStrategy = strategy;
- }
-
- public String getTestName( )
- {
- return testName;
- }
- public String getAssertion( )
- {
- return assertion;
- }
- public String getTestStrategy( )
- {
- return testStrategy;
- }
+ /**
+ * <code>setAssertion</code> sets the assertion text
+ * for the current test.
+ *
+ * @param assertion assertion text
+ */
+ public void setAssertion ( String assertion ) {
+ this.assertion = assertion;
+ }
- public void setResultFileName( String fileName )
- throws IOException
- {
- if ( firstTask )
- {
- resultFileName = fileName;
- File passedFile= new File( fileName );
- System.out.println("Full Path of Result File-> " +
passedFile.getAbsolutePath() );
- resultOut = new FileOutputStream( passedFile);
- if ( resultOut == null )
- {
- System.out.println("ERROR: Not able to create FileOutputStream
for result");
- }
- else
- {
- resultOut.write("<root>\n".getBytes() );
- }
- }
-
- }
- public void setFirstTask( boolean val )
- {
- firstTask=val;
- }
- public void setLastTask ( boolean val )
- throws IOException
- {
- lastTask=val;
-
- }
-
+ /**
+ * <code>setTestStrategy</code> sets the test strategy
+ * for the current test.
+ *
+ * @param strategy test strategy text
+ */
+ public void setTestStrategy ( String strategy ) {
+ testStrategy = strategy;
+ }
- public GTest() {
+ /**
+ * <code>getTestName</code> returns the current
+ * test name.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getTestName( ) {
+ return testName;
}
-
-
- public void setPrefix(String prefix) {
- this.prefix=prefix;
+
+ /**
+ * <code>getAssertion</code> returns the current
+ * assertion text.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getAssertion( ) {
+ return assertion;
}
-
- public void setHost(String h) {
- this.host=h;
+
+ /**
+ * <code>getTestStrategy</code> returns the current
+ * test strategy test.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getTestStrategy( ) {
+ return testStrategy;
}
-
- public void setPort(String portS) {
- this.port=Integer.valueOf( portS).intValue();
+
+ /**
+ * <code>setResultFileName</code> allows the user
+ * to set the filename in which to write test results
+ * to.
+ *
+ * @param fileName result filename
+ * @exception IOException if an error occurs
+ */
+ public void setResultFileName( String fileName )
+ throws IOException {
+ // if ( firstTask ) {
+ resultFileName = fileName;
+ File passedFile = new File( fileName );
+ System.out.println( "Full Path of Result File-> " +
passedFile.getAbsolutePath() );
+ resultOut = new FileOutputStream( passedFile );
+
+ if ( resultOut == null ) {
+ System.out.println( "ERROR: Not able to create FileOutputStream for
result" );
+ } else {
+ resultOut.write( "<root>\n".getBytes() );
+ }
+ // }
}
- public void setExactMatch(String exact) {
- exactMatch=Boolean.valueOf( exact ).booleanValue();
+ /*
+ *public void setFirstTask( boolean val ) {
+ * firstTask = val;
+ *}
+ *
+ *public void setLastTask ( boolean val )
+ *throws IOException {
+ * lastTask = val;
+ *
+ *}
+ */
+
+ /**
+ * <code>setPrefix</code> sets the protocol
+ * prefix. Defaults to "http"
+ *
+ * @param prefix Either http or https
+ */
+ public void setPrefix( String prefix ) {
+ this.prefix = prefix;
}
- /** Set the port as int - different name to avoid confusing ant
+ /**
+ * <code>setHost</code> sets hostname where
+ * the target server is running. Defaults to
+ * "localhost"
+ *
+ * @param h a <code>String</code> value
*/
- public void setPortInt(int i) {
- this.port=i;
+ public void setHost( String h ) {
+ this.host = h;
}
- /** Description should be in <test description=""/>
+ /**
+ * <code>setPort</code> sets the port
+ * that the target server is listening on.
+ * Defaults to "8080"
+ *
+ * @param portS a <code>String</code> value
*/
- public String getDescription() {
- return description;
+ public void setPort( String portS ) {
+ this.port = Integer.valueOf( portS ).intValue();
}
- public void setDescription(String description) {
- this.description=description;
+ /**
+ * <code>setExactMatch</code> determines if a
+ * byte-by-byte comparsion is made of the server's
+ * response and the test's goldenFile, or if
+ * a token comparison is made. By default, only
+ * a token comparison is made ("false").
+ *
+ * @param exact a <code>String</code> value
+ */
+ public void setExactMatch( String exact ) {
+ exactMatch = Boolean.valueOf( exact ).booleanValue();
}
- public void setContent(String s) {
- this.content=s;
+ /**
+ * <code>setContent</code> String value upon which
+ * the request header Content-Length is based upon.
+ *
+ * @param s a <code>String</code> value
+ */
+ public void setContent( String s ) {
+ this.content = s;
}
+ /**
+ * <code>setDebug</code> enables debug output.
+ * By default, this is disabled ( value of "0" ).
+ *
+ * @param debugS a <code>String</code> value
+ */
public void setDebug( String debugS ) {
- debug=Integer.valueOf( debugS).intValue();
+ debug = Integer.valueOf( debugS ).intValue();
}
+ /**
+ * <code>setMagnitude</code> Expected return
+ * value of the test execution.
+ * Defaults to "true"
+ *
+ * @param magnitudeS a <code>String</code> value
+ */
public void setMagnitude( String magnitudeS ) {
- magnitude = Boolean.valueOf(magnitudeS).booleanValue();
+ magnitude = Boolean.valueOf( magnitudeS ).booleanValue();
}
+ /**
+ * <code>setGoldenFile</code> Sets the goldenfile
+ * that will be used to validate the server's response.
+ *
+ * @param s fully qualified path and filename
+ */
public void setGoldenFile( String s ) {
- this.goldenFile=s;
+ this.goldenFile = s;
+ }
+
+ /**
+ * <code>setExpectResponseBody</code> sets a flag
+ * to indicate if a response body is expected from the
+ * server or not
+ *
+ * @param b a <code>boolean</code> value
+ */
+ public void setExpectResponseBody( boolean b ) {
+ this.expectResponseBody = b;
}
- //Ramesh
+ /**
+ * <code>setExpectHeaders</code> Configures GTest
+ * to look for the header passed in the server's
+ * response.
+ *
+ * @param s a <code>String</code> value in the
+ * format of <header-field>:<header-value>
+ */
public void setExpectHeaders( String s ) {
- this.expectHeaders=new Hashtable();
- getHeaderDetails( s, expectHeaders );
+ this.expectHeaders = new HashMap();
+ getHeaderDetails( s, expectHeaders, false );
+ }
- //parseHeader( s, expectHeaders );
+ /**
+ * <code>setUnexpectedHeaders</code> Configures GTest
+ * to look for the header passed to validate that it
+ * doesn't exist in the server's response.
+ *
+ * @param s a <code>String</code> value in the
+ * format of <header-field>:<header-value>
+ */
+ public void setUnexpectedHeaders( String s ) {
+ this.unexpectedHeaders = new HashMap();
+ getHeaderDetails( s, unexpectedHeaders, false );
}
+ /**
+ * <code>setResponseMatch</code> Match the
+ * passed value in the server's response.
+ *
+ * @param s a <code>String</code> value
+ */
public void setResponseMatch( String s ) {
- this.responseMatch=s;
+ this.responseMatch = s;
}
+ /**
+ * <code>setRequest</code> Sets the HTTP/HTTPS
+ * request to be sent to the target server
+ * Ex.
+ * GET /servlet_path/val HTTP/1.0
+ *
+ * @param s a <code>String</code> value in the form
+ * of METHOD PATH HTTP_VERSION
+ * @exception Exception if an error occurs
+ */
public void setRequest ( String s ) throws Exception {
- this.request=s;
- String addressString = request.substring( request.indexOf("/"),
request.indexOf("HTTP") ).trim();
- if ( addressString.indexOf("?") > -1 )
- {
- addressString = addressString.substring(0, addressString.indexOf("?")
) ;
- }
- requestURL= new URL("http", host, port, addressString);
+ this.request = s;
+ String addressString = request.substring( request.indexOf( "/" ),
request.indexOf( "HTTP" ) ).trim();
+
+ if ( addressString.indexOf( "?" ) > -1 ) {
+ addressString = addressString.substring( 0, addressString.indexOf( "?"
) ) ;
+ }
+
+ requestURL = new URL( "http", host, port, addressString );
}
-
- public void setReturnCode( String s ) {
- this.returnCode=s;
+
+ /**
+ * <code>setReturnCode</code> Sets the expected
+ * return code from the server's response.
+ *
+ * @param code a valid HTTP response status code
+ */
+ public void setReturnCode( String code ) {
+ this.returnCode = code;
}
- public void setHeaders( String s ) {
- requestHeaders=new Hashtable();
- parseHeader( s, requestHeaders );
+ /**
+ * Describe <code>setReturnCode</code> Sets the expected
+ * return code and message to be found in the server's
+ * response.
+ *
+ * @param code a valid HTTP resonse status code
+ * @param message a <code>String</code> value
+ */
+ public void setReturnCode( String code, String message ) {
+ this.returnCode = code;
+ this.returnCodeMsg = message;
}
- //Ramesh
+ /**
+ * <code>setRequestHeaders</code> Configures the request
+ * headers GTest should send to the target server.
+ *
+ * @param s a <code>String</code> value in for format
+ * of <field-name>:<field-value>
+ */
public void setRequestHeaders( String s ) {
- requestHeaders=new Hashtable();
- getHeaderDetails( s, requestHeaders );
- if( debug>0)
- {
- System.out.println("Request Headers -> " );
- Enumeration reqHeaderEnum = requestHeaders.keys();
- while ( reqHeaderEnum.hasMoreElements() )
- {
- String headerKey = (String)reqHeaderEnum.nextElement();
- System.out.println( headerKey + "::" +
requestHeaders.get(headerKey) );
- }
- }
-
- //parseHeader( s, requestHeaders );
+ requestHeaders = new HashMap();
+ getHeaderDetails( s, requestHeaders, true );
}
-
+
+ /**
+ * <code>execute</code> Executes the test.
+ *
+ * @exception BuildException if an error occurs
+ */
public void execute() throws BuildException {
-
- try {
- if ( resultOut != null )
- {
- resultOut.write("<test>".getBytes() );
- resultOut.write( ("\n<testName>"+ testName + "</testName>").getBytes()
);
- resultOut.write( ("\n<assertion>"+ assertion +
"</assertion>").getBytes() );
- resultOut.write( ("\n<testStrategy>"+ testStrategy +
"</testStrategy>\n").getBytes() );
- }
-
- dispatch(request, requestHeaders);
- //dispatch(request, null);
+ try {
- boolean result=checkResponse( magnitude );
- if(result) {
- if ( resultOut != null )
- {
- resultOut.write("<result>PASS</result>\n".getBytes() );
- }
+ if ( resultOut != null ) {
+ resultOut.write( "<test>".getBytes() );
+ resultOut.write( ( "\n<testName>" + testName + "</testName>"
).getBytes() );
+ resultOut.write( ( "\n<assertion>" + assertion + "</assertion>"
).getBytes() );
+ resultOut.write( ( "\n<testStrategy>" + testStrategy +
"</testStrategy>\n" ).getBytes() );
+ }
- if( "No description".equals( description )) {
- System.out.println("OK " + request );
- }
- else
- System.out.println("OK " + description + " (" + request + ")");
- } else {
- if ( resultOut != null )
- {
- resultOut.write("<result>FAIL</result>\n".getBytes() );
- }
+ dispatch( request, requestHeaders );
+ //dispatch(request, null);
- if( "No description".equals( description )) {
- System.out.println("FAIL " + request );
- } else
- System.out.println("FAIL " + description + " (" + request + ")" );
- }
-
- if ( resultOut != null )
- {
- resultOut.write("</test>\n".getBytes() );
- if ( lastTask== true)
- {
- resultOut.write("</root>\n".getBytes() );
- resultOut.close();
- }
- }
+ boolean result = checkResponse( magnitude );
- } catch(Exception ex ) {
- if( "No description".equals( description )) {
- System.out.println("FAIL " + request );
- } else
- System.out.println("FAIL " + description + " (" + request + ")" );
- ex.printStackTrace();
- }
+ if ( result ) {
+ if ( resultOut != null ) {
+ resultOut.write( "<result>PASS</result>\n".getBytes() );
+ }
+
+ if ( "No description".equals( description ) ) {
+ System.out.println( " OK " + request );
+ } else
+ System.out.println( " OK " + description + " (" + request + ")"
);
+ } else {
+ if ( resultOut != null ) {
+ resultOut.write( "<result>FAIL</result>\n".getBytes() );
+ }
+
+ if ( "No description".equals( description ) ) {
+ System.out.println( " FAIL " + request );
+ } else
+ System.out.println( " FAIL " + description + " (" + request +
")" );
+ }
+
+ if ( resultOut != null ) {
+ resultOut.write( "</test>\n".getBytes() );
+
+ if ( lastTask == true ) {
+ resultOut.write( "</root>\n".getBytes() );
+ resultOut.close();
+ }
+ }
+
+ } catch ( Exception ex ) {
+ if ( "No description".equals( description ) ) {
+ System.out.println( " FAIL " + request );
+ } else
+ System.out.println( " FAIL " + description + " (" + request + ")" );
+
+ ex.printStackTrace();
+ }
}
- private boolean checkResponse(boolean testCondition)
- throws Exception
- {
+ /**
+ * <code>checkResponse</code> Executes various response
+ * checking mechanisms against the server's response.
+ * Checks include:
+ * <ul>
+ * <li>expected headers
+ * <li>unexpected headers
+ * <li>return codes and messages in the Status-Line
+ * <li>response body comparison againt a goldenfile
+ * </ul>
+ *
+ * @param testCondition a <code>boolean</code> value
+ * @return a <code>boolean</code> value
+ * @exception Exception if an error occurs
+ */
+ private boolean checkResponse( boolean testCondition )
+ throws Exception {
boolean responseStatus = true;
-
- // If returnCode doesn't match
- if( request.indexOf( "HTTP/1." ) > -1) {
- boolean match= ( responseLine!=null && responseLine.indexOf(returnCode) >
-1);
- if( match != testCondition ) {
- responseStatus = false;
- System.out.println("ERROR in: " + request);
- System.out.println(" Expecting: " + returnCode );
- System.out.println(" Got : " + responseLine);
- if ( resultOut != null )
- {
- expectedString = "<expectedReturnCode>" +
returnCode + "</expectedReturnCode>\n";
- actualString = "<actualReturnCode>"+
responseLine + "</actualReturnCode>\n";
- resultOut.write(expectedString.getBytes() );
- resultOut.write(actualString.getBytes() );
+ boolean match = false;
+
+ if ( responseLine != null ) {
+ // If returnCode doesn't match
+ if ( responseLine.indexOf( "HTTP/1." ) > -1 ) {
- }
- }
- }
+ if ( !returnCode.equals( "" ) ) {
+ boolean resCode = ( responseLine.indexOf( returnCode ) > -1 );
+ boolean resMsg = ( responseLine.indexOf( returnCodeMsg ) > -1 );
- if( expectHeaders != null ) {
- // Check if we got the expected headers
- if(headers==null) {
- System.out.println("ERROR no response header, expecting header");
- }
- Enumeration e=expectHeaders.keys();
- while( e.hasMoreElements()) {
- String key=(String)e.nextElement();
- String value=(String)expectHeaders.get(key);
- String respValue=(String)headers.get(key);
- if( respValue==null || respValue.indexOf( value ) <0 ) {
- System.out.println("ERROR expecting header " + key + ":" +
- value + " GOT: " + respValue+ " HEADERS(" +
headers + ")");
- if ( resultOut != null )
- {
- expectedString = "<expectedHeader>" + key + ":"+ value
+ "</expectedHeader>\n";
- actualString = "<actualHeader>"+ key + ":" + respValue
+ "</actualHeader>\n";
- resultOut.write(expectedString.getBytes() );
- resultOut.write(actualString.getBytes() );
-
+ if ( returnCodeMsg.equals( "" ) ) {
+ match = resCode;
+ } else {
+ match = ( resCode && resMsg );
+ }
+
+ if ( match != testCondition ) {
+ responseStatus = false;
+ System.out.println( " Error in: " + request );
+ System.out.println( " Expected Status-Line with one or all
of the following values:" );
+ System.out.println( " Status-Code: " + returnCode );
+ System.out.println( " Reason-Phrase: " + returnCodeMsg );
+ System.out.println( " Received: " + responseLine );
+
+ if ( resultOut != null ) {
+ String expectedStatusCode = "<expectedStatusCode>" +
returnCode + "</expectedReturnCode>\n";
+ String expectedReasonPhrase = "<expectedReasonPhrase>" +
returnCodeMsg + "</expectedReasonPhrase>";
+ actualString = "<actualStatusLine>" + responseLine +
"</actualStatusLine>\n";
+ resultOut.write( expectedStatusCode.getBytes() );
+ resultOut.write( expectedReasonPhrase.getBytes() );
+ resultOut.write( actualString.getBytes() );
}
-
- return false;
+ } else {
+ if ( debug > 0 ) {
+ System.out.println( " Expected values found in
Status-Line" );
+ }
+ }
}
+ } else {
+ responseStatus = false;
+ System.out.println( " Error: Received invalid HTTP version in
response header from target Server" );
+ System.out.println( " Target server must support HTTP 1.0 or
HTTP 1.1" );
+ System.out.println( " Response from server: " + responseLine );
}
-
+ } else {
+ responseStatus = false;
+ System.out.println( " Error in: " + request );
+ System.out.println( " Expecting response from server, received
null" );
}
-
- if( responseMatch != null ) {
- // check if we got the string we wanted
- if( responseBody == null ) {
- System.out.println("ERROR: got no response, expecting " +
responseMatch);
- return false;
+
+ /*
+ * Check for headers the test expects to be in the server's response
+ */
+
+ // Duplicate set of response headers
+ HashMap copiedHeaders = cloneHeaders( headers );
+
+ // used for error reporting
+ String currentHeaderField = null;
+ String currentHeaderValue = null;
+
+ if ( !expectHeaders.isEmpty() ) {
+ boolean found = false;
+ String expHeader = null;
+
+ if ( debug > 0 ) {
+ System.out.println( " Looking for expected response headers..." );
}
- if( responseBody.indexOf( responseMatch ) < 0) {
- System.out.println("ERROR: expecting match on " + responseMatch);
- System.out.println("GOT: " );
- System.out.println(responseBody );
+
+ if ( !headers.isEmpty() ) {
+ Iterator expectIterator = expectHeaders.keySet().iterator();
+ while ( expectIterator.hasNext() ) {
+ found = false;
+ String expFieldName = (String) expectIterator.next();
+ currentHeaderField = expFieldName;
+ ArrayList expectValues = (ArrayList) expectHeaders.get(
expFieldName );
+ Iterator headersIterator = copiedHeaders.keySet().iterator();
+
+ while( headersIterator.hasNext() ) {
+ String headerFieldName = (String) headersIterator.next();
+ ArrayList headerValues = (ArrayList) copiedHeaders.get(
headerFieldName );
+
+ // compare field names and values in an HTTP 1.x compliant
fashion
+ if ( ( headerFieldName.equalsIgnoreCase( expFieldName ) ) )
{
+ int hSize = headerValues.size();
+ int eSize = expectValues.size();
+
+ // number of expected headers found in server response
+ int numberFound = 0;
+
+ for ( int i = 0; i < eSize; i++ ) {
+ currentHeaderValue = (String) expectValues.get( i );
+
+ if ( headerValues.contains( currentHeaderValue ) ) {
+ numberFound++;
+ headerValues.remove( headerValues.indexOf(
currentHeaderValue ) );
+ }
+ }
+ if ( numberFound == eSize ) {
+ found = true;
+ }
+ }
+ }
+ if ( !found ) {
+ /*
+ * Expected headers not found in server response.
+ * Break the processing loop.
+ */
+ break;
+ }
+ }
+ }
+
+ if ( !found ) {
+ StringBuffer actualBuffer = new StringBuffer( 128 );
+ System.out.println( " Unable to find the expected header: '" +
currentHeaderField + ": " + currentHeaderValue + "' in the server's response." );
+ if ( resultOut != null ) {
+ expectedString = "<expectedHeader>" + currentHeaderField + ": " +
currentHeaderValue + "</expectedHeader>\n";
+ }
+ if ( !headers.isEmpty() ) {
+ System.out.println( " The following headers were received: " );
+ Iterator iter = headers.keySet().iterator();
+ while ( iter.hasNext() ) {
+ String headerName = (String) iter.next();
+ ArrayList vals = (ArrayList) headers.get( headerName );
+ String[] val = (String[]) vals.toArray( new String[
vals.size() ] );
+ for ( int i = 0; i < val.length; i++ ) {
+ System.out.println( "\tHEADER -> " + headerName + ": "
+ val[ i ] );
+ if ( resultOut != null ) {
+ actualBuffer.append( "<actualHeader>" + headerName +
": " + val[ i ] + "</actualHeader>\n" );
+ }
+ }
+ }
+ if ( resultOut != null ) {
+ resultOut.write( expectedString.getBytes() );
+ resultOut.write( actualBuffer.toString().getBytes() );
+ }
+ }
+ return false;
+ }
+ }
+
+ /*
+ * Check to see if we're looking for unexpected headers.
+ * If we are, compare the values in the unexectedHeaders
+ * ArrayList against the headers from the server response.
+ * if the unexpected header is found, then return false.
+ */
+
+ if ( !unexpectedHeaders.isEmpty() ) {
+ boolean found = false;
+ String unExpHeader = null;
+ if ( debug > 0 ) {
+ System.out.println( " looking for unexpected headers..." );
}
+
+ // Check if we got any unexpected headers
+
+ if ( !copiedHeaders.isEmpty() ) {
+ Iterator unexpectedIterator = unexpectedHeaders.keySet().iterator();
+ while ( unexpectedIterator.hasNext() ) {
+ found = false;
+ String unexpectedFieldName = (String) unexpectedIterator.next();
+ ArrayList unexpectedValues = (ArrayList) unexpectedHeaders.get(
unexpectedFieldName );
+ Iterator headersIterator = copiedHeaders.keySet().iterator();
+
+ while ( headersIterator.hasNext() ) {
+ String headerFieldName = (String) headersIterator.next();
+ ArrayList headerValues = (ArrayList) copiedHeaders.get(
headerFieldName );
+
+ // compare field names and values in an HTTP 1.x compliant
fashion
+ if ( ( headerFieldName.equalsIgnoreCase(
unexpectedFieldName ) ) ) {
+ int hSize = headerValues.size();
+ int eSize = unexpectedValues.size();
+ int numberFound = 0;
+ for ( int i = 0; i < eSize; i++ ) {
+ if ( headerValues.contains( unexpectedValues.get( i
) ) ) {
+ numberFound++;
+ headerValues.remove( headerValues.indexOf(
headerFieldName ) );
+ }
+ }
+ if ( numberFound == eSize ) {
+ found = true;
+ }
+ }
+ }
+ if ( !found ) {
+ /*
+ * Expected headers not found in server response.
+ * Break the processing loop.
+ */
+ break;
+ }
+ }
+ }
+
+ if ( found ) {
+ System.out.println( " Unexpected header received from server: " +
unExpHeader );
+ return false;
+ }
}
- // compare the body
- if( goldenFile==null) return responseStatus;
- // Get the expected result from the "golden" file.
- StringBuffer expResult = getExpectedResult();
-
- // Compare the results and set the status
- boolean cmp=true;
-
- if(exactMatch)
- cmp=compare(responseBody, expResult.toString() );
- else
- cmp=compareWeek( responseBody, expResult.toString());
-
- if( cmp != testCondition ) {
- responseStatus = false;
- System.out.println("ERROR (" + cmp + "," + testCondition + ")in : " +
request);
- System.out.println("====================Expecting: ");
- System.out.println(expResult);
- System.out.println("====================Got:");
- System.out.println(responseBody);
- System.out.println("====================");
- if ( resultOut != null )
- {
- expectedString = "<expectedBody>" + expResult +
"</expectedBody>\n";
- actualString = "<actualBody>"+ responseBody +
"</actualBody>\n";
- resultOut.write(expectedString.getBytes() );
- resultOut.write(actualString.getBytes() );
+
- }
- }
-
- return responseStatus;
+ if ( responseMatch != null ) {
+ // check if we got the string we wanted
+ if ( expectResponseBody && responseBody == null ) {
+ System.out.println( " ERROR: got no response, expecting " +
responseMatch );
+ return false;
+ }
+ String responseBodyString = new String( responseBody );
+ if ( responseBodyString.indexOf( responseMatch ) < 0 ) {
+ System.out.println( " ERROR: expecting match on " + responseMatch );
+ System.out.println( "Received: " );
+ System.out.println( responseBodyString );
+ }
+ }
+
+ // compare the body
+ if ( goldenFile == null )
+ return responseStatus;
+
+ // Get the expected result from the "golden" file.
+ byte[] expResult = getExpectedResult();
+
+ // Compare the results and set the status
+ boolean cmp = true;
+
+ if ( exactMatch ) {
+ cmp = compare( responseBody, expResult );
+ } else {
+ cmp = compareWeak( responseBody, expResult );
+ }
+
+ if ( cmp != testCondition ) {
+ responseStatus = false;
+
+ if ( resultOut != null ) {
+ expectedString = "<expectedBody>" + new String( expResult ) +
"</expectedBody>\n";
+ actualString = "<actualBody>" + new String( responseBody ) +
"</actualBody>\n";
+ resultOut.write( expectedString.getBytes() );
+ resultOut.write( actualString.getBytes() );
+ }
+ }
+
+ return responseStatus;
}
+
- /** Invoke a request, set headers, responseLine, body
+ /**
+ * <code>dispatch</code> sends the request and any
+ * configured request headers to the target server.
+ *
+ * @param request a <code>String</code> value
+ * @param requestHeaders a <code>HashMap</code> value
*/
- private void dispatch(String request, Hashtable requestHeaders)
- throws Exception
- {
- // XXX headers are ignored
- Socket s = null;
-
- s = new Socket( host, port);
- InputStream is= s.getInputStream();
-
- // Write the request
- s.setSoLinger( true, 1000);
- OutputStream os=s.getOutputStream();
- OutputStreamWriter out=new OutputStreamWriter(os);
- PrintWriter pw = new PrintWriter(out);
+ private void dispatch( String request, HashMap requestHeaders )
+ throws Exception {
+ // XXX headers are ignored
+ Socket socket = new Socket( host, port );
+
+ InputStream is = new CRBufferedInputStream( socket.getInputStream() );
+
+ // Write the request
+ socket.setSoLinger( true, 1000 );
+
+ PrintWriter pw = new PrintWriter(
+ new BufferedWriter(
+ new OutputStreamWriter( socket.getOutputStream() ) )
);
- try {
- pw.println(request);
-
- // Now sending any specified request headers
- if ( requestHeaders != null )
- {
- Enumeration reqHeaderEnum = requestHeaders.keys();
- while ( reqHeaderEnum.hasMoreElements() )
- {
- String headerKey = (String)reqHeaderEnum.nextElement();
- if ( debug >0 )
- {
- System.out.println( headerKey + "::" +
requestHeaders.get(headerKey) );
- }
- pw.println( headerKey + ":" + requestHeaders.get( headerKey));
- }
- }
- if ( testSession != null )
- {
- cookieController = (CookieController)sessionHash.get( testSession );
- if ( cookieController != null )
- {
-
- String releventCookieString=
cookieController.applyRelevantCookies(requestURL );
- if ( ( releventCookieString != null ) &&
(!releventCookieString.trim().equals("" ) ) )
- {
- String cookieHeader= "Cookie : " +
releventCookieString ;
- if ( debug >0 )
- {
- System.out.println( "Sending Cookie Header:: " +
cookieHeader );
- }
- pw.println( cookieHeader );
+ try {
+ pw.println( request );
+
+ // Now sending any specified request headers
+ if ( !requestHeaders.isEmpty() ) {
+ Iterator iter = requestHeaders.keySet().iterator();
+
+ while ( iter.hasNext() ) {
+ String headerKey = ( String ) iter.next();
+ ArrayList values = (ArrayList) requestHeaders.get( headerKey );
+ String[] value = (String[]) values.toArray( new String[
values.size() ] );
+ for ( int i = 0; i < value.length; i++ ) {
+ StringBuffer sb = new StringBuffer( 25 );
+ sb.append( headerKey );
+ sb.append( ": " );
+ sb.append( value[ i ] );
+ pw.println( sb.toString() );
+ if ( debug > 0 ) {
+ System.out.println( sb.toString() );
}
- }
+ }
+ }
+ }
+
+ if ( testSession != null ) {
+ cookieController = ( CookieController ) sessionHash.get(
testSession );
+
+ if ( cookieController != null ) {
+
+ String releventCookieString =
cookieController.applyRelevantCookies( requestURL );
+
+ if ( ( releventCookieString != null ) && (
!releventCookieString.trim().equals( "" ) ) ) {
+ String cookieHeader = "Cookie : " + releventCookieString ;
+
+ if ( debug > 0 ) {
+ System.out.println( " Sending Cookie Header:: " +
cookieHeader );
+ }
+
+ pw.println( cookieHeader );
+ }
+ }
+
+ }
- }
- /*
-
- if ( ( testSession != null ) && ( sessionHash.get( testSession ) != null )
)
- {
- System.out.println("Sending Session Id : " + (String)sessionHash.get(
testSession ) );
- pw.println("JSESSIONID:" + (String)sessionHash.get( testSession) );
+ /*
+
+ if ( ( testSession != null ) && ( sessionHash.get( testSession ) !=
null ) )
+ {
+ System.out.println("Sending Session Id : " + (String)sessionHash.get(
testSession ) );
+ pw.println("JSESSIONID:" + (String)sessionHash.get( testSession) );
+ }
+
+ */
+
+ if ( content != null ) {
+ pw.println( "Content-Length: " + content.length() );
+ }
+
+ if ( request.indexOf( "HTTP/1." ) > -1 )
+ pw.println( "" );
+
+ if ( content != null ) {
+ pw.print( content );
+ // XXX no /n at the end -see HTTP specs!
+ }
+
+ pw.flush();
+ } catch ( Exception ex1 ) {
+ System.out.println( " Error writing request " + ex1 );
+ if ( debug > 0 ) {
+ System.out.println( "Message: " + ex1.getMessage() );
+ ex1.printStackTrace();
}
+ }
- */
+ try {
+
+ responseLine = read( is );
- if( content != null) {
- pw.println("Content-Length: " + content.length());
+ if ( debug > 0 ) {
+ System.out.println( " RESPONSE STATUS-LINE: " + responseLine );
}
-
- if( request.indexOf( "HTTP/1." ) > -1)
- pw.println("");
-
- if( content != null) {
- pw.print(content);
- // XXX no /n at the end -see HTTP specs!
+
+ headers = parseHeaders( is );
+
+ byte[] result = readBody( is );
+
+ if ( result != null ) {
+ responseBody = result;
+ if ( debug > 0 ) {
+ System.out.println( " RESPONSE BODY:\n" + new String( responseBody
) );
+ }
}
-
- pw.flush();
- } catch (Exception ex1 ) {
- System.out.println("Error writing request " + ex1);
- }
-
- try {
- // http 0.9
- if( request.indexOf( "HTTP/1." ) > -1) {
- responseLine = read( is );
- if( debug>0) System.out.println("RESPONSE: " + responseLine );
- headers=parseHeaders( is );
+ } catch ( SocketException ex ) {
+ System.out.println( " Socket Exception: " + ex );
+ ex.printStackTrace();
+ } finally {
+ if ( debug > 0 ) {
+ System.out.println( " closing socket" );
}
-
- // else do content matching as well
- StringBuffer result = readBody( is );
- if(result!=null)
- responseBody=result.toString();
-
- if(debug>0) System.out.println("BODY: " + responseBody );
- } catch( SocketException ex ) {
- System.out.println("Socket Exception: " + ex);
- ex.printStackTrace();
- s.close();
- return;
+ socket.close();
+ socket = null;
}
- s.close();
}
-
- // Parse a file into a String.
- private StringBuffer getExpectedResult()
- throws IOException
- {
- StringBuffer expResult = new StringBuffer("NONE");
+
+ /**
+ * <code>getExpectedResult</code> returns a byte array
+ * containing the content of the configured goldenfile
+ *
+ * @return goldenfile as a byte[]
+ * @exception IOException if an error occurs
+ */
+ private byte[] getExpectedResult()
+ throws IOException {
+ byte[] expResult = { 'N','O',' ',
+ 'G','O','L','D','E','N','F','I','L','E',' ',
+ 'F','O','U','N','D' };
+
try {
- // InputStream in = this.getClass().getResourceAsStream(goldenFile);
- InputStream in = new FileInputStream( goldenFile );
- return readBody ( in );
- } catch (Exception ex) {
- System.out.println("\tGolden file not found: " + goldenFile);
+ InputStream in = new BufferedInputStream(
+ new FileInputStream( goldenFile ) );
+ return readBody ( in );
+ } catch ( Exception ex ) {
+ System.out.println( "Golden file not found: " + goldenFile );
return expResult;
}
}
-
- // Compare the actual result and the expected result.
- private boolean compare(String str1, String str2) {
- //System.out.println("In compare");
- if ( str1==null || str2==null) return false;
- if ( str1.length() != str2.length() ) {
- System.out.println("Wrong size " + str1.length() +" " + str2.length() );
- return false;
+ /**
+ * <code>compare</code> compares the two byte arrays passed
+ * in to verify that the lengths of the arrays are equal, and
+ * that the content of the two arrays, byte for byte are equal.
+ *
+ * @param fromServer a <code>byte[]</code> value
+ * @param fromGoldenFile a <code>byte[]</code> value
+ * @return <code>boolean</code> true if equal, otherwise false
+ */
+ private boolean compare( byte[] fromServer, byte[] fromGoldenFile ) {
+ if ( fromServer == null || fromGoldenFile == null ) {
+ return false;
}
-
- for(int i=0; i<str1.length() ; i++ ) {
- if (str1.charAt( i ) != str2.charAt( i ) ) {
- System.out.println("Error at " + i + " " + str1.charAt(1) +
- str2.charAt(i));
- return false;
+
+ /*
+ * Check to see that the respose and golden file lengths
+ * are equal. If they are not, dump the hex and don't
+ * bother comparing the bytes. If they are equal,
+ * iterate through the byte arrays and compare each byte.
+ * If the bytes don't match, dump the hex representation
+ * of the server response and the goldenfile and return
+ * false.
+ */
+ if ( fromServer.length != fromGoldenFile.length ) {
+ StringBuffer sb = new StringBuffer( 50 );
+ sb.append( " Response and golden files lengths do not match!\n" );
+ sb.append( " Server response length: " );
+ sb.append( fromServer.length );
+ sb.append( "\n Goldenfile length: " );
+ sb.append( fromGoldenFile.length );
+ System.out.println( sb.toString() );
+ sb = null;
+ // dump the hex representation of the byte arrays
+ dumpHex( fromServer, fromGoldenFile );
+
+ return false;
+ } else {
+
+ int i = 0;
+ int j = 0;
+
+ while ( ( i < fromServer.length ) && ( j < fromGoldenFile.length ) ) {
+ if ( fromServer[ i ] != fromGoldenFile[ j ] ) {
+ System.out.println( " Error at position " + ( i + 1 ) );
+ // dump the hex representation of the byte arrays
+ dumpHex( fromServer, fromGoldenFile );
+
+ return false;
+ }
+
+ i++;
+ j++;
}
}
- return true;
+
+ return true;
}
- // Compare the actual result and the expected result.
- // Original compare - ignores spaces ( because most
- // golden files are wrong !)
- private boolean compareWeek(String str1, String str2) {
- //System.out.println("In compareWeek");
- if ( str1==null || str2==null) return false;
-
- StringTokenizer st1=new StringTokenizer(str1);
- StringTokenizer st2=new StringTokenizer(str2);
+ /**
+ * <code>compareWeak</code> creates new Strings from the passed arrays
+ * and then uses a StringTokenizer to compare non-whitespace tokens.
+ *
+ * @param fromServer a <code>byte[]</code> value
+ * @param fromGoldenFile a <code>byte[]</code> value
+ * @return a <code>boolean</code> value
+ */
+ private boolean compareWeak( byte[] fromServer, byte[] fromGoldenFile ) {
+ if ( fromServer == null || fromGoldenFile == null ) {
+ return false;
+ }
+
+ StringTokenizer st1 = new StringTokenizer( new String( fromServer ) );
- while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
+ StringTokenizer st2 = new StringTokenizer( new String( fromGoldenFile ) );
+
+ while ( st1.hasMoreTokens() && st2.hasMoreTokens() ) {
String tok1 = st1.nextToken();
String tok2 = st2.nextToken();
- if (!tok1.equals(tok2)) {
- System.out.println("\tFAIL*** : Rtok1 = " + tok1
- + ", Etok2 = " + tok2);
+
+ if ( !tok1.equals( tok2 ) ) {
+ System.out.println( "\t FAIL*** : Rtok1 = " + tok1
+ + ", Etok2 = " + tok2 );
return false;
}
}
- if (st1.hasMoreTokens() || st2.hasMoreTokens()) {
+ if ( st1.hasMoreTokens() || st2.hasMoreTokens() ) {
return false;
} else {
return true;
}
}
-
- // XXX return byte [], fix the reading !!!!!
- StringBuffer readBody( InputStream input )
- {
- StringBuffer sb = new StringBuffer();
- while (true) {
- try {
+ /**
+ * <code>readBody</code> reads the body of the response
+ * from the InputStream.
+ *
+ * @param input an <code>InputStream</code>
+ * @return a <code>byte[]</code> representation of the response
+ */
+ private byte[] readBody( InputStream input ) {
+ StringBuffer sb = new StringBuffer( 255 );
+ while ( true ) {
+ try {
int ch = input.read();
- if (ch < 0) {
- if (sb.length() == 0) {
- return (null);
- } else {
- break;
+
+ if ( ch < 0 ) {
+ if ( sb.length() == 0 ) {
+ return ( null );
+ } else {
+ break;
}
}
- sb.append((char) ch);
- } catch(IOException ex ) {
- return sb;
- }
- }
- return sb;
+ sb.append( ( char ) ch );
+
+ } catch ( IOException ex ) {
+ return null;
+ }
+ }
+ return sb.toString().getBytes();
}
- //Ramesh
- private void getHeaderDetails( String line, Hashtable headerHash )
- {
- StringTokenizer stk = new StringTokenizer( line, "##" );
- while ( stk.hasMoreElements( ) )
- {
- String presentHeader = stk.nextToken();
- parseHeader( presentHeader, headerHash );
- }
- }
+ /**
+ * <code>getHeaderDetails</code> Wrapper method for parseHeader.
+ * Allows easy addition of headers to the specified
+ * HashMap
+ *
+ * @param line a <code>String</code> value
+ * @param headerMap a <code>HashMap</code> value
+ * @param isRequest a <code>boolean</code> indicating if the passed Header
+ * HashMap is for request headers
+ */
+ private void getHeaderDetails( String line, HashMap headerHash, boolean
isRequest ) {
+ StringTokenizer stk = new StringTokenizer( line, "##" );
+ while ( stk.hasMoreElements( ) ) {
+ String presentHeader = stk.nextToken();
+ parseHeader( presentHeader, headerHash, isRequest );
+ }
+ }
+
// ==================== Code from JSERV !!! ====================
/**
* Parse the incoming HTTP request headers, and set the corresponding
@@ -610,106 +1015,368 @@
*
* @exception IOException if an input/output error occurs
*/
- private Hashtable parseHeaders(InputStream is) throws IOException {
- Hashtable headers=new Hashtable();
- cookieVector = new Vector();
- while (true) {
- // Read the next header line
- String line = read(is);
- if ((line == null) || (line.length() < 1)) {
- break;
+ private HashMap parseHeaders( InputStream is ) throws IOException {
+ HashMap headers = new HashMap();
+ cookieVector = new Vector();
+
+ while ( true ) {
+ // Read the next header line
+ String line = read( is );
+
+ if ( ( line == null ) || ( line.length() < 1 ) ) {
+ break;
+ }
+
+ parseHeader( line, headers, false );
+
+ if ( debug > 0 ) {
+ System.out.println( " RESPONSE HEADER: " + line );
}
- parseHeader( line, headers);
- if( debug>0) System.out.println("HEADER: " +line +"X" );
+ }
- }
- if ( testSession != null )
- {
- cookieController = (CookieController)sessionHash.get(testSession);
- if ( cookieController != null )
- {
- cookieController.recordAnyCookies(cookieVector,requestURL);
- }
- }
+ if ( testSession != null ) {
+ cookieController = ( CookieController ) sessionHash.get( testSession );
+
+ if ( cookieController != null ) {
+ cookieController.recordAnyCookies( cookieVector, requestURL );
+ }
+ }
- return headers;
+ return headers;
}
- private void parseHeader(String line, Hashtable headers) {
- // Parse the header name and value
- int colon = line.indexOf(":");
- if (colon < 0) {
- System.out.println("ERROR: Wrong Header Line: " + line );
- return;
- }
- String name = line.substring(0, colon).trim();
- String value = line.substring(colon + 1).trim();
- if ( (cookieVector != null ) && ( name.equalsIgnoreCase("Set-Cookie") ) )
- {
- cookieVector.addElement(value);
- /*
- if ( ( value.indexOf("JSESSIONID") > -1 ) ||
(value.indexOf("jsessionid") > -1 ) )
- {
- String sessionId= value.substring( value.indexOf("=")+1);
- if ( testSession != null )
- {
- sessionHash.put( testSession, sessionId );
- }
- System.out.println("Got Session-ID : " + sessionId );
- }
- */
- }
+ /**
+ * <code>parseHeader</code> parses input headers in format of "key:value"
+ * The parsed header field-name will be used as a key in the passed
+ * HashMap object, and the values found will be stored in an ArrayList
+ * associated with the field-name key.
+ *
+ * @param line String representation of an HTTP header line.
+ * @param headers a<code>HashMap</code> to store key/value header objects.
+ * @param isRequest set to true if the headers being processed are
+ * requestHeaders.
+ */
+ private void parseHeader( String line, HashMap headerMap, boolean isRequest ) {
+ // Parse the header name and value
+ int colon = line.indexOf( ":" );
+
+ if ( colon < 0 ) {
+ System.out.println( " ERROR: Header is in incorrect format: " + line );
+ return ;
+ }
+
+ String name = line.substring( 0, colon ).trim();
+ String value = line.substring( colon + 1 ).trim();
+
+ if ( ( cookieVector != null ) && ( name.equalsIgnoreCase( "Set-Cookie" ) )
) {
+ cookieVector.addElement( value );
+ /*
+ if ( ( value.indexOf("JSESSIONID") > -1 ) ||
(value.indexOf("jsessionid") > -1 ) )
+ {
+ String sessionId= value.substring( value.indexOf("=")+1);
+ if ( testSession != null )
+ {
+ sessionHash.put( testSession, sessionId );
+ }
+ System.out.println("Got Session-ID : " + sessionId );
+ }
+ */
+ }
- // System.out.println("HEADER: " +name + " " + value);
- headers.put(name, value);
+ // System.out.println("HEADER: " +name + " " + value);
+
+ ArrayList values = (ArrayList) headerMap.get( name );
+ if ( values == null ) {
+ values = new ArrayList();
+ }
+ // HACK
+ if ( value.indexOf( ',' ) > -1 && !isRequest && !name.equalsIgnoreCase( "Date"
) ) {
+ StringTokenizer st = new StringTokenizer( value, "," );
+ while ( st.hasMoreElements() ) {
+ values.add( st.nextToken() );
+ }
+ } else {
+ values.add( value );
+ }
+
+ headerMap.put( name, values );
}
/**
* Read a line from the specified servlet input stream, and strip off
* the trailing carriage return and newline (if any). Return the remaining
- * characters that were read as a string.
+ * characters that were read as a string.7
*
* @returns The line that was read, or <code>null</code> if end of file
* was encountered
*
* @exception IOException if an input/output error occurred
*/
- private String read(InputStream input) throws IOException {
- // Read the next line from the input stream
- StringBuffer sb = new StringBuffer();
- while (true) {
- try {
- int ch = input.read();
- // System.out.println("XXX " + (char)ch );
- if (ch < 0) {
- if (sb.length() == 0) {
- if(debug>0) System.out.println("Error reading line " + ch + "
" + sb.toString() );
- return "";
- } else {
- break;
- }
- } else if (ch == '\n') {
- break;
+ private String read( InputStream input ) throws IOException {
+ // Read the next line from the input stream
+ StringBuffer sb = new StringBuffer();
+
+ while ( true ) {
+ try {
+ int ch = input.read();
+ // System.out.println("XXX " + (char)ch );
+ if ( ch < 0 ) {
+ if ( sb.length() == 0 ) {
+ if ( debug > 0 )
+ System.out.println( " Error reading line " + ch + " " +
sb.toString() );
+ return "";
+ } else {
+ break;
+ }
+ } else if ( ch == LINE_FEED ) {
+ break;
+ }
+
+ sb.append( ( char ) ch );
+ } catch ( IOException ex ) {
+ System.out.println( " Error reading : " + ex );
+ debug = 1;
+
+ if ( debug > 0 ) {
+ System.out.println( "Partial read: " + sb.toString() );
+ ex.printStackTrace();
}
- sb.append((char) ch);
- } catch( IOException ex ) {
- System.out.println("Error reading : " + ex );
- debug=1;
- if(debug>0) System.out.println("Partial read: " + sb.toString());
- ex.printStackTrace();
- //break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * <code>dumpHex</code> helper method to dump formatted
+ * hex output of the server response and the goldenfile.
+ *
+ * @param serverResponse a <code>byte[]</code> value
+ * @param goldenFile a <code>byte[]</code> value
+ */
+ private void dumpHex( byte[] serverResponse, byte[] goldenFile ) {
+ StringBuffer outBuf = new StringBuffer( ( serverResponse.length +
goldenFile.length ) * 2 );
+
+ String fromServerString = getHexValue( serverResponse, 0,
serverResponse.length );
+ String fromGoldenFileString = getHexValue( goldenFile, 0, goldenFile.length
);
+
+ outBuf.append( " Hex dump of server response and goldenfile below.\n\n###
RESPONSE FROM SERVER ###\n" );
+ outBuf.append( "----------------------------\n" );
+ outBuf.append( fromServerString );
+ outBuf.append( "\n\n### GOLDEN FILE ###\n" );
+ outBuf.append( "-------------------\n" );
+ outBuf.append( fromGoldenFileString );
+ outBuf.append( "\n\n### END OF DUMP ###\n" );
+
+ System.out.println( outBuf.toString() );
+
+ }
+
+ /**
+ * <code>getHexValue</code> displays a formatted hex
+ * representation of the passed byte array. It also
+ * allows for only a specified offset and length of
+ * a particular array to be returned.
+ *
+ * @param bytes <code>byte[]</code> array to process.
+ * @param pos <code>int</code> specifies offset to begin processing.
+ * @param len <code>int</code> specifies the number of bytes to process.
+ * @return <code>String</code> formatted hex representation of processed
+ * array.
+ */
+ private String getHexValue( byte[] bytes, int pos, int len ) {
+ StringBuffer outBuf = new StringBuffer( bytes.length * 2 );
+ int bytesPerLine = 36;
+ int cnt = 1;
+ int groups = 4;
+ int curPos = pos;
+ int linePos = 1;
+ boolean displayOffset = true;
+
+ while ( len-- > 0 ) {
+ if ( displayOffset ) {
+
+ outBuf.append( "\n" + paddedHexString( pos, SHORTPADSIZE,
+ true ) + ": " );
+ displayOffset = false;
+ }
+
+ outBuf.append(
+ paddedHexString( ( int ) bytes[ pos ], BYTEPADSIZE, false ) );
+ linePos += 2; // Byte is padded to 2 characters
+
+ if ( ( cnt % 4 ) == 0 ) {
+ outBuf.append( " " );
+ linePos++;
+ }
+
+ // Now display the characters that are printable
+ if ( ( cnt % ( groups * 4 ) ) == 0 ) {
+ outBuf.append( " " );
+
+ while ( curPos <= pos ) {
+ if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+ outBuf.append( ( char ) bytes[ curPos ] );
+ } else {
+ outBuf.append( "." );
+ }
+
+ curPos++;
+ }
+
+ curPos = pos + 1;
+ linePos = 1;
+ displayOffset = true;
+ }
+
+ cnt++;
+ pos++;
+ }
+
+ // pad out the line with spaces
+ while ( linePos++ <= bytesPerLine ) {
+ outBuf.append( " " );
+ }
+
+ outBuf.append( " " );
+ // Now display the printable characters for the trailing bytes
+ while ( curPos < pos ) {
+ if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+ outBuf.append( ( char ) bytes[ curPos ] );
+ } else {
+ outBuf.append( "." );
+ }
+
+ curPos++;
+ }
+
+ return outBuf.toString();
+ }
+
+ /**
+ * <code>paddedHexString</code> pads the passed value
+ * based on the specified wordsize and the value of the
+ * prefixFlag.
+ *
+ * @param val an <code>int</code> value
+ * @param wordsize an <code>int</code> value
+ * @param prefixFlag a <code>boolean</code> value
+ * @return a <code>String</code> value
+ */
+ private String paddedHexString( int val, int wordsize,
+ boolean prefixFlag ) {
+
+ String prefix = prefixFlag ? "0x" : "" ;
+ String hexVal = Integer.toHexString( val );
+
+ if ( hexVal.length() > wordsize )
+ hexVal = hexVal.substring( hexVal.length() - wordsize );
+
+ return ( prefix + ( wordsize > hexVal.length() ?
+ ZEROS.substring( 0, wordsize - hexVal.length() ) : "" )
+ hexVal );
+ }
+
+ /**
+ * <code>cloneHeaders</code> returns a "cloned"
+ * HashMap of the map passed in.
+ *
+ * @param map a <code>HashMap</code> value
+ * @return a <code>HashMap</code> value
+ */
+ private HashMap cloneHeaders( HashMap map ) {
+ HashMap dupMap = new HashMap();
+ Iterator iter = map.keySet().iterator();
+
+ while ( iter.hasNext() ) {
+ String key = new String( (String) iter.next() );
+ ArrayList origValues = (ArrayList) map.get( key );
+ ArrayList dupValues = new ArrayList();
+
+ String[] dupVal = (String[]) origValues.toArray( new String[
origValues.size() ] );
+ for ( int i = 0; i < dupVal.length; i++ ) {
+ dupValues.add( new String( dupVal[ i ] ) );
}
+
+ dupMap.put( key, dupValues );
}
+ return dupMap;
+ }
- // Strip any trailing carriage return
- int n = sb.length();
- if ((n > 0) && (sb.charAt(n - 1) == '\r')) {
- sb.setLength(n - 1);
- }
+ /**
+ * <code>CRBufferedInputStream</code> is a modified version of
+ * the java.io.BufferedInputStream class. The fill code is
+ * the same, but the read is modified in that if a carriage return
+ * is found in the response stream from the target server,
+ * it will skip that byte and return the next in the stream.
+ */
+ private class CRBufferedInputStream extends BufferedInputStream {
+
+ private static final int DEFAULT_BUFFER = 2048;
+
+ /**
+ * Creates a new <code>CRBufferedInputStream</code> instance.
+ *
+ * @param in an <code>InputStream</code> value
+ */
+ public CRBufferedInputStream( InputStream in ) {
+ super( in, DEFAULT_BUFFER );
+ }
- // Convert the line to a String and return it
- return (sb.toString());
- }
+ /**
+ * <code>read</code> reads a single byte value per call.
+ * If, the byte read, is a carriage return, the next byte
+ * in the stream in returned instead.
+ *
+ * @return an <code>int</code> value
+ * @exception IOException if an error occurs
+ */
+ public int read() throws IOException {
+ if ( in == null ) {
+ throw new IOException ( "Stream closed" );
+ }
+ if ( pos >= count ) {
+ fill();
+ if ( pos >= count ) {
+ return -1;
+ }
+ }
+ int val = buf[pos++] & 0xff;
+ if ( val == CARRIAGE_RETURN ) {
+ return buf[pos++] & 0xff;
+ }
+ return val;
+ }
+ /**
+ * <code>fill</code> is used to fill the internal
+ * buffer used by this BufferedInputStream class.
+ *
+ * @exception IOException if an error occurs
+ */
+ private void fill() throws IOException {
+ if (markpos < 0)
+ pos = 0; /* no mark: throw away the buffer */
+ else if (pos >= buf.length) /* no room left in buffer */
+ if (markpos > 0) { /* can throw away early part of the buffer */
+ int sz = pos - markpos;
+ System.arraycopy(buf, markpos, buf, 0, sz);
+ pos = sz;
+ markpos = 0;
+ } else if (buf.length >= marklimit) {
+ markpos = -1; /* buffer got too big, invalidate mark */
+ pos = 0; /* drop buffer contents */
+ } else { /* grow buffer */
+ int nsz = pos * 2;
+ if (nsz > marklimit)
+ nsz = marklimit;
+ byte nbuf[] = new byte[nsz];
+ System.arraycopy(buf, 0, nbuf, 0, pos);
+ buf = nbuf;
+ }
+ count = pos;
+ int n = in.read(buf, pos, buf.length - pos);
+ if (n > 0)
+ count = n + pos;
+ }
+ }
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>