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