You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2008/06/14 17:44:35 UTC

svn commit: r667821 [1/2] - /tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/

Author: costin
Date: Sat Jun 14 08:44:34 2008
New Revision: 667821

URL: http://svn.apache.org/viewvc?rev=667821&view=rev
Log:
Helper to start all test servers and init testing. 
A small refactoring of the ancient watchdog, for lazy people - it runs now as JUnit test suite, pretty easy to integrate 
in an eclipse workflow. 


Added:
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/SimpleHttpClient.java   (with props)
    tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/WatchdogClient.java   (with props)

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Represents a collection of Cookie instances. 
+ * <p>
+ * Fires events when the cookies have been changed internally. Deals
+ * with management of cookies in terms of saving and loading them,
+ * and disabling them.
+ *
+ * @author	Ramesh.Mandava 
+ */
+public class CookieController {
+
+//    private VetoableChangeSupport vceListeners;
+
+    private static Hashtable cookieJar = new Hashtable();
+
+    /* public no arg constructor for bean */
+    public CookieController() {
+    }
+
+/////////////////////////////////////////////////////////////
+ /**
+     * Records any cookies which have been sent as part of an HTTP response.
+     * The connection parameter must be already have been opened, so that
+     * the response headers are available.  It's ok to pass a non-HTTP
+     * URL connection, or one which does not have any set-cookie headers.
+     */
+    public void recordAnyCookies(Vector rcvVectorOfCookies , URL url ) {
+
+	if ((rcvVectorOfCookies == null) || ( rcvVectorOfCookies.size()== 0) ) {
+	    // no headers here
+	    return;
+	}	
+	try {
+	/*
+        Properties properties = new Properties(); 
+	FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+	properties.load(fin);
+      
+	String cookiepolicy = properties.getProperty("cookie.acceptpolicy");
+	if (cookiepolicy == null || cookiepolicy.equals("none")) {
+	    return;
+	}
+	*/
+
+
+
+
+	for (int hi = 0; hi<rcvVectorOfCookies.size(); hi++) {
+
+		String cookieValue = (String)rcvVectorOfCookies.elementAt(hi) ;
+		recordCookie(url, cookieValue); // What to do here
+	    }
+
+	}
+	catch( Exception e )
+	{
+		System.out.println("exception : " + e );
+	}
+    }
+
+
+    /**
+     * Create a cookie from the cookie, and use the HttpURLConnection to
+     * fill in unspecified values in the cookie with defaults.
+     */
+    public void recordCookie(URL url,
+				     String cookieValue) {
+	HttpCookie cookie = new HttpCookie(url, cookieValue);
+	
+	// First, check to make sure the cookie's domain matches the
+	// server's, and has the required number of '.'s
+	String twodot[]=
+	    {"com", "edu", "net", "org", "gov", "mil", "int"};
+	String domain = cookie.getDomain();
+	if( domain == null )
+	    return;
+	int index = domain.indexOf(':');
+	if (index != -1) {
+	    int portCookie;
+	    try {
+		portCookie = (Integer.valueOf(domain.substring(index+1,domain.length()))).intValue();
+	    } catch (Exception e) {
+		return;
+	    }
+	    portCookie = ( portCookie == -1 ) ? 80 : portCookie;
+	    domain=domain.substring(0,index);
+	}
+	domain.toLowerCase();
+	
+	String host = url.getHost();
+	host.toLowerCase();
+
+	boolean domainOK = host.equals(domain);
+	if( !domainOK && host.endsWith( domain ) ) {
+	    int dotsNeeded = 2;
+	    for( int i = 0; i < twodot.length; i++ ) {
+		if( domain.endsWith( twodot[i] ) ) {
+		    dotsNeeded = 1;
+		}
+	    }
+
+	    int lastChar = domain.length();
+	    for( ; lastChar > 0 && dotsNeeded > 0; dotsNeeded-- ) {
+		lastChar = domain.lastIndexOf( '.', lastChar-1 );
+	    }
+
+	    if( lastChar > 0 )
+		domainOK = true;
+	}
+
+	if( domainOK ) {
+	    recordCookie(cookie);
+
+	}
+    }
+
+
+    /**
+     * Record the cookie in the in-memory container of cookies.  If there
+     * is already a cookie which is in the exact same domain with the
+     * exact same
+     */
+    public void recordCookie(HttpCookie cookie) {
+	if (!checkIfCookieOK(cookie)) {
+	    return;
+	}
+	synchronized (cookieJar) {
+	    
+	    String domain = cookie.getDomain().toLowerCase();
+
+	    Vector cookieList = (Vector)cookieJar.get(domain);
+	    if (cookieList == null) {
+		cookieList = new Vector();
+	    }
+
+	    addOrReplaceCookie(cookieList, cookie);
+	    cookieJar.put(domain, cookieList);
+	    
+	}
+
+    }
+
+    public boolean checkIfCookieOK(HttpCookie cookie) {
+	return true;
+    }
+
+    /**
+     * Scans the vector of cookies looking for an exact match with the
+     * given cookie.  Replaces it if there is one, otherwise adds
+     * one at the end.  The vector is presumed to have cookies which all
+     * have the same domain, so the domain of the cookie is not checked.
+     * <p>
+     * <p>
+     * If this is called, it is assumed that the cookie jar is exclusively
+     * held by the current thread.
+     *
+     */
+    private void addOrReplaceCookie(Vector cookies,
+				       HttpCookie cookie) {
+	int numCookies = cookies.size();
+
+	String path = cookie.getPath();
+	String name = cookie.getName();
+	HttpCookie replaced = null;
+	int replacedIndex = -1;
+
+	for (int i = 0; i < numCookies; i++) {
+	    HttpCookie existingCookie = (HttpCookie)cookies.elementAt(i);
+	
+	    String existingPath = existingCookie.getPath();
+	    if (path.equals(existingPath)) {
+		String existingName = existingCookie.getName();
+		if (name.equals(existingName)) {
+		    // need to replace this one!
+		    replaced = existingCookie;
+		    replacedIndex = i;
+		    break;
+		}
+	    }
+	}
+	
+	
+	// Do the replace - if cookie has already expired, remove 
+	// the replaced cookie. 
+	if (replaced != null) {
+	    if (cookie.isSaveableInMemory()) {
+		cookies.setElementAt(cookie, replacedIndex);
+		//System.out.println("REPLACED existing cookie with " + cookie);
+	    } else {
+		cookies.removeElementAt(replacedIndex);
+		//System.out.println("Removed cookie b/c or expr " + cookie);
+	    }
+
+	} else { // only save the cookie in memory if it is non persistent
+          	 // or not expired.
+	    if (cookie.isSaveableInMemory()) {
+		cookies.addElement(cookie);
+		//System.out.println("RECORDED new cookie " + cookie);
+	    } 
+
+	}
+
+    }
+
+    public String applyRelevantCookies(URL url ) {
+
+       try {	
+		/*
+		Properties properties = new Properties(); 
+		FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+		properties.load(fin);
+		// check current accept policy instead enableCookies
+		String cookiepolicy = properties.getProperty("cookie.acceptpolicy");
+		if (cookiepolicy == null || cookiepolicy.equals("none")) {
+		    return null;
+		}
+
+		*/
+
+		return applyCookiesForHost(url);
+
+	}
+	catch ( Exception e )
+	{
+		System.out.println("Exception : " +e );
+		return null;
+	}
+      
+
+
+
+    }
+
+    
+   /**
+     * Host may be a FQDN, or a partial domain name starting with a dot.
+     * Adds any cookies which match the host and path to the
+     * cookie set on the URL connection.
+     */
+    private String applyCookiesForHost(URL url ){
+	String cookieString = null;
+	Vector cookieVector = getAllRelevantCookies(url);
+	
+	if (cookieVector != null) {
+
+	    for (Enumeration e = cookieVector.elements(); e.hasMoreElements();) {
+		HttpCookie cookie = (HttpCookie)e.nextElement();
+		if( cookieString == null ) {
+		    cookieString = cookie.getNameValue();
+		} else {
+		    cookieString = cookieString + "; " + cookie.getNameValue();
+		}
+	    }
+	    
+	 /*
+
+	    if( cookieString != null ) {
+		httpConn.setRequestProperty("Cookie", cookieString);
+	 
+//		System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host);
+	     }
+
+	  */
+
+
+	}
+//		System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host);
+	return cookieString;
+	
+    }
+
+    private Vector getAllRelevantCookies(URL url) {
+	String host = url.getHost();
+	Vector cookieVector = getSubsetRelevantCookies(host, url);
+
+	Vector tempVector;
+	int index;
+
+	while ((index = host.indexOf('.', 1)) >= 0) {
+	    // trim off everything up to, and including the dot.
+	    host = host.substring(index+1);
+	    
+            // add onto cookieVector
+	    tempVector = getSubsetRelevantCookies(host,url);
+	    if (tempVector != null ) {
+		for (Enumeration e = tempVector.elements(); e.hasMoreElements(); ) {
+		    if (cookieVector == null) {
+			cookieVector = new Vector(2);
+		    }
+
+		    cookieVector.addElement(e.nextElement());
+
+		}
+	    }
+	}
+	return cookieVector;
+    }
+
+    private Vector getSubsetRelevantCookies(String host, URL url) {
+
+	Vector cookieList = (Vector)cookieJar.get(host);
+	
+//	System.out.println("getRelevantCookies() .. for host, url " + host +", "+url);
+	Vector cookiePortList = (Vector)cookieJar.get(host+":"+((url.getPort() == -1) ? 80 : url.getPort()));
+	if (cookiePortList != null) {
+	    if (cookieList == null) {
+		cookieList = new Vector(10);
+	    }
+	    Enumeration cookies = cookiePortList.elements(); 
+	    while (cookies.hasMoreElements()) {
+		cookieList.addElement(cookies.nextElement());
+	    }  
+	}
+	
+	    
+	if (cookieList == null) {
+	    return null;
+	}
+
+	String path = url.getFile();
+//	System.out.println("        path is " + path + "; protocol = " + url.getProtocol());
+
+
+	int queryInd = path.indexOf('?');
+	if (queryInd > 0) {
+	    // strip off the part following the ?
+	    path = path.substring(0, queryInd);
+	}
+
+	Enumeration cookies = cookieList.elements();
+	Vector cookiesToSend = new Vector(10);
+
+	while (cookies.hasMoreElements()) {
+	    HttpCookie cookie = (HttpCookie)cookies.nextElement();
+	
+	    String cookiePath = cookie.getPath();
+
+	    if (path.startsWith(cookiePath)) {
+		// larrylf: Actually, my documentation (from Netscape)
+		// says that /foo should
+		// match /foobar and /foo/bar.  Yuck!!!
+
+		if (!cookie.hasExpired()) {
+		    cookiesToSend.addElement(cookie);
+		}
+
+/*
+   We're keeping this piece of commented out code around just in
+   case we decide to put it back.  the spec does specify the above,
+   but it is so disgusting!
+
+		int cookiePathLen = cookiePath.length();
+
+		// verify that /foo does not match /foobar by mistake
+		if ((path.length() == cookiePathLen)
+		    || (path.length() > cookiePathLen &&
+			path.charAt(cookiePathLen) == '/')) {
+		
+		    // We have a matching cookie!
+
+		    if (!cookie.hasExpired()) {
+			cookiesToSend.addElement(cookie);
+		    }
+		}
+*/
+	    }
+	}
+
+	// Now, sort the cookies in most to least specific order
+	// Yes, its the deaded bubblesort!! Wah Ha-ha-ha-ha....
+	// (it should be a small vector, so perf is not an issue...)
+	if( cookiesToSend.size() > 1 ) {
+	    for( int i = 0; i < cookiesToSend.size()-1; i++ ) {
+		HttpCookie headC = (HttpCookie)cookiesToSend.elementAt(i);
+		String head = headC.getPath();
+		// This little excercise is a cheap way to get
+		// '/foo' to read more specfic then '/'
+		if( !head.endsWith("/") ) {
+		    head = head + "/";
+		}
+		for( int j = i+1; j < cookiesToSend.size(); j++ ) {
+		    HttpCookie scanC = (HttpCookie)cookiesToSend.elementAt(j);
+		    String scan = scanC.getPath();
+		    if( !scan.endsWith("/") ) {
+			scan = scan + "/";
+		    }
+
+		    int headCount = 0;
+		    int index = -1;
+		    while( (index=head.indexOf('/', index+1)) != -1 ) {
+			headCount++;
+		    }
+		    index = -1;
+
+		    int scanCount = 0;
+		    while( (index=scan.indexOf('/', index+1)) != -1 ) {
+			scanCount++;
+		    }
+
+		    if( scanCount > headCount ) {
+			cookiesToSend.setElementAt(headC, j);
+			cookiesToSend.setElementAt(scanC, i);
+			headC = scanC;
+			head = scan;
+		    }
+		}
+	    }
+	}
+
+
+    return cookiesToSend;
+
+    }
+
+    /*
+     * Writes cookies out to PrintWriter if they are persistent
+     * (i.e. have a expr date)
+     * and haven't expired. Will remove cookies that have expired as well
+     */
+    private void saveCookiesToStream(PrintWriter pw) {
+
+	Enumeration cookieLists = cookieJar.elements();
+		
+	while (cookieLists.hasMoreElements()) {
+	    Vector cookieList = (Vector)cookieLists.nextElement();
+
+	    Enumeration cookies = cookieList.elements();
+
+	    while (cookies.hasMoreElements()) {
+		HttpCookie cookie = (HttpCookie)cookies.nextElement();
+		
+		if (cookie.getExpirationDate() != null) {
+		    if (cookie.isSaveable()) {
+			pw.println(cookie);
+		    } else { // the cookie must have expired, 
+			//remove from Vector cookieList
+			cookieList.removeElement(cookie);
+		    }
+		 
+		}   
+	    }
+	}
+        // Must print something to the printwriter in the case that 
+	// the cookieJar has been cleared - otherwise the old cookie
+	// file will continue to exist.
+	pw.print("");
+    }
+/////////////////////////////////////////////////////////////
+    /* adds cookieList to the existing cookie jar*/
+    public void addToCookieJar(HttpCookie[] cookieList) {
+
+	if (cookieList != null) {
+	    for (int i = 0; i < cookieList.length; i++) {
+		
+		recordCookie(cookieList[i]);
+	    }
+	}
+
+    }
+
+    /*adds one cookie to the Cookie Jar */
+    public void addToCookieJar(String cookieString, URL docURL) {
+	recordCookie(new HttpCookie(docURL, cookieString));
+    }
+
+    /* loads the cookies from the given filename */
+    public void loadCookieJarFromFile(String cookieFileName) {
+	try {
+	    FileReader fr = new FileReader(cookieFileName);
+	    
+	    BufferedReader in = new BufferedReader(fr);
+
+	    try {
+		String cookieString;
+		while ((cookieString = in.readLine()) != null) {
+		    HttpCookie cookie = new HttpCookie(cookieString);
+		    // Record the cookie, without notification.  We don't
+		    // do a notification for cookies that are read at
+		    // program start-up.
+		    recordCookie(cookie);
+		}
+	    } finally {
+		in.close();
+	    }
+
+	    
+	} catch (IOException e) {
+	    // do nothing; it's not an error not to have persistent cookies
+	}
+
+    }
+    
+    /* saves the cookies to the given file specified by fname */
+    public void saveCookieJarToFile(String cookieFileName) {
+	try {
+	    FileWriter fw = new FileWriter(cookieFileName);
+	    PrintWriter pw = new PrintWriter(fw, false);
+
+	    try {
+		saveCookiesToStream(pw);
+	    } finally {
+		pw.close();
+	    }
+
+	} catch (IOException e) {
+	    // REMIND: I18N
+	    System.err.println("Saving cookies failed " + e.getMessage());
+	}
+    }
+
+    /**
+     * Return an array with all of the cookies represented by this
+     * jar.  This is useful when the bean is shutting down, and the client
+     * wants to make the cookie jar persist.
+     */
+    public HttpCookie[] getAllCookies() {
+
+	Vector result = new Vector();
+	Hashtable jar;
+	jar = (Hashtable) cookieJar.clone();
+	
+	synchronized (jar) {
+	
+	    for (Enumeration e = jar.elements(); e.hasMoreElements() ;) {
+		Vector v = (Vector) e.nextElement();
+		for (int i = 0; i < v.size(); i++) {
+		    HttpCookie hc = (HttpCookie) v.elementAt(i);
+		    result.addElement(hc);
+		    
+		}
+		
+	    }
+	}
+
+	HttpCookie[] resultA = new HttpCookie[result.size()];
+	for (int i = 0; i < result.size(); i++) {
+	    resultA[i] = (HttpCookie) result.elementAt(i);
+	}
+	return resultA;
+    }
+
+    /* Gets all cookies that applies for the URL */
+    public HttpCookie[] getCookiesForURL(URL url) {
+
+	Vector cookieVector = getAllRelevantCookies(url);
+
+	if (cookieVector == null) {
+	    return null;
+	}
+
+	int i = 0;
+	HttpCookie[] cookieArr = new HttpCookie[cookieVector.size()];
+
+	for (Enumeration e = cookieVector.elements(); e.hasMoreElements(); ) {
+
+	    cookieArr[i++] = (HttpCookie)e.nextElement();
+//	    System.out.println("cookieArr["+(i-1)+"] = " +cookieArr[i-1].toString());
+	}
+	    
+	return cookieArr;
+    }
+
+    /* this will set the property of enableCookies to isDisabled */
+    public void setCookieDisable(boolean isDisabled) {
+
+	// Pending visit back this again
+	try {
+	Properties properties = new Properties();
+	properties.load(new FileInputStream("ServerAutoRun.properties") );
+	
+	
+	properties.put("enableCookies", isDisabled ? "false" : "true");
+	properties.store(new FileOutputStream("ServerAutoRun.properties"),"comments");
+	}
+	catch ( Exception e )
+	{
+		System.out.println("Exception : " + e );
+	}
+    }
+
+    public void discardAllCookies() {
+	cookieJar.clear();
+	
+    }
+
+    /* 
+     * purges any expired cookies in the Cookie hashtable.
+     */
+    public void purgeExpiredCookies() {
+	Enumeration cookieLists = cookieJar.elements();
+		
+	while (cookieLists.hasMoreElements()) {
+	    Vector cookieList = (Vector)cookieLists.nextElement();
+
+	    Enumeration cookies = cookieList.elements();
+
+	    while (cookies.hasMoreElements()) {
+		HttpCookie cookie = (HttpCookie)cookies.nextElement();
+		
+		if (cookie.hasExpired()) {
+		    cookieList.removeElement(cookie);
+		}   
+	    }
+	}
+
+    }
+
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
------------------------------------------------------------------------------
    svn:executable = *

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.coyote.adapters.CoyoteServer;
+import org.apache.coyote.adapters.EchoAdapter;
+import org.apache.coyote.adapters.MapperAdapter;
+import org.apache.coyote.adapters.ProxyAdapter;
+import org.apache.coyote.adapters.SleepAdapter;
+import org.apache.coyote.adapters.StaticAdapter;
+import org.apache.coyote.client.AsyncHttp;
+import org.apache.coyote.client.AsyncHttpPool;
+import org.apache.coyote.client.BlockingHttp;
+import org.apache.coyote.http11.async.AsyncProtocolHandler;
+import org.apache.juli.JdkLoggerConfig;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.lite.TomcatLiteTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class CoyoteTestHelper {
+
+    public static boolean testWithNewConnector = true;
+    public static boolean testWithAsyncClient = true;
+
+    /**
+     *  Get url using URLConnection.
+     */
+    public static ByteChunk getUrl(String path) throws IOException {
+
+        ByteChunk out = new ByteChunk();
+        
+        if (!testWithAsyncClient) {
+            URL url = new URL(path);
+            URLConnection connection = url.openConnection();
+            connection.setReadTimeout(5000);
+            connection.connect();
+            InputStream is = connection.getInputStream();
+            BufferedInputStream bis = new BufferedInputStream(is);
+            byte[] buf = new byte[2048];
+            int rd = 0;
+            while((rd = bis.read(buf)) > 0) {
+                out.append(buf, 0, rd);
+            }
+        } else {
+            AsyncHttp aclient = AsyncHttpPool.getDefault().get();
+            BlockingHttp client = aclient.getBlockingHttp();
+            aclient.open(path);
+            client.readAll(out, 20000);
+            aclient.release(); // return connection to pool
+        }
+        return out;
+    }
+  
+    private void dumpHead(AsyncHttp client) throws IOException {
+        ByteChunk buf = new ByteChunk();
+        AsyncHttp.serializeResponse(client.getResponse(), buf);
+        System.err.println("-------RESPONSE HEAD:" +  buf);
+    }
+    
+    static Map<Integer, CoyoteServer> servers = new HashMap();
+  
+  /**
+   * Return a test suite which will run with a started coyote server with all
+   * the test servlets.  
+k   */
+  public static TestSuite coyoteSuite() {
+      return new TestSuite("Coyote") {
+          public void run(TestResult r) {
+              
+              super.run(r);
+          }
+      };
+  }
+  
+  /** 
+   * Return a (singleton) test server. Use to avoid starting
+   * coyote on each test.
+   *
+   * @param port
+   * @return
+ * @throws ServletException 
+   */
+  public static CoyoteServer getTestServer(int port)  {
+      CoyoteServer server = getCachedServer(port);
+      if (!server.getStarted()) {
+          server.start();
+      }
+      return server;
+  }
+
+  private static CoyoteServer getCachedServer(int port) {
+    CoyoteServer server = servers.get(port);
+    if (server == null) {
+        try {
+            server = startServer(port, true);
+        } catch (ServletException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        servers.put(port, server);
+    }
+    return server;
+}
+  
+  public static CoyoteServer getProxyServer(int port) {
+      CoyoteServer server = servers.get(port);
+      if (server == null) {
+          server = new CoyoteServer(port, new ProxyAdapter());
+          AsyncProtocolHandler proto = new AsyncProtocolHandler();
+          server.setConnector(proto);
+          server.start();
+          servers.put(port, server);
+                    
+      }
+      return server;
+  }
+  
+  public static CoyoteServer startServer(int port, boolean daemon) 
+      throws ServletException, IOException {
+    JdkLoggerConfig.loadCustom();
+    CoyoteServer server = initServerAdapters(port, daemon);
+    
+    addConnector(port, daemon, server);
+    
+    server.start();
+        
+    return server;
+  }
+
+  private static void addConnector(int port, boolean daemon, 
+                                   CoyoteServer server) {
+      server.setPort(port);
+      server.setDaemon(daemon);
+      if (testWithNewConnector) {
+          server.setAsyncConnector();
+      } else {
+          server.setNioConnector();
+      }
+  }
+
+  private static CoyoteServer initServerAdapters(int port, boolean daemon) throws ServletException, IOException {
+      CoyoteServer server = new CoyoteServer();
+      server.setPort(port);
+      server.setDaemon(daemon);
+
+      server.addAdapter("/hello", 
+              new StaticAdapter().setData("Hello world"));
+
+      server.addAdapter("/2nd", 
+              new StaticAdapter().setData("Hello world2"));
+
+      server.addAdapter("/sleep/1", 
+              new SleepAdapter().sleep(1000).setData("sleep 1"));
+      server.addAdapter("/sleep/1c", 
+              new SleepAdapter().sleep(1000).setData("sleep 1c").chunked());
+      server.addAdapter("/sleep/2", 
+              new SleepAdapter().sleep(2000).setData("sleep 2"));
+      server.addAdapter("/sleep/10", 
+              new SleepAdapter().sleep(10000).setData("sleep 10"));
+
+      server.addAdapter("/echo/*", new EchoAdapter());
+      server.addAdapter("/chunked/*", 
+              new StaticAdapter().chunked());
+
+      server.addAdapter("/aaa/*", 
+              new StaticAdapter());
+
+      // Add servlets
+      TomcatLite servlets = new TomcatLite(server);
+      TomcatLiteTest.initServlets(servlets);
+
+      server.addAdapter("/", servlets); 
+      server.init();
+      return server;
+  }
+  
+  public static CoyoteServer getWatchdog(String path) throws ServletException, 
+          IOException {
+      if (path == null) {
+          path = System.getProperty("watchdog.home");
+      }
+      if (path == null) {
+          path = "../../watchdog";
+      }
+
+      File f = new File(path + "/build/webapps");
+      CoyoteServer server = new CoyoteServer();
+      server.setPort(8080);
+      server.setDaemon(true);
+      TomcatLite servlets = new TomcatLite(server);
+      
+      servlets.init("webapps/ROOT", "/");
+      
+      for (String s : new String[] {      
+              "servlet-compat", 
+              "servlet-tests",
+              "jsp-tests"} ) {
+          servlets.init(f.getCanonicalPath() + "/" + s, 
+                  "/" + s);
+      }
+      server.addAdapter("/", new MapperAdapter());
+      server.addAdapter("/", servlets);
+      server.init();
+      addConnector(8080, true, server);
+      servlets.init();
+      servlets.start();
+      server.start();
+      return server;
+  }
+
+  
+  public static void main(String[] args) throws ServletException, IOException {
+      startServer(8902, false);
+      startServer(0, false);
+      getWatchdog(null);
+    //CoyoteServer proxyServer = getProxyServer(8901);
+  }
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,1196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @Author Costin, Ramesh.Mandava
+*/
+
+package org.apache.tomcat.test;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.sun.xml.internal.rngom.ast.builder.BuildException;
+
+
+// derived from Jsp
+
+public class GTest {
+
+    private static final String ZEROS        = "00000000";
+    private static final int SHORTPADSIZE    = 4;
+    private static final int BYTEPADSIZE     = 2;
+
+    int failureCount = 0;
+    int passCount = 0;
+    Throwable lastError;
+    boolean hasFailed = false;
+
+    String prefix = "http";
+    String host = "localhost";
+    String localHost = null;
+    String localIP = null;
+    int port = 8080;
+    int debug = 0;
+
+    String description = "No description";
+
+    String request;
+    HashMap requestHeaders = new HashMap();
+    String content;
+    
+    // true if task is nested
+    private boolean nested = false;
+
+    // Expected response
+    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
+    HashMap expectHeaders = new HashMap();
+
+    // Headers that should not be found in response
+    HashMap unexpectedHeaders = new HashMap();
+
+    // Match request line
+    String returnCode = "";
+    String returnCodeMsg = "";
+
+    // Actual response
+    String responseLine;
+    byte[] responseBody;
+    HashMap headers;
+
+
+    // For Report generation
+    StringBuffer resultOut = new StringBuffer();
+    
+    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() );
+        }
+    }
+
+    /**
+     * <code>setTestName</code> sets the current test name.
+     *
+     * @param tn current testname.
+     */
+    public void setTestName ( String tn ) {
+        testName = tn;
+    }
+
+    /**
+     * <code>setAssertion</code> sets the assertion text
+     * for the current test.
+     *
+     * @param assertion assertion text
+     */
+    public void setAssertion ( String assertion ) {
+        this.assertion = assertion;
+    }
+ 
+    /**
+     * <code>setTestStrategy</code> sets the test strategy
+     * for the current test.
+     *
+     * @param strategy test strategy text
+     */
+    public void setTestStrategy ( String strategy ) {
+        testStrategy = strategy;
+    }
+
+    /**
+     * <code>getTestName</code> returns the current 
+     * test name.
+     *
+     * @return a <code>String</code> value
+     */
+    public String getTestName( ) {
+        return testName;
+    }
+
+    /**
+     * <code>getAssertion</code> returns the current
+     * assertion text.
+     *
+     * @return a <code>String</code> value
+     */
+    public String getAssertion( ) {
+        return assertion;
+    }
+
+    /**
+     * <code>getTestStrategy</code> returns the current
+     * test strategy test.
+     *
+     * @return a <code>String</code> value
+     */
+    public String getTestStrategy( ) {
+        return testStrategy;
+    }
+
+    /**
+     * <code>setFirstTask</code> denotes that current task
+     * being executed is the first task within the list.
+     *
+     * @param a <code>boolean</code> value
+     */    
+    public void setFirstTask( boolean val ) {
+        firstTask = val;
+    }
+   
+
+    /**
+     * <code>setLastTask</code> denotes that the current task
+     * being executed is the last task within the list.
+     *
+     * @param a <code>boolean</code> value
+     */ 
+    public void setLastTask ( boolean val ) {
+        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;
+    }
+
+    /**
+     * <code>setHost</code> sets hostname where
+     * the target server is running. Defaults to
+     * "localhost"
+     *
+     * @param h a <code>String</code> value
+     */
+    public void setHost( String h ) {
+        this.host = h;
+    }
+
+    /**
+     * <code>setPort</code> sets the port
+     * that the target server is listening on.
+     * Defaults to "8080"
+     *
+     * @param portS a <code>String</code> value
+     */
+    public void setPort( String portS ) {
+        this.port = Integer.valueOf( portS ).intValue();
+    }
+
+    /**
+     * <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();
+    }
+
+    /**
+     * <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();
+    }
+
+    /**
+     * <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();
+    }
+
+    /**
+     * <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;
+    }
+
+    /**
+     * <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;
+    }
+
+    /**
+     * <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 HashMap();
+        StringTokenizer tok = new StringTokenizer( s, "|" );
+        while ( tok.hasMoreElements() ) {
+            String header = (String) tok.nextElement();
+            setHeaderDetails( header, expectHeaders, false );
+        }
+    }
+
+    /**
+     * <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();
+        setHeaderDetails( s, unexpectedHeaders, false );
+    }
+
+    public void setNested( String s ) {
+        nested = Boolean.valueOf( s ).booleanValue();
+    }
+
+    /**
+     * <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;
+    }
+
+    /**
+     * <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
+     */
+    public void setRequest ( String s ) {
+        this.request = 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;
+    }
+
+    /**
+     * Describe <code>setReturnCodeMsg</code> Sets the expected
+     * return 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 setReturnCodeMsg( String message ) {
+        this.returnCodeMsg = message;
+    }
+
+    /**
+     * <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 HashMap();
+        StringTokenizer tok = new StringTokenizer( s, "|" );
+        while ( tok.hasMoreElements() ) {
+            String header = (String) tok.nextElement();
+            setHeaderDetails( header, requestHeaders, true );
+        }
+    }
+
+    // Inner tests are not used currently, can be reworked
+    
+//    /**
+//     * Add a Task to this container
+//     *
+//     * @param Task to add
+//     */
+//    public void addTask(Task task) {
+//        children.add(task);
+//    }
+
+    /**
+     * <code>execute</code> Executes the test.
+     *
+     * @exception BuildException if an error occurs
+     */
+    public void execute()  {
+
+        try {
+
+            if ( resultOut != null && !nested ) {
+                resultOut.append("\ntestName: " + testName);
+                resultOut.append("\nreq: " + request);
+                resultOut.append("\nassertion: " + assertion);
+                resultOut.append("\ntestStrategy: " + testStrategy);
+            }
+
+            SimpleHttpClient.dispatch(this);
+
+            hasFailed = !checkResponse( magnitude );
+
+
+//            if ( !children.isEmpty() ) {
+//                Iterator iter = children.iterator();
+//                while (iter.hasNext()) {
+//                    Task task = (Task) iter.next();
+//                    task.perform();
+//                }
+//            }
+
+            if ( !hasFailed && !nested ) {
+                passCount++;
+                if ( resultOut != null ) {
+                    resultOut.append( "<result>PASS</result>\n" );
+                }
+                System.out.println( " PASSED " + testName + "\n        (" + request + ")" );
+            } else if ( hasFailed && !nested ){
+		        failureCount++;
+                if ( resultOut != null ) {
+                    resultOut.append( "<result>FAIL</result>\n" );
+                }
+                System.out.println( " FAILED " + testName + "\n        (" + request + ")\n" +
+                        resultOut.toString());
+            }
+
+        } catch ( Exception ex ) {
+            failureCount++;
+            System.out.println( " FAIL " + description + " (" + request + ")" );
+            lastError = ex;
+            ex.printStackTrace();
+        } finally {
+            if ( !nested ) {
+                hasFailed = false;
+            }
+        }
+    }
+
+    /**
+     * <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 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 ( returnCodeMsg.equals( "" ) ) {
+			        match = resCode;
+		        } else {
+			        match = ( resCode && resMsg );
+		        }
+
+		        if ( match != testCondition ) {
+
+			        if ( resultOut != null ) {
+                                  String expectedStatusCode = "<expectedStatusCode>" + returnCode + "</expectedReturnCode>\n";
+                                  String expectedReasonPhrase = "<expectedReasonPhrase>" + returnCodeMsg + "</expectedReasonPhrase>";
+                                  actualString = "<actualStatusLine>" + responseLine + "</actualStatusLine>\n";
+			            resultOut.append( expectedStatusCode );
+			            resultOut.append( expectedReasonPhrase );
+			            resultOut.append( actualString );
+			        }
+
+			        return false;
+		        }
+		    }
+	    } else {
+	        resultOut.append("\n<failure>Wrong Http version: " + responseLine +
+	                "</failure>");
+	        return false;
+	    }
+	} else {
+	    resultOut.append("\n<failure>No response from server</failure>" );
+	    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 ( !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 );
+				                
+                                /*
+                                 * Handle the Content-Type header appropriately
+                                 * based on the the test is configured to look for.
+                                 */
+                                if ( currentHeaderField.equalsIgnoreCase( "content-type" ) ) {
+                                    String resVal = (String) headerValues.get( 0 );
+                                    if ( currentHeaderValue.indexOf( ';' ) > -1 ) {
+                                        if ( currentHeaderValue.equals( resVal ) ) {
+                                            numberFound++;
+                                            headerValues.remove( 0 );
+                                        }
+                                    } else if ( resVal.indexOf( currentHeaderValue ) > -1 ) {
+                                        numberFound++;
+                                        headerValues.remove( 0 );
+                                    }
+                                } else if ( currentHeaderField.equalsIgnoreCase( "location" ) ) {
+                                    String resVal = (String) headerValues.get( 0 );
+                                    int idx = currentHeaderValue.indexOf( ":80/" );
+                                    if ( idx > -1 ) {
+                                        String tempValue = currentHeaderValue.substring( 0, idx ) +
+                                                           currentHeaderValue.substring( idx + 3 );
+                                        if ( currentHeaderValue.equals( resVal ) || 
+                                             tempValue.equals( resVal ) ) {
+                                            numberFound++;
+                                            headerValues.remove( 0 );
+                                        }
+                                    } else {
+                                        if ( currentHeaderValue.equals( resVal ) ) {
+                                            numberFound++;
+                                            headerValues.remove( 0 );
+                                        }
+                                    }
+                                } else 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 );
+		if ( resultOut != null ) {
+		    expectedString = "<expectedHeaderNotFound>" + currentHeaderField + ": " + currentHeaderValue + "</expectedHeader>\n";
+		}
+                if ( !headers.isEmpty() ) {
+                    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++ ) {
+			    if ( resultOut != null ) {
+				actualBuffer.append( "<actualHeader>" + headerName + ": " + val[ i ] + "</actualHeader>\n" );
+			    }
+                        }
+                    }
+		    if ( resultOut != null ) {
+			resultOut.append( expectedString );
+			resultOut.append( actualBuffer.toString() );
+		    }
+                }
+                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;
+            // 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 ) {
+                resultOut.append( "\n Unexpected header received from server: " + unExpHeader );
+                return false;
+            }
+	}
+
+           
+
+        if ( responseMatch != null ) {
+            // check if we got the string we wanted
+            if ( expectResponseBody && responseBody == null ) {
+                resultOut.append( "\n ERROR: got no response, expecting " + responseMatch );
+                return false;
+            }
+	    String responseBodyString = new String( responseBody );
+            if ( responseBodyString.indexOf( responseMatch ) < 0 ) {
+                resultOut.append( "\n ERROR: expecting match on " + responseMatch );
+                resultOut.append( "\n Received: \n" + responseBodyString );
+            }
+        }
+
+	if ( !expectResponseBody && responseBody != null ) {
+	    resultOut.append("Received a response body from the server where none was expected" );
+	    return false;
+	}
+
+        // compare the body
+        if ( goldenFile == null )
+            return true;
+
+        // Get the expected result from the "golden" file.
+        byte[] expResult = getExpectedResult();
+        String expResultS = (expResult == null) ? "" : new String(expResult);
+        // Compare the results and set the status
+        boolean cmp = true;
+
+        if ( exactMatch ) {
+            cmp = compare( responseBody, expResult );
+	} else {
+            cmp = compareWeak( responseBody, expResult );
+	}
+
+        if ( cmp != testCondition ) {
+
+            if ( resultOut != null ) {
+              expectedString = "<expectedBody>" + new String(expResult) + "</expectedBody>\n";
+              actualString = "<actualBody>" + 
+              (responseBody != null ? new String(responseBody) : "null" ) + 
+              "</actualBody>\n";
+                resultOut.append( expectedString );
+                resultOut.append( actualString );
+            }
+ 
+	    return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Replaces any |client.ip| and |client.host| parameter marks
+     * with the host and IP values of the host upon which Watchdog
+     * is running.
+     *
+     * @param request An HTTP request. 
+     */
+     String replaceMarkers( String req, Socket socket ) {
+        
+        final String CLIENT_IP = "client.ip";
+        final String CLIENT_HOME = "client.host";
+
+        if (localIP == null || localHost == null) {
+            InetAddress addr = socket.getLocalAddress(); 
+            localHost = addr.getHostName();
+            localIP = addr.getHostAddress();
+        }
+
+        if (req.indexOf('|') > -1) {
+            StringTokenizer tok = new StringTokenizer( request, "|" );
+            StringBuffer sb = new StringBuffer( 50 );
+        
+            while ( tok.hasMoreElements() ) {
+                String token = tok.nextToken();
+                if ( token.equals( CLIENT_IP ) ) {
+                    sb.append( localIP );
+                } else if ( token.equals( CLIENT_HOME ) ) {
+                    sb.append( localHost );
+                } else {
+                    sb.append( token );
+                }
+            }
+            return sb.toString(); 
+        } else {
+            return req;
+        }
+    }
+            
+
+    
+    /**
+     * <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 = new BufferedInputStream(
+			         new FileInputStream( goldenFile ) );
+            return readBody ( in );
+        } catch ( Exception ex ) {
+            System.out.println( "Golden file not found: " + goldenFile );
+            return expResult;
+        }
+    }
+
+    /**
+     * <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;
+	}
+
+	/*
+         * 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 );
+            resultOut.append( 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 ] ) {
+                    resultOut.append( "\n Error at position " + ( i + 1 ) );
+                    // dump the hex representation of the byte arrays
+                    dumpHex( fromServer, fromGoldenFile );
+
+                    return false;
+                }
+
+                i++;
+                j++;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * <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;
+	    }
+
+        boolean status = true;
+
+        String server = new String( fromServer );
+        String golden = new String( fromGoldenFile );
+
+        StringTokenizer st1 = new StringTokenizer( server );
+
+        StringTokenizer st2 = new StringTokenizer( golden );
+
+        while ( st1.hasMoreTokens() && st2.hasMoreTokens() ) {
+            String tok1 = st1.nextToken();
+            String tok2 = st2.nextToken();
+
+            if ( !tok1.equals( tok2 ) ) {
+                resultOut.append( "\t FAIL*** : Rtok1 = " + tok1
+                                    + ", Etok2 = " + tok2 );
+                status = false;
+            }
+        }
+
+        if ( st1.hasMoreTokens() || st2.hasMoreTokens() ) {
+             status = false;
+        }
+
+        if ( !status ) {
+            StringBuffer sb = new StringBuffer( 255 );
+            sb.append( "ERROR: Server's response and configured goldenfile do not match!\n" );
+            sb.append( "Response received from server:\n" );
+            sb.append( "---------------------------------------------------------\n" );
+            sb.append( server );
+            sb.append( "\nContent of Goldenfile:\n" );
+            sb.append( "---------------------------------------------------------\n" );
+            sb.append( golden );
+            sb.append( "\n" );
+            resultOut.append( sb.toString() );
+        }
+        return status;
+    }
+
+    /**
+     * <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;
+                    }
+                }
+                sb.append( ( char ) ch );
+                 
+            } catch ( IOException ex ) {
+                return null;
+            }
+        }
+        return sb.toString().getBytes();
+    }
+
+    /**
+     * <code>setHeaderDetails</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
+     */
+    void setHeaderDetails( String line, HashMap headerHash, boolean isRequest ) {
+        StringTokenizer stk = new StringTokenizer( line, "##" );
+
+        while ( stk.hasMoreElements( ) ) {
+            String presentHeader = stk.nextToken();
+            parseHeader( presentHeader, headerHash, isRequest );
+        }
+    }
+
+    /**
+     * <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.
+     */
+    void parseHeader( String line, HashMap headerMap, boolean isRequest ) {
+        // Parse the header name and value
+        int colon = line.indexOf( ":" );
+
+        if ( colon < 0 ) {
+            resultOut.append( "\n 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);
+
+	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 );
+    }
+
+    /**
+     * <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" );
+
+        resultOut.append( 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;
+    }
+
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.test;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Date;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * An object which represents an HTTP cookie.  Can be constructed by
+ * parsing a string from the set-cookie: header.
+ *
+ * Syntax: Set-Cookie: NAME=VALUE; expires=DATE;
+ *             path=PATH; domain=DOMAIN_NAME; secure
+ *
+ * All but the first field are optional.
+ *
+ * @author	Ramesh.Mandava
+ */
+
+public class HttpCookie {
+    private Date expirationDate = null;
+    private String nameAndValue;
+    private String path;
+    private String domain;
+    private boolean isSecure = false;
+    private static boolean defaultSet = true;
+    private static long defExprTime = 100;
+
+    public HttpCookie(String cookieString) {
+	/*
+	System.out.println("Calling default expiration :");
+	getDefaultExpiration();
+	*/
+	parseCookieString(cookieString);
+    }
+
+    //
+    // Constructor for use by the bean
+    //
+    public HttpCookie(Date expirationDate,
+		      String nameAndValue,
+		      String path,
+		      String domain,
+		      boolean isSecure) {
+	this.expirationDate = expirationDate;
+	this.nameAndValue = nameAndValue;
+	this.path = path;
+	this.domain = domain;
+	this.isSecure = isSecure;
+    }
+
+    public HttpCookie(URL url, String cookieString) {
+	parseCookieString(cookieString);
+	applyDefaults(url);
+    }
+
+    /**
+     * Fills in default values for domain, path, etc. from the URL
+     * after creation of the cookie.
+     */
+    private void applyDefaults(URL url) {
+	if (domain == null) {
+	    domain = url.getHost()+":"+((url.getPort() == -1) ? 80 : url.getPort());
+	}
+
+	if (path == null) {
+	    path = url.getFile();
+
+	    // larrylf: The documentation for cookies say that the path is
+	    // by default, the path of the document, not the filename of the
+	    // document.  This could be read as not including that document
+	    // name itself, just its path (this is how NetScape intrprets it)
+	    // so amputate the document name!
+	    int last = path.lastIndexOf("/");
+	    if( last > -1 ) {
+		path = path.substring(0, last);
+	    }
+	}
+    }
+
+
+    /**
+     * Parse the given string into its individual components, recording them
+     * in the member variables of this object.
+     */
+    private void parseCookieString(String cookieString) {
+	StringTokenizer tokens = new StringTokenizer(cookieString, ";");
+
+	if (!tokens.hasMoreTokens()) {
+	    // REMIND: make this robust against parse errors
+	    nameAndValue="=";
+	    return;
+	}
+
+	nameAndValue = tokens.nextToken().trim();
+	
+	while (tokens.hasMoreTokens()) {
+	    String token = tokens.nextToken().trim();
+	
+	    if (token.equalsIgnoreCase("secure")) {
+		isSecure = true;
+	    } else {
+		int equIndex = token.indexOf("=");
+		
+		if (equIndex < 0) {
+		    continue;
+		    // REMIND: malformed cookie
+		}
+		
+		String attr = token.substring(0, equIndex);
+		String val = token.substring(equIndex+1);
+		
+		if (attr.equalsIgnoreCase("path")) {
+		    path = val;
+		} else if (attr.equalsIgnoreCase("domain")) {
+		    if( val.indexOf(".") == 0 ) {
+			// spec seems to allow for setting the domain in
+			// the form 'domain=.eng.sun.com'.  We want to
+			// trim off the leading '.' so we can allow for
+			// both leading dot and non leading dot forms
+			// without duplicate storage.
+			domain = val.substring(1);
+		    } else {
+			domain = val;
+		    }
+		} else if (attr.equalsIgnoreCase("expires")) {
+		    expirationDate = parseExpireDate(val);
+		} else {
+		    // unknown attribute -- do nothing
+		}
+	    }
+	}
+
+	// commented the following out, b/c ok to have no expirationDate
+	// that means that the cookie should last only for that particular 
+	// session.
+	//	if (expirationDate == null) {
+	//     	    expirationDate = getDefaultExpiration();
+	//	}
+    }
+    
+    /* Returns the default expiration, which is the current time + default
+       expiration as specified in the properties file.
+       This uses reflection to get at the properties file, since Globals is 
+       not in the utils/ directory 
+       */
+    private Date getDefaultExpiration() {
+	if (defaultSet == false) {
+	    Properties props = new Properties();
+	    
+	    try {
+		FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+		props.load( fin );
+		
+		System.out.println("Got properties from ServerAutoRun.properties");
+		props.list(System.out);
+		
+	    } catch (IOException ex) {
+		System.out.println("HttpCookie getDefaultExpiration : ServerAutoRun.properties not found!" + ex);
+	    }
+	    
+		 // defExprTime = props.getProperty("cookies.default.expiration");
+		 defExprTime = Long.parseLong( props.getProperty("cookies.default.expiration") );
+
+	    }
+	    defaultSet = true;
+	  
+	return (new Date(System.currentTimeMillis() + defExprTime));
+	
+    }
+
+    //======================================================================
+    //
+    // Accessor functions
+    //
+
+
+
+     public String getNameValue() {
+	return nameAndValue;
+    }
+
+    /**
+     * Returns just the name part of the cookie
+     */
+     public String getName() {
+
+	 // it probably can't have null value, but doesn't hurt much
+	 // to check.
+	 if (nameAndValue == null) {
+	     return "=";
+	 }
+	 int index = nameAndValue.indexOf("=");
+	 return (index < 0) ? "=" : nameAndValue.substring(0, index);
+     }
+
+
+    /**
+     * Returns the domain of the cookie as it was presented
+     */
+     public String getDomain() {
+	// REMIND: add port here if appropriate
+	return domain;
+    }
+
+     public String getPath() {
+	return path;
+    }
+
+     public Date getExpirationDate() {
+	return expirationDate;
+    }
+
+    public boolean hasExpired() {
+	if(expirationDate == null) {
+	    return false;
+	}
+	return (expirationDate.getTime() <= System.currentTimeMillis());
+    }
+
+    /**
+     * Returns true if the cookie has an expiration date (meaning it's
+     * persistent), and if the date nas not expired;
+     */
+    public boolean isSaveable() {
+	return (expirationDate != null)
+	    && (expirationDate.getTime() > System.currentTimeMillis());
+    }
+
+    public boolean isSaveableInMemory() {
+	return ((expirationDate == null) ||
+		(expirationDate != null && expirationDate.getTime() > System.currentTimeMillis()));
+    }
+		
+     public boolean isSecure() {
+	return isSecure;
+    }
+
+    private Date parseExpireDate(String dateString) {
+	// format is wdy, DD-Mon-yyyy HH:mm:ss GMT
+	RfcDateParser parser = new RfcDateParser(dateString);
+	Date theDate = parser.getDate();
+	if (theDate == null) {
+	    // Expire in some intelligent default time
+	    theDate = getDefaultExpiration();
+	}
+	return theDate;
+    }
+
+    public String toString() {
+
+	String result = (nameAndValue == null) ? "=" : nameAndValue;
+	if (expirationDate != null) {
+	    result += "; expires=" + expirationDate;
+	}
+	
+	if (path != null) {
+	    result += "; path=" + path;
+	}
+
+	if (domain != null) {
+	    result += "; domain=" + domain;
+	}
+
+	if (isSecure) {
+	    result += "; secure";
+	}
+
+	return result;
+    }
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
------------------------------------------------------------------------------
    svn:executable = *

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import junit.framework.Test;
+
+public class LiteJspTests  extends LiteServletTests {
+
+    public static Test suite() {
+        // The individual targets are dups - and bad ones, 
+        // RequestWrapper are missing part of the URL
+        String base = "../../watchdog";
+        String goldenDir = 
+            base + "/src/clients/org/apache/jcheck/jsp/client/";
+        String file = base + "/src/conf/jsp-gtest.xml";
+        
+        return new LiteServletTests().getSuite(base, 
+                file, goldenDir, testMatch, 
+                "jsp-test", exclude);
+    }
+    
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+
+public class LiteServletTests extends WatchdogClient {
+ 
+  static String testMatch = 
+      null;
+      //"ServletToJSP";
+  
+  static String[] exclude = null;
+  static String[] slow = 
+      { 
+          "SingleModelTest" // slow  
+      
+      };  
+  
+  protected void beforeSuite() {
+      // Start the server
+      try {
+          CoyoteTestHelper.getWatchdog(null);
+      } catch (ServletException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      } catch (IOException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      }
+      
+  }
+  
+  protected void afterSuite(TestResult res) {
+      // no need to stop it - using daemon threads.
+      System.out.println("DONE");
+  }
+  
+  
+  public static Test suite() {
+      // The individual targets are dups - and bad ones, 
+      // RequestWrapper are missing part of the URL
+      String base = "../../watchdog";
+      String goldenDir = 
+          base + "/src/clients/org/apache/jcheck/servlet/client/";
+      String file = base + "/src/conf/servlet-gtest.xml";
+      
+      return new LiteServletTests().getSuite(base, 
+              file, goldenDir, testMatch, 
+              "gtestservlet-test", exclude);
+  }
+  
+}

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * A parser for date strings commonly found in http and email headers that
+ * follow various RFC conventions.  Given a date-string, the parser will
+ * attempt to parse it by trying matches with a set of patterns, returning
+ * null on failure, a Date object on success.
+ *
+ * @author Ramesh.Mandava 
+ */
+public class RfcDateParser {
+
+    private boolean isGMT = false;
+
+    static final String[] standardFormats = {
+	"EEEE', 'dd-MMM-yy HH:mm:ss z",   // RFC 850 (obsoleted by 1036)
+	"EEEE', 'dd-MMM-yy HH:mm:ss",     // ditto but no tz. Happens too often
+	"EEE', 'dd-MMM-yyyy HH:mm:ss z",  // RFC 822/1123
+	"EEE', 'dd MMM yyyy HH:mm:ss z",  // REMIND what rfc? Apache/1.1
+	"EEEE', 'dd MMM yyyy HH:mm:ss z", // REMIND what rfc? Apache/1.1
+	"EEE', 'dd MMM yyyy hh:mm:ss z",  // REMIND what rfc? Apache/1.1
+	"EEEE', 'dd MMM yyyy hh:mm:ss z", // REMIND what rfc? Apache/1.1
+	"EEE MMM dd HH:mm:ss z yyyy",      // Date's string output format
+	"EEE MMM dd HH:mm:ss yyyy",	  // ANSI C asctime format()
+	"EEE', 'dd-MMM-yy HH:mm:ss",      // No time zone 2 digit year RFC 1123
+ 	"EEE', 'dd-MMM-yyyy HH:mm:ss"     // No time zone RFC 822/1123
+    };
+
+    /* because there are problems with JDK1.1.6/SimpleDateFormat with
+     * recognizing GMT, we have to create this workaround with the following
+     * hardcoded strings */
+    static final String[] gmtStandardFormats = {
+	"EEEE',' dd-MMM-yy HH:mm:ss 'GMT'",   // RFC 850 (obsoleted by 1036)
+	"EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'",  // RFC 822/1123
+	"EEE',' dd MMM yyyy HH:mm:ss 'GMT'",  // REMIND what rfc? Apache/1.1
+	"EEEE',' dd MMM yyyy HH:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+	"EEE',' dd MMM yyyy hh:mm:ss 'GMT'",  // REMIND what rfc? Apache/1.1
+	"EEEE',' dd MMM yyyy hh:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+	"EEE MMM dd HH:mm:ss 'GMT' yyyy"      // Date's string output format
+    };
+
+    String dateString;
+
+    public RfcDateParser(String dateString) {
+	this.dateString = dateString.trim();
+	if (this.dateString.indexOf("GMT") != -1) {
+	    isGMT = true;
+	}
+    }
+
+    public Date getDate() {
+
+        int arrayLen = isGMT ? gmtStandardFormats.length : standardFormats.length;
+        for (int i = 0; i < arrayLen; i++) {
+            Date d = null;
+
+            if (isGMT) {
+                d = tryParsing(gmtStandardFormats[i]);
+            } else {
+                d = tryParsing(standardFormats[i]);
+            }
+            if (d != null) {
+                return d;
+            }
+
+        }
+
+        return null;
+    }    
+
+    private Date tryParsing(String format) {
+
+	java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(format, Locale.US);
+	if (isGMT) {
+	    df.setTimeZone(TimeZone.getTimeZone("GMT"));
+	}
+	try {
+		return df.parse(dateString);
+	} catch (Exception e) {
+	    return null;
+	}
+    }
+} /* class RfcDateParser */

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
------------------------------------------------------------------------------
    svn:executable = *



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org