You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by pr...@apache.org on 2005/08/04 18:43:04 UTC
cvs commit: ws-axis/c/tests/utils/monitor/org/apache/test MockServerThread.java
prestonf 2005/08/04 09:43:04
Modified: c/tests/utils/monitor/org/apache/test MockServerThread.java
Log:
Update to the mock server to perform more checks on chunked expected server response files (see AXISCPP-777).
CVS: ----------------------------------------------------------------------
CVS: PR:
CVS: If this change addresses a PR in the problem report tracking
CVS: database, then enter the PR number(s) here.
CVS: Obtained from:
CVS: If this change has been taken from another system, such as NCSA,
CVS: then name the system in this line, otherwise delete it.
CVS: Submitted by:
CVS: If this code has been contributed to Apache by someone else; i.e.,
CVS: they sent us a patch or a new module, then include their name/email
CVS: address here. If this is your work then delete this line.
CVS: Reviewed by:
CVS: If we are doing pre-commit code reviews and someone else has
CVS: reviewed your changes, include their name(s) here.
CVS: If you have not had it reviewed then delete this line.
Revision Changes Path
1.9 +259 -25 ws-axis/c/tests/utils/monitor/org/apache/test/MockServerThread.java
Index: MockServerThread.java
===================================================================
RCS file: /home/cvs/ws-axis/c/tests/utils/monitor/org/apache/test/MockServerThread.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- MockServerThread.java 15 Jul 2005 14:37:34 -0000 1.8
+++ MockServerThread.java 4 Aug 2005 16:43:04 -0000 1.9
@@ -202,7 +202,8 @@
* This method opens the input file and streams it out to the given
* outputstream
*
- * @param outputStream the stream to output the file to
+ * @param outputStream
+ * the stream to output the file to
*/
private void sendResponseToClient( ) throws FileNotFoundException,
IOException
@@ -317,37 +318,231 @@
* Because the repositories we use accomodate the dos2unix conversion we
* have a problem. On unix the response files have the crlf converted to
* just cr. this method returns the crlf !
+ *
+ * The HTTP header and chunk sizes need to be delimited with CR LF's.
+ * The 'server response' expected files used to mimic the response of a
+ * server when performing unit tests also need to have the correct
+ * delimiting character combinations in the fake response messages
+ * (generated by the monitor). Problems arise because the expected
+ * response files have been captured on different operating systems (Unix
+ * and Windows) and then edited using a variety of editors that interpret
+ * the CR character differently. Thus the file may be stored with or
+ * without the CR characters. Also, the souce control application can be
+ * set to convert a single LF character into a CR LF combination. The
+ * outcome of all this character manipulation is that LF's may or may not
+ * have the necessary associated CR for it to be recognised by the HTTP
+ * transport. It is not just sufficient to look for every LF and to prefix
+ * it with a CR because the context of that LF must be taken into
+ * consideration. For example, if a LF is found in the HTTP header then it
+ * definitely needs a CR prefix. This also applies when the message is
+ * chunked and the chunk size must also be delimited by the CR LF sequence.
+ * But, when a LF appears inside a chunk of data it should remain unchanged
+ * unless the chunk size is different from the actual data size between
+ * chunks, in which case the CR has probably been stripped out and needs to
+ * be replaced. Below is a low level design of what should work in all
+ * instances...
+ *
+ * Is the message chunked?
+ * NO: Convert all single LF sequences to CR+LF.
+ * NB: Because the value associated with the 'Content-Length' label is
+ * not used correctly, if the size of the file grows larger than the
+ * Content-Length value, no action is taken.
+ * Exit.
+ * YES: Convert all single LF sequences to CR+LF in the HTTP header.
+ * Set Index = location of the first 'chunk' value.
+ * Read the chunk size.
+ * While the chunk size > 0
+ * Convert any single LF sequences to CR+LF that surround the chunk
+ * value.
+ * Is the character at offset Index + chunk size equal to CR or LF?
+ * NO: Count up the number of unaccompanied LF's in the chunk.
+ * Is the difference between the expected and actual chunk data
+ * length double the number of unaccompanied LF's?
+ * NO: Error - Irreconcilable differences between expected and
+ * actual chunk data sizes.
+ * Exit.
+ * YES: Convert all single LF sequences to CR+LF in the chunk
+ * data.
+ * Continue.
+ * Index = Index + chunk size.
+ * Read the new chunk size.
+ * End of while.
+ * Exit.
*/
private static void setCRLF( )
{
- if (System.getProperty("os.name").toLowerCase( ).startsWith("windows"))
- {
- System.out
- .println("Windows operating system - not converting crlf's");
- }
- else
+ for( int i = 0; i < responses.length; i++)
{
- for(int i=0; i<responses.length; i++)
+ if( responses[i] != null)
{
- if (responses[i]!=null)
- {
- String request=new String((char[]) responses[i]);
- // check the last two digits for CRLF - if they are LFLF
- // then this is wrong
- // e.g. 0a 0a converts to 0d0a 0d0a
- // I'm doing it using a matcher because this could get
- // complicated !
- Pattern pattern=Pattern.compile("\n");
- Matcher matcher=pattern.matcher(request);
- StringBuffer stringBuffer=new StringBuffer( );
- while (matcher.find( ))
+ String sResponse = new String((char[]) responses[i]);
+ String sModifiedResponse = "";
+ String sContentLength = "Content-Length:";
+ boolean bChunked = sResponse.indexOf( sContentLength) == -1;
+
+ if( bChunked)
+ {
+ String sLF = "\n";
+ String sCR = "\r";
+ String sCRLF = sCR + sLF;
+
+ System.out.println("Information - Response file is chunked.");
+
+ // Find HTTP Header block.
+ String sLine;
+ int iIndex = 0;
+ int iEoL = sResponse.indexOf( sLF, iIndex) + 1;
+
+ do
{
- char[] tmpStr=matcher.group( ).toCharArray( );
- matcher.appendReplacement(stringBuffer, "\r\n");
- }
- matcher.appendTail(stringBuffer);
+ sLine = getResponseLine(sResponse, sCRLF, iIndex, iEoL);
+
+ sModifiedResponse += sLine;
+
+ // Get next line.
+ iIndex = iEoL;
+
+ iEoL = sResponse.indexOf( sLF, iIndex) + 1;
+ } while( iEoL > 0 && !sLine.equals( sCRLF));
+
+ // Find first chunk_size.
+ sLine = getResponseLine(sResponse, sCRLF, iIndex, iEoL);
+
+ sModifiedResponse += sLine;
+
+ iIndex = iEoL;
+
+ // Evaluate chunk_size value.
+ int iChunkSize = Integer.parseInt( sLine.trim(), 16);
+
+ do
+ {
+ int iChunkDataBlockBegin = iIndex;
+ int iChunkDataBlockEnd = iIndex + iChunkSize;
+ int iResponseSize = sResponse.length();
+
+ // If the chunk data block end is greater than the size
+ // of the file, then the size of the chunk is incorrect.
+ // If '###' was used, then the size of the chunk is
+ // incorrectly calculated to include the chunk size in
+ // the chunk length.
+ if( iChunkDataBlockEnd > iResponseSize)
+ {
+ System.out.println("Warning - The chunk size is greater than the file size by " + (iChunkDataBlockEnd - iResponseSize) + " bytes.");
+
+// iChunkSize -= (sLine.length() + iChunkDataBlockEnd - iResponseSize - 1);
+// iChunkDataBlockEnd = iIndex + iChunkSize;
+
+ iChunkDataBlockEnd = sResponse.lastIndexOf( "0") - 1;
+ iChunkSize = iChunkDataBlockEnd - iIndex;
+ }
+
+ String sChunkDataBlock = sResponse.substring( iChunkDataBlockBegin, iChunkDataBlockEnd);
+
+ iIndex += iChunkSize;
+
+ // Check that offset from current position + chunk_size is
+ // another chunk_size.
+ iEoL = sResponse.indexOf( sLF, iIndex) + 1;
+
+ if( iEoL == 0)
+ {
+ // There are no more LF's in the file. This is
+ // probably because there is no LF at the end of
+ // the file. Assume so and make sLine = "0".
+ System.out.println("Warning - The response file chunk sizes appear to be wrong.");
+
+ sLine = "";
+ }
+ else
+ {
+ sLine = getResponseLine(sResponse, sCRLF, iIndex, iEoL);
+
+ sChunkDataBlock += sLine;
+
+ // Get next line.
+ iIndex = iEoL;
+
+ iEoL = sResponse.indexOf( sLF, iIndex) + 1;
+
+ if( iEoL == 0)
+ {
+ // There are no more LF's in the file. This is
+ // probably because there is no LF at the end of
+ // the file. Assume so and make sLine = "0".
+ System.out.println("Warning - The response file does not end with a LF.");
+
+ sLine = "0" + sLF;
+ }
+ else
+ {
+ sLine = getResponseLine(sResponse, sCRLF, iIndex, iEoL);
+ }
+
+ if( !isStringAHexNumber( sLine.trim()))
+ {
+ // Next chunk_size not found at position. Count the
+ // number of LF's in the block. Check if when this
+ // number * 2 is added to the offset that the pointer
+ // now points to the next chunk_size.
+ System.out.println( "Error - The next chunk_size was not found in the correct position. Check that the contents of the chunked data between " + iChunkDataBlockBegin + " and " + iChunkDataBlockEnd + " is correct.");
+ }
+ }
+
+ sModifiedResponse += sChunkDataBlock;
+ sModifiedResponse += sLine;
+
+ iIndex = iEoL;
+
+ // Evaluate chunk_size value.
+ if( sLine.trim().length() > 0 && isStringAHexNumber( sLine.trim()))
+ {
+ iChunkSize = Integer.parseInt( sLine.trim(), 16);
+ }
+ else
+ {
+ System.out.println("Warning - The response file does not appear to end with a 0 and LF characters.");
+
+ iChunkSize = 0;
+ }
+ } while( iChunkSize > 0);
+
// Now put it back into the responses
- responses[i]=stringBuffer.toString( ).toCharArray( );
+ responses[i] = sModifiedResponse.toCharArray();
+ }
+ else
+ {
+ if (System.getProperty("os.name").toLowerCase( ).startsWith("windows"))
+ {
+ System.out
+ .println("Windows operating system - not converting crlf's");
+ }
+ else
+ {
+ String request=new String((char[]) responses[i]);
+
+ // check the last two digits for CRLF - if they
+ // are LFLF
+ // then this is wrong
+ // e.g. 0a 0a converts to 0d0a 0d0a
+ // I'm doing it using a matcher because this
+ // could get
+ // complicated !
+ Pattern pattern=Pattern.compile("\n");
+ Matcher matcher=pattern.matcher(request);
+ StringBuffer stringBuffer=new StringBuffer( );
+
+ while (matcher.find( ))
+ {
+ char[] tmpStr=matcher.group( ).toCharArray( );
+ matcher.appendReplacement(stringBuffer, "\r\n");
+ }
+
+ matcher.appendTail(stringBuffer);
+
+ // Now put it back into the responses
+ responses[i]=stringBuffer.toString( ).toCharArray( );
+ }
}
}
}
@@ -373,4 +568,43 @@
}
}
}
+
+ /**
+ * @param sResponse
+ * @param sCRLF
+ * @param iIndex
+ * @param iEOL
+ */
+ private static String getResponseLine(String sResponse, String sCRLF, int iIndex, int iEOL)
+ {
+ String sLine = sResponse.substring( iIndex, iEOL);
+
+ if( (!sLine.endsWith( sCRLF)) && (iEOL > iIndex))
+ {
+ sLine = sResponse.substring( iIndex, iEOL - 1) + sCRLF;
+ }
+
+ return sLine;
+ }
+
+ private static boolean isStringAHexNumber( String sValue)
+ {
+ boolean bOutcome = true;
+ String sValidChars = "0123456789ABCDEFabcdef";
+ int iIndex = 0;
+
+ while( bOutcome && iIndex < sValue.length())
+ {
+ if( sValidChars.indexOf( sValue.substring( iIndex, iIndex + 1)) == -1)
+ {
+ bOutcome = false;
+ }
+ else
+ {
+ iIndex++;
+ }
+ }
+
+ return bOutcome;
+ }
}
\ No newline at end of file