/*
* $Header: /home/cvs/jakarta-slide/testsuite/testsuite/junit/src/org/apache/slide/testsuite/testtools/tprocessor/TProcessors.java,v 1.85 2004/08/03 08:44:13 luetzkendorf Exp $
* $Revision: 1.85 $
* $Date: 2004/08/03 08:44:13 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Slide", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.slide.testsuite.testtools.tprocessor;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.slide.testsuite.testtools.tutil.TArgs;
import org.apache.slide.testsuite.testtools.tutil.XConf;
import org.apache.webdav.lib.util.WebdavStatus;
import org.apache.webdav.lib.WebdavState;
import org.apache.webdav.lib.methods.*;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
/**
* Main class to performe a test case and check and report the results
*
* @version $Revision: 1.85 $
*/
public class TProcessors {
/** Table for startup parameter */
Hashtable startUp = null;
/** home */
File config;
/** port */
String port;
/** host */
String host;
/** user */
String defaultUser;
/** password */
String defaultPassword;
/** url encoding */
String defaultUrlEncoding;
/** Tracing required */
String tracingRequest;
/** hold all the variable defined **/
KnownVariablesHashtable knownVariables = new KnownVariablesHashtable();
/** holds all configuration **/
XConf xdavConfiguration = null;
/** specify where to write the xml results **/
private XMLOutput xmlresult = new XMLOutput(System.out);
/** count all executed test elements **/
private long testElementsExecuted = 0;
/** count all executed test elements **/
private long testElementsExecutedWithError = 0;
/** The absolute path name of the execute input file **/
private String globalAbsolutePath = null;
/** The absolute path name of the execute input file **/
private String globalTestFileName = null;
private final Properties properties;
/** Configures from System properties **/
public static TProcessors create() throws IOException, JDOMException {
String home;
File config;
home = System.getProperty("xdav.home");
if (home == null) {
throw new IOException("xdav.home is not set!");
}
config = new File(home + File.separator + "testsuite" + File.separator + "junit" + File.separator + "tprocessor.xml");
return new TProcessors(config, System.getProperty("xdav.host"),
System.getProperty("xdav.port"), System.getProperty("xdav.user"),
System.getProperty("xdav.password"), System.getProperty("xdav.urlencoding"),
System.getProperty("xdav.tracingRequest", "none"),
System.getProperties());
}
/**
* Constructor
*/
public TProcessors (File config, String host, String port, String defaultUser,
String defaultPassword, String defaultUrlEncoding, String tracingRequest,
Properties properties)
throws IOException, JDOMException {
this.config = config;
this.host = host;
this.port = port;
this.defaultUser = defaultUser;
this.defaultPassword = defaultPassword;
this.defaultUrlEncoding = defaultUrlEncoding;
this.tracingRequest = tracingRequest;
this.properties = properties;
if (defaultUrlEncoding == null) {
defaultUrlEncoding = "UTF-8";
}
if (defaultUser == null) {
defaultUser = "guest";
}
if (defaultPassword == null) {
defaultPassword = "guest";
}
if (host == null) {
throw new IOException("xdav.host is not set!");
}
if (config == null) {
throw new IOException("config file is not set!");
}
if (port == null) {
throw new IOException("xdav.port is not set!");
}
// Set some defaults
startUp = new Hashtable();
startUp.put("host", host);
startUp.put("port", new Integer(port));
xdavConfiguration = new XConf(config);
}
/**
* main method
*/
public static void main(String[] args) {
if (!mainExecuter(args, null, null)) {
System.exit (-1);
}
}
/**
* main executer method to be called from outside
*/
public static boolean mainExecuter(String[] args, java.io.PrintStream xmlresult, int[] counters) {
TProcessors tp;
String stestName = "";
boolean result = true;
TArgs arg = new TArgs (args);
try {
tp = TProcessors.create();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
return false; // dummy
}
if(!tp.processStartUp( args )){
System.exit(-1);
}
if (arg.isOptionSet ("name")) {
stestName = arg.get ("name");
}
else {
return false;
}
if (!tp.executeTestCaseVerbose( new File (stestName), xmlresult, System.out )) {
result = false;
}
if (counters != null) {
counters[0] ++;
if (!result) counters[1] ++;
// System.out.println("$$$$$$$$$$$ processed cases " + counters[0]);
// System.out.println("$$$$$$$$$$$ processed cases err " + counters[1]);
// System.out.println("");
}
return result;
}
/**
* Process the initial args passed to the Class.<br>
* Currently this should consist of:<br>
*
* -host [the host to connect to]</br>
* -port [the port the host is running webdav on]<br>
*
* There are default set if anything is missing.<br>
*
* If all goes well, a session will be created and credentials set.
*/
private boolean processStartUp( String[] args ){
boolean ready = false;
TArgs arg = new TArgs (args);
if (arg.isOptionSet ("help")) {
printStartUsage();
return false;
}
if (arg.isOptionSet("host")){
startUp.put("host", arg.get("host"));
ready = true;
}
if(arg.isOptionSet("port")){
int val;
try {
val = Integer.parseInt( arg.get("port") );
}
catch ( NumberFormatException ne ) {
printStartUsage();
return false;
}
startUp.put("port", new Integer(val) );
ready = true;
}
if (arg.isOptionSet( "name" ) ){
ready = true;
}
return ready;
}
/**
* Print the commands options from startup
*/
private static void printStartUsage() {
System.out.println("XDAV Tprocessor Startup args:");
System.out.println(" -name <The name of testcase, full path should be given>");
System.out.println(" -host <host to connect to>");
System.out.println(" -port <post to conect on>");
System.out.println(" -help");
}
// -------------------------------------------------------- Private Methods
public boolean executeTestCaseVerbose(File testfile, PrintStream xmlresultPar, PrintStream verbose) {
boolean result;
verbose.println("");
verbose.println(new Date() + " Starting test case: " + testfile.getAbsolutePath());
try {
result = executeTestCase(testfile, xmlresultPar);
} catch (IOException e) {
e.printStackTrace(verbose);
result = false;
} catch (JDOMException e) {
e.printStackTrace(verbose);
result = false;
}
if (!result) {
verbose.println(new Date() + " FAILED test case: " + testfile.getAbsolutePath());
}
return result;
}
/**
* Construct a document (tree) out of given XML file. Execute testStep given in the
* file
* @param WeddavClient client, File
*/
public boolean executeTestCase(File testfile, PrintStream xmlresultPar) throws IOException, JDOMException {
long time = System.currentTimeMillis();
if (xmlresultPar != null){
this.xmlresult = new XMLOutput(xmlresultPar);
}
xmlresult.writeRootElementStart("testCase");
xmlresult.writeElement("fileName", testfile.getAbsolutePath());
try{
globalTestFileName = testfile.getName();
globalAbsolutePath = testfile.getParent();
// globalAbsolutePath = testfile.;
exceuteStepOrRepeater(new SAXBuilder(true).build(testfile).getRootElement().getChildren().iterator());
} catch (JDOMException e){
xmlresult.writeElement("domException", e.toString());
throw e;
}
xmlresult.writeElement("result", ((testElementsExecutedWithError!=0)?"ERROR":"Success"));
xmlresult.writeElement("time", ((System.currentTimeMillis() - time)));
xmlresult.writeElement("testElementCount", testElementsExecuted);
xmlresult.writeElement("testElementErrors", testElementsExecutedWithError);
xmlresult.writeRootElementEnd("testCase");
xmlresult.flush();
return testElementsExecutedWithError==0;
}
private boolean exceuteStepOrRepeater(Iterator items) throws IOException, JDOMException {
boolean result = true;
Vector threadsToExceute = new Vector(10);
Vector cleanUpThreads = new Vector(10);
result = exceuteStepOrRepeater(items, threadsToExceute, cleanUpThreads);
try {
// now execute all collected threads in parallel
for (int i = 0 ; i<threadsToExceute.size(); i++) {
((Thread)threadsToExceute.elementAt(i)).start();
}
for (int i = 0 ; i<threadsToExceute.size(); i++) {
((Thread)threadsToExceute.elementAt(i)).join();
}
// now do the clean up tasks
// now execute all collected threads in parallel
for (int i = 0 ; i<cleanUpThreads.size(); i++) {
((Thread)cleanUpThreads.elementAt(i)).start();
}
for (int i = 0 ; i<cleanUpThreads.size(); i++) {
((Thread)cleanUpThreads.elementAt(i)).join();
}
} catch (InterruptedException e) {
throw new IllegalStateException("unexpected InterruptedException");
}
return result;
}
private boolean exceuteStepOrRepeater(Iterator items, Vector threadsToExceute, Vector cleanUpThreads)
throws IOException, JDOMException {
HttpClientExtended client = new HttpClientExtended(defaultUser, defaultPassword);
return exceuteStepOrRepeater(items, threadsToExceute, cleanUpThreads, client);
}
private boolean checkCondition(Element conditionContainer, String condition) throws IOException {
if (condition == null) return false;
String evaluatedCondition = replaceKnownVariable(conditionContainer, condition, "x=x");
StringTokenizer expression = new StringTokenizer(evaluatedCondition, "=");
if (expression.countTokens() != 2) throw new IOException("Condition malformed: " + evaluatedCondition);
String leftSide = expression.nextToken();
String rightSide = expression.nextToken();
return leftSide.equals(rightSide);
}
private boolean exceuteStepOrRepeater(Iterator items, Vector threadsToExceute, Vector cleanUpThreads, HttpClientExtended client)
throws IOException, JDOMException
{
boolean result = true;
while(items.hasNext()){
Element item = (Element) items.next();
// System.out.println("**** Execute of Step Element: "+ item.getName());
if (item.getName().equals("step")){
if(!executeStep(item, client)){
result = false;
}
} else if(item.getName().equals("wait")){
try {
Thread.currentThread().sleep(new Long(item.getAttributeValue("time")).longValue());
} catch (InterruptedException e) {
throw new IllegalStateException("unexpected InterruptedException");
}
} else if(item.getName().equals("thread")){
threadsToExceute.add(new Thread(new Runner(item.getChildren().iterator(), Thread.currentThread()), "parallelThread-" + (threadsToExceute.size()+1)));
} else if(item.getName().equals("cleanup")){
cleanUpThreads.add(new Thread(new Runner(item.getChildren().iterator(), Thread.currentThread()), "cleanUpThread"));
} else if(item.getName().equals("repeater")){
String varName = "repeatCounter";
if (item.getAttribute("varDefinition") != null &&
!item.getAttributeValue("varDefinition").equals("") ) {
varName = item.getAttributeValue("varDefinition");
}
String condition = null;
if (item.getAttribute("condition") != null &&
!item.getAttributeValue("condition").equals("") ) {
condition = item.getAttributeValue("condition");
}
knownVariables.put(varName, "undefined");
int stackMarker = knownVariables.size();
long maximum = new Long(replaceKnownVariable(item, item.getAttribute("repeatCount").getValue(), "0")).longValue();
for (long i = 0; i < maximum && !checkCondition(item, condition); i++){
knownVariables.removeAllFramedVariables(stackMarker);
knownVariables.put(varName, new Long(i+1).toString());
result = exceuteStepOrRepeater(item.getChildren().iterator(), threadsToExceute, cleanUpThreads, client) && result;
}
} else if(item.getName().equals("specification")){
// do nothing in case of docu
} else {
System.out.println("#########################");
System.out.println("Illegal entry in XML = " + item.getName() );
System.out.println("Received response code = " + getElementString(item) );
System.out.println("#########################");
}
}
return result;
}
private void assignVariables(List varDefinitions ) throws IOException {
if (varDefinitions != null) {
Iterator iter = varDefinitions.iterator();
while (iter.hasNext()) {
Element element = (Element)iter.next();
if (element.getAttributeValue("varDefinition") != null)
knownVariables.put(element.getAttributeValue("varDefinition"), replaceKnownVariable(element));
}
}
}
/**
* Execute a given request for a testStep
* @param Element
*/
private boolean executeStep(Element elt, HttpClientExtended client ) throws IOException, JDOMException {
boolean result = false;
long executionTime = 0;
HttpMethod method = null;
// initialise user and password
knownVariables.put("user", defaultUser);
knownVariables.put("password", defaultPassword);
assignVariables(elt.getChildren("assign"));
String user = replaceKnownVariable(elt.getChild("user"), defaultUser);
String password = replaceKnownVariable(elt.getChild("password"), defaultPassword);
// set user and password to the computed values
knownVariables.put("user", user);
knownVariables.put("password", password);
// create a new client, iff the user id has changed, else use the current HttpClient
if (!client.getUser().equals(user)) {
client = new HttpClientExtended(user, password);
}
// System.out.println("############### user " + user);
// System.out.println("############### pwd " + password);
xmlresult.writeElementStart("exceuteStep");
try{
method = executeRequest(elt.getChild("request"));
if (method == null) {
System.out.println("#########################");
System.out.println("Method pointer is null = " + getElementString(elt.getChild("request")) );
System.out.println("#########################");
return false;
}
xmlresult.writeElement("method", method.getName());
xmlresult.writeElement("url", URIUtil.encodePath(method.getPath(),"UTF-8"));
method.setRequestHeader("User-Agent", "Jakarta Slide TProcessor " + URIUtil.encodePath(globalTestFileName,"UTF-8"));
final int MAX = 50;
int i;
for (i = 0; true; i++) {
try {
long time = System.currentTimeMillis();
client.executeMethod(method);
executionTime = (System.currentTimeMillis() - time);
break;
}
catch (java.net.ConnectException e) {
if (i == MAX) {
System.out.println("connect failed: ");
System.out.println(" name=" + method.getName());
System.out.println(" uri=" + method.getURI());
System.out.println(" user=" + user);
System.out.println(" password=" + password);
throw e;
} else {
if (i > 1) {
System.out.println(Thread.currentThread().getName() + ": retry connection " + i + " out of " + MAX);
}
try {
Thread.currentThread().sleep(i*i);
} catch( InterruptedException x ) {}
client = new HttpClientExtended(user, password); // the old client might be brocken
continue;
}
}
}
// System.out.println("Status Code "+ m.getStatusCode());
// System.out.println("Status Text "+ m.getStatusText());
// if (method instanceof PropFindMethod) {
// System.out.println("###################");
// System.out.println("###################");
// System.out.println("###################");
// if (((PropFindMethod)method).getResponseDocument() != null) System.out.println("body " + getElementString(((PropFindMethod)method).getResponseDocument().getDocumentElement()));
// System.out.println("###################");
// System.out.println("###################");
// System.out.println("###################");
// }
fillVariables(method, elt.getChild("response"));
result = (responseAssert(method, elt));
method.releaseConnection();
} catch (JDOMException e) {
xmlresult.writeException(e);
throw e;
} catch (IOException e) {
xmlresult.writeException( e );
throw e;
}
if (!result) testElementsExecutedWithError ++;
testElementsExecuted ++;
xmlresult.writeElement("result", (!result?"ERROR":"Success"));
xmlresult.writeElement("time", (executionTime));
xmlresult.writeElementEnd("exceuteStep");
return result;
}
/**
* Constructs from request the method associated to the given request
* @param Element
*/
private HttpMethod executeRequest(Element request) throws IOException {
HttpMethod method = null;
List list = request.getChildren();
Iterator items = list.iterator();
while(items.hasNext()){
Element item = (Element) items.next();
if(item.getName().equals("command")){
method = fillMethodName(item, method);
}
else if(item.getName().equals("header")){
method = fillHeader(item, method);
} else if(item.getName().equals("body")){
method = fillBody(item, method);
}
}
return method;
}
/**
* This method is used to replace variables in a element
* @param element the element to replacement should be applied
* @return String the value of the element, with all applied replacements, if element is null return null
*/
private String replaceKnownVariable(Element element) throws IOException {
return replaceKnownVariable(element, null);
}
/**
* This method checks if a name points to a valid file
* @param fileName
* @return true if the file name is valid
*/
private boolean checkFileName(String name){
// System.out.println("Checking " + name + " = " + new File(name).isFile());
return new File(name).isFile();
}
/**
* This method returns the name of a valid file
* @param name is the possibly unqualified file name
* @return return name, if the unqualified File exists, else qualify the name
*/
private String getFileReferenceName(Element name){
String result = null;
String fileName = name.getAttributeValue("fileReference");
if (fileName != null && fileName.length() > 1) {
result = getFileReferenceName(replaceKnownVariable(name, fileName, fileName));
}
return result;
}
/**
* This method returns the name of a valid file
* @param name is the possibly unqualified file name
* @return return name, if the unqualified File exists, else qualify the name
*/
private String getFileReferenceName(String name){
String result = name;
if (globalAbsolutePath != null) {
if (checkFileName(name)) {
result = name;
} else if (checkFileName(globalAbsolutePath+File.separatorChar+name)) {
result = globalAbsolutePath+File.separatorChar+name;
}
}
return result;
}
/**
* This method returns the name of a valid file
* @param name is the possibly unqualified file name
* @return return name, if the unqualified File exists, else qualify the name
*/
private String getFileEncoding(Element name){
String result = name.getAttributeValue("fileEncoding");
if (result == null || result.equals("")) result = "UTF-8";
return result;
}
/**
* This method is used to replace variables in a string
* @param element the element to replacement should be applied
* @param defaultValue if element is null, return this default
* @return String the value of the element, with all applied replacements, if element is null return defaultValue
*/
private String getBodyValue(Element body) throws IOException {
String result = body.getText();
String fileName = getFileReferenceName(body);
if (fileName != null) {
Reader input = new BufferedReader(
new InputStreamReader(
new FileInputStream(fileName), getFileEncoding(body)));
StringWriter output = new StringWriter();
char[] buffer = new char[1024];
int numberOfBytesRead;
while ((numberOfBytesRead=input.read(buffer)) > 0) {
output.write (buffer, 0, numberOfBytesRead);
}
result = output.toString();
input.close();
output.close();
}
return result;
}
/**
* This method is used to replace variables in a string
* @param element the element to replacement should be applied
* @param defaultValue if element is null, return this default
* @return String the value of the element, with all applied replacements, if element is null return defaultValue
*/
private String replaceKnownVariable(Element element, String defaultValue) throws IOException {
if (element == null) return defaultValue;
return replaceKnownVariable(element, getBodyValue(element), defaultValue);
}
/**
* This method is used to replace variables in a string. If a variable value uses other variables
* those variables are subsituted too.
* @param element the element containing variable definitions
* @param line the input line the replacement should be applied
* @param defaultValue if element is null, return this default
* @return String the value of the element, with all applied replacements, if element is null return defaultValue
*/
private String replaceKnownVariable(Element element, String line, String defaultValue){
if (element == null) return defaultValue;
if (element.getAttributeValue("varUsage") != null && !element.getAttributeValue("varUsage").equals("")){
if (element.getAttributeValue("varUsage").indexOf(",") == (-1)) {
String varName = "varUsage"; // default
line = replace(line, "%"+varName+"%", computeVarValue(element, element.getAttributeValue("varUsage")));
varName = element.getAttributeValue("varUsage"); // real name
line = replace(line, "%"+varName+"%", computeVarValue(element, varName));
} else {
StringTokenizer varNames = new StringTokenizer(element.getAttributeValue("varUsage"), ",");
while (varNames.hasMoreElements()) {
String varName = (String)varNames.nextElement();
line = replace(line, "%"+varName+"%", computeVarValue(element, varName));
}
}
}
return line;
}
/**
* This method is used to replace variables in a string. If a variable value uses other variables
* those variables are NOT subsituted.
* @param element the element containing variable definitions
* @param line the input line the replacement should be applied
* @param defaultValue if element is null, return this default
* @return String the value of the element, with all applied replacements, if element is null return defaultValue
*/
private String doReplaceKnownVariable(Element element, String line, String defaultValue){
if (element == null) return defaultValue;
if (element.getAttributeValue("varUsage") != null && !element.getAttributeValue("varUsage").equals("")){
if (element.getAttributeValue("varUsage").indexOf(",") == (-1)) {
String varName = "varUsage"; // default
line = replace(line, "%"+varName+"%", knownVariables.get(element.getAttributeValue("varUsage")));
varName = element.getAttributeValue("varUsage"); // real name
line = replace(line, "%"+varName+"%", knownVariables.get(varName));
} else {
StringTokenizer varNames = new StringTokenizer(element.getAttributeValue("varUsage"), ",");
while (varNames.hasMoreElements()) {
String varName = (String)varNames.nextElement();
line = replace(line, "%"+varName+"%", knownVariables.get(varName));
}
}
}
return line;
}
/**
* This method computes for a given variable name the value. If the value contains
* additional variable references, these are resolved to their values
* @param element the element containing variable definitions
* @param varName the name of the variable
* @return value of the variable
*/
public String computeVarValue(Element element, String varName){
String result = knownVariables.get(varName);
if (result != null && result.indexOf("%") != -1 && result.indexOf("%", result.indexOf("%")+1) != -1) {
result = doReplaceKnownVariable(element, result, result);
}
return result;
}
/**
* This method is used to replace variables in a string
* @param line the string which will be modified
* @param pattern search string to be replaced
* @param value value of the replace string
* @return value of line, with all applied replacements
*/
public static String replace(String line, String pattern, String value){
while (line.indexOf(pattern) != -1){
line = line.substring(0, line.indexOf(pattern)) +
value +
line.substring(line.indexOf(pattern) + pattern.length());
}
// System.out.println("#### Replaced " + pattern + " with " + value + " --> " + line);
return line;
}
/**
* This method is used to find out the name of the Resquest Method
* @param List
*/
private HttpMethod fillMethodName(Element methodElement, HttpMethod method)
throws IOException {
StringTokenizer st = new StringTokenizer(replaceKnownVariable(methodElement));
method = createHttpMethod(st.nextToken(), st.nextToken());
method.setRequestHeader("Content-Length", "0");
return method;
}
/**
* This method is used to set the Header in request Method
* @param List
*/
private HttpMethod fillHeader (Element header, HttpMethod method) throws IOException {
Header headerToSet = getResponseHeader(header);
String name = headerToSet.getName();
String value = headerToSet.getValue();
if (name.equalsIgnoreCase("destination")) {
value = URIUtil.encodePath(value, "utf-8");
}
method.setRequestHeader(name, value);
return method;
}
private boolean binaryReadRequest(Element element) {
String fileReference = getFileReferenceName(element);
String fileEncoding = element.getAttributeValue("fileEncoding");
boolean result = (fileReference != null) &&
(fileEncoding == null || fileEncoding.equals("binary"));
return result;
}
/**
* This method is used to set the Header in request Method
*/
private HttpMethod fillBody (Element element, HttpMethod method) throws IOException {
if (binaryReadRequest(element)) {
File input = new File(getFileReferenceName(element));
if (!input.exists()) throw new IOException("File " + getFileReferenceName(element) + " does not exist");
method.setRequestHeader("Content-Length", ""+input.length());
if (method instanceof HttpRequestBodyMethodBase) {
((HttpRequestBodyMethodBase)method).setRequestBody(input);
} else if (method instanceof PutMethod) {
((PutMethod)method).setRequestBody(new FileInputStream(input));
}
}
else {
try {
String source = replaceKnownVariable(element);
byte[] input = source.getBytes(getFileEncoding(element));
// System.out.println("##### encoding " + getFileEncoding(element));
// System.out.println("##### length " + input.length);
// System.out.println("##### data " + source);
method.setRequestHeader("Content-Length", ""+input.length);
if (method instanceof HttpRequestBodyMethodBase) {
((HttpRequestBodyMethodBase)method).setRequestBody(input);
} else if (method instanceof PutMethod) {
((PutMethod)method).setRequestBody(new ByteArrayInputStream(input));
}
}
catch (UnsupportedEncodingException e) {
throw new IOException(e.toString());
}
}
return method;
}
/**
* This method is used to return body as String
* @param String
*/
public boolean responseAssert (HttpMethod m, Element elt) throws IOException, JDOMException {
boolean firstPart = false;
boolean secondPart = false;
Iterator header = responseHeader(elt.getChild("response"));
List expectedResponseCodes = responseStatus(elt.getChild("response").getChildText("command"));
if (expectedResponseCodes != null && !expectedResponseCodes.contains(new Integer(m.getStatusCode()))) {
xmlresult.writeElementStart("responseError");
xmlresult.writeElement("receivedValue", WebdavStatus.getStatusText(m.getStatusCode()) +
" " + m.getStatusCode());
xmlresult.writeElement("expectedValue", getStatusText(expectedResponseCodes) +
" " + expectedResponseCodes);
xmlresult.writeElementEnd("responseError");
if (m instanceof XMLResponseMethodBase && m.getStatusCode()==207 ) {
System.out.println("#################");
System.out.println(getElementString(((XMLResponseMethodBase)m).getResponseDocument().getDocumentElement()));
System.out.println("#################");
}
return false;
}
// a received response code of 404 will not compare the headers
ResponseBodyAssert methodAssert = assertFactory(m, elt, expectedResponseCodes);
secondPart = (m.getStatusCode() == 404 && expectedResponseCodes != null &&
expectedResponseCodes.size() != 1 &&
expectedResponseCodes.contains(new Integer(404)))
||
responseHeaderAssert(m, elt, header);
firstPart = (methodAssert!=null)?methodAssert.assertResponseBody():true;
return ( firstPart && secondPart);
}
/**
* This method is used to set the Header in request Method
* @param List
*/
private String getStatusText (List responseCodes){
String result = "";
Iterator iter = responseCodes.iterator();
while (iter.hasNext()) {
result = result + " " + WebdavStatus.getStatusText(((Integer)iter.next()).intValue());
}
return result;
}
/**
* This method is used to set the Header in request Method
* @param String
*/
private Header getResponseHeader (String headerString){
Header result = new Header();
String name;
String value;
StringTokenizer st = new StringTokenizer(headerString);
int size = st.nextToken().length();
name = headerString.substring(0,size-1);
if (size >= headerString.length()) {
value = "";
} else {
value = headerString.substring(size+1);
}
value = value.trim();
result.setName(name);
result.setValue(value);
return result;
}
/**
* This method is used to set the Header in request Method
* @param Element
*/
private Header getResponseHeader (Element headerElement) throws IOException {
return getResponseHeader(replaceKnownVariable(headerElement));
}
/**
* This method is used to return body as String
* @param String
*/
private boolean responseHeaderAssert(HttpMethod m, Element elt, Iterator header) {
return verifyHeader(xdavConfiguration.getPropertyList ("excludedHeaderProperties", m.getName()), m, header);
}
/**
* This method is used to check if all the given headers are returned by the WebDav method
* @param String
*/
private boolean verifyHeader(List allowHeaders, HttpMethod m, Iterator header){
boolean result = true;
while (header.hasNext()){
Header headToMatch = (Header) header.next();
boolean oneHeaderMatched = allowHeaders.contains(headToMatch.getName()) || // head to be compared
verifyOneHeader(headToMatch, m.getResponseHeader(headToMatch.getName())); // compare it
if (!oneHeaderMatched){
if (result) {
xmlresult.writeElementStart("headerErrors");
}
if (m.getResponseHeader(headToMatch.getName()) == null){
xmlresult.writeElement("nonExistingHeader", "name", headToMatch.getName(), headToMatch.getValue().trim());
}
else{
xmlresult.writeElementStart("nonMatchingHeader", "name", headToMatch.getName());
xmlresult.writeElement("expectedValue", headToMatch.getValue().trim());
xmlresult.writeElement("receivedValue", m.getResponseHeader(headToMatch.getName()).getValue().trim());
xmlresult.writeElementEnd("nonMatchingHeader");
}
}
result = result && oneHeaderMatched;
}
if (!result) {
xmlresult.writeElementEnd("headerErrors");
}
return result;
}
private boolean verifyOneHeader(Header expected, Header received){
boolean result = false;
result = received != null &&
(expected.getValue().equals("*") ||
compareOneHeader(expected, received));
return result;
}
private boolean compareOneHeader(Header expected, Header received){
boolean result = false;
if (expected.getName().equals("Allow") || expected.getName().equals("DAV")) {
result = compareCommaSeperatedListHeader(expected, received);
} else {
result = received.getValue().equalsIgnoreCase(expected.getValue());
}
return result;
}
private boolean compareCommaSeperatedListHeader(Header expected, Header received){
boolean result = false;
HashSet expList = tokeniseCommaList(expected.getValue());
HashSet recList = tokeniseCommaList(received.getValue());
if (!expList.contains("*")) {
// no wildcard ==> lists must be identical
result = expList.equals(recList);
} else {
// wildcard ==> expected must be completely contained in received
expList.remove("*");
result = recList.containsAll(expList);
}
return result;
}
private HashSet tokeniseCommaList(String value){
HashSet result = new HashSet();
StringTokenizer iter = new StringTokenizer(value, ",");
while (iter.hasMoreElements()) {
String element = ((String)iter.nextElement()).trim();
result.add(element);
}
return result;
}
private Iterator responseHeader(Element response) throws IOException {
ArrayList result = new ArrayList();
Iterator iter = response.getChildren("header").iterator();
while (iter.hasNext()){
Element headerElement = (Element)iter.next();
result.add(getResponseHeader(headerElement));
}
return result.iterator();
}
public static List responseStatus (String response){
List result = new ArrayList();
if (response.equals("*")) return null;
StringTokenizer st = new StringTokenizer(response);
st.nextToken(); // ignore the first 'http' element
String resonseString = st.nextToken();
if (resonseString.equals("*")) return null;
if (!resonseString.startsWith("(")) result.add(new Integer(resonseString));
if (resonseString.startsWith("(")) {
StringTokenizer responseCodes = new StringTokenizer(resonseString, ",");
while (responseCodes.hasMoreElements()) {
String element = (String)responseCodes.nextElement();
if (element.startsWith("(")) element = element.substring(1, element.length());
if (element.endsWith(")")) element = element.substring(0, element.length()-1);
if (!element.startsWith(")")) result.add(new Integer(element));
}
}
return result;
}
//
/**
*
*/
public static String getElementString (org.w3c.dom.Element e) {
return getElementString(new org.jdom.input.DOMBuilder().build(e));
}
/**
*
*/
public static String getElementString (Element e) {
XMLOutputter out = new XMLOutputter(org.jdom.output.Format.getPrettyFormat());
if (e == null) {
return "null";
} else {
return out.outputString(e);
}
}
/**
* Extract from expected response it body
*/
protected Element getElementFromString(String input) throws IOException, JDOMException {
if (input == null) return null;
input = input.trim();
if (input.equals("")) return null;
return (new SAXBuilder().build(new StringReader(input))).getRootElement();
}
/**
*
*/
private void fillVariables (HttpMethod m, Element responseElement) {
fillSpecifiedCommandHeaderVariable(m, responseElement);
if (m instanceof XMLResponseMethodBase){
fillAutomatedVariables((XMLResponseMethodBase)m);
fillSpecifiedVariable((XMLResponseMethodBase)m, responseElement.getChild("body"));
}
}
/**
*
*/
private void fillSpecifiedCommandHeaderVariable (HttpMethod m, Element responseElement) {
if (responseElement == null) return; // no response, nothing to fill
// fill the command variable, if present
String varName = responseElement.getChild("command").getAttributeValue("varDefinition");
if (varName != null && !varName.trim().equals("")) {
String responseCode = new Integer(m.getStatusCode()).toString();
knownVariables.put(varName, responseCode);
}
// fill the header variable, if present
Iterator iter = responseElement.getChildren("header").iterator();
while (iter.hasNext()) {
Element headerElement = (Element)iter.next();
varName = headerElement.getAttributeValue("varDefinition");
if (varName != null && !varName.trim().equals("")) {
String headerName = getResponseHeader(headerElement.getText()).getName();
Header h = m.getResponseHeader(headerName);
String varValue ;
if (h != null) varValue = h.getValue();
else varValue = "header " + headerName + " not found";
knownVariables.put(varName, varValue);
}
}
}
/**
*
*/
private void fillSpecifiedVariable (XMLResponseMethodBase m, Element body) {
if (body == null) return; // no body, nothing to fill
String searchPattern = body.getAttributeValue("varPath");
String varName = body.getAttributeValue("varDefinition");
if ((searchPattern != null) && (varName != null) && m.getResponseDocument() != null){
String varValue = "";
Iterator iter = findElementList(getMethodElement(m), searchPattern).iterator();
while (iter.hasNext()) {
varValue = ((Element)iter.next()).getText();
}
knownVariables.put(varName, varValue); // store only the very last ocuurence
}
}
/**
*
*/
private void fillAutomatedVariables (XMLResponseMethodBase m) {
List possible = xdavConfiguration.getPropertyList("automatedVariables", m.getName());
Iterator iter = possible.iterator();
while (iter.hasNext()){
String searchPattern = (String)iter.next();
if (((XMLResponseMethodBase)m).getResponseDocument() != null){
fillAutomatedVariables(findElementList(getMethodElement(m), searchPattern));
}
}
}
private void fillAutomatedVariables (List valueList) {
Iterator iter = valueList.iterator();
while (iter.hasNext()){
Element e = ((Element)iter.next());
String varName = "automaticVariable" + (knownVariables.size()-2);
String varValue = e.getText();
knownVariables.put(varName, varValue);
}
}
private Element getMethodElement(XMLResponseMethodBase m) {
return new org.jdom.input.DOMBuilder().build(m.getResponseDocument().getDocumentElement());
}
private List findElementList (Element rootElement, String key) {
List result = new ArrayList();
if (key == null || key.equals("")) return result;
if (rootElement.getName().equals(key)) {
Element e = rootElement;
if (key.equals("href")) {
e = (Element)e.clone();
try {e.setText(URIUtil.decode(e.getText(), defaultUrlEncoding));} catch (Exception ex) { }
}
result.add(e);
return result;
}
if (key.indexOf("/") == -1) return result;
String head = key.substring(0, key.indexOf("/"));
String tail = key.substring(key.indexOf("/")+1);
String child = null;
// System.out.println("@@@@@@@@@ xml " + rootElement.getName());
if (!rootElement.getName().equals(head)) {
return result;
}
if (tail.indexOf("/") == (-1)){
child = tail;
}
else{
child = tail.substring(0, tail.indexOf("/"));
}
// System.out.println("@@@@@@@@@ head " + head);
// System.out.println("@@@@@@@@@ child " + child);
// System.out.println("@@@@@@@@@ tail " + tail);
Iterator iter = rootElement.getChildren().iterator();
while (iter.hasNext()){
Element e = (Element)iter.next();
if (e.getName().equals(child))
result.addAll(findElementList(e, tail));
}
return result;
}
private Element expectedResponseAsDOM(Element expectedResponse) throws IOException, JDOMException {
return getElementFromString(expectedResponseAsString(expectedResponse));
}
private InputStream expectedResponseAsStream(Element element) throws IOException {
Element expectedResponse = element.getChild("response").getChild("body");
if (expectedResponse == null) return null;
InputStream result = null;
if (binaryReadRequest(expectedResponse)) {
result = new FileInputStream(getFileReferenceName(expectedResponse));
}
else {
result = new ByteArrayInputStream(
replaceKnownVariable(expectedResponse).getBytes(
getFileEncoding(element)));
}
return result;
}
private String expectedResponseAsString(Element expectedResponse) throws IOException {
if (expectedResponse.getChild("response").getChild("body") != null) {
return replaceKnownVariable(expectedResponse.getChild("response").getChild("body"));
}
return null;
}
private ResponseBodyAssert assertFactory(HttpMethod m, Element expectedResponseElement, List expectedResponseCodes)
throws IOException, JDOMException {
// check for the wildcard
String expectedResponseString = expectedResponseAsString(expectedResponseElement);
if (expectedResponseString == null || expectedResponseString.equals("*")) return null;
ResponseBodyAssert result = null;
if(m instanceof PropFindMethod){
result = new PropfindAssert((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof SearchMethod){
boolean sortingRequired = true;
if (expectedResponseElement.getChild("response").getChild("body") != null &&
expectedResponseElement.getChild("response").getChild("body").getAttributeValue("nosorting") != null &&
expectedResponseElement.getChild("response").getChild("body").getAttributeValue("nosorting").equalsIgnoreCase("true")) {
sortingRequired = false;
}
result = new SearchAssert((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes, sortingRequired);
} else if (m instanceof LockMethod){
result = new LockAssert((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof PropPatchMethod){
result = new PropPatchAssert((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof DeleteMethod){
result = new DeleteAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof MoveMethod){
result = new MoveAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof CopyMethod){
result = new CopyAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof AclMethod){
result = new AclAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof CheckinMethod){
result = new CheckinAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof CheckoutMethod){
result = new CheckoutAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof MkWorkspaceMethod){
result = new MkWorkspaceAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof LabelMethod){
result = new LabelAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof ReportMethod){
result = new ReportAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof UncheckoutMethod){
result = new UncheckoutAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof VersionControlMethod){
result = new VersionControlAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof UpdateMethod){
result = new UpdateAssert ((XMLResponseMethodBase) m, expectedResponseAsDOM(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else if (m instanceof GetMethod) {
if (m.getResponseHeader("Content-Type") == null || !m.getResponseHeader("Content-Type").getValue().trim().startsWith("text/xml")) {
result = new GetAssert ( m, expectedResponseAsStream(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
} else {
result = new GetXMLAssert ( m, expectedResponseAsStream(expectedResponseElement), xdavConfiguration, xmlresult, expectedResponseCodes);
}
} else if (m instanceof PollMethod) {
result = new PollAssert((XMLResponseMethodBase) m,
expectedResponseAsDOM(expectedResponseElement),
xdavConfiguration, xmlresult, expectedResponseCodes);
}
return result;
}
/**
* Factory method to return a method object based on the methodName.
* If the method name is not known, null is returned
*/
public static HttpMethod createHttpMethod(String methodName) throws IOException {
HttpMethod result = null;
if (methodName.equalsIgnoreCase("COPY")){
result = new CopyMethod();
}
else if(methodName.equalsIgnoreCase("BIND")) {
result = new BindMethod();
}
else if(methodName.equalsIgnoreCase("REBIND")) {
result = new RebindMethod();
}
else if(methodName.equalsIgnoreCase("UNBIND")) {
result = new UnbindMethod();
}
else if(methodName.equalsIgnoreCase("DELETE")){
result = new DeleteMethod();
}
else if(methodName.equalsIgnoreCase("GET")){
result = new GetMethod();
}
else if(methodName.equalsIgnoreCase("HEAD")){
result = new HeadMethod();
}
else if(methodName.equalsIgnoreCase("LOCK")){
result = new LockMethod();
}
else if(methodName.equalsIgnoreCase("MKCOL")){
result = new MkcolMethod();
}
else if(methodName.equalsIgnoreCase("MOVE")){
result = new MoveMethod();
}
else if(methodName.equalsIgnoreCase("LABEL")){
result = new LabelMethod();
}
else if(methodName.equalsIgnoreCase("OPTIONS")){
result = new OptionsMethod();
}
else if(methodName.equalsIgnoreCase("POST")){
result = new PostMethod();
}
else if(methodName.equalsIgnoreCase("PROPFIND")){
result = new PropFindMethod();
}
else if(methodName.equalsIgnoreCase("SEARCH")){
result = new SearchMethod();
}
else if(methodName.equalsIgnoreCase("PROPPATCH")){
result = new PropPatchMethod();
}
else if(methodName.equalsIgnoreCase("PUT")){
result = new PutMethod();
}
else if(methodName.equalsIgnoreCase("POST")){
result = new PostMethod();
}
else if(methodName.equalsIgnoreCase("UNLOCK")){
result = new UnlockMethod();
}
else if(methodName.equalsIgnoreCase("ACL")){
result = new AclMethod();
}
else if(methodName.equalsIgnoreCase("CHECKIN")){
result = new CheckinMethod();
}
else if(methodName.equalsIgnoreCase("CHECKOUT")){
result = new CheckoutMethod();
}
else if(methodName.equalsIgnoreCase("MKWORKSPACE")){
result = new MkWorkspaceMethod();
}
else if(methodName.equalsIgnoreCase("REPORT")){
result = new ReportMethod();
}
else if(methodName.equalsIgnoreCase("UNCHECKOUT")){
result = new UncheckoutMethod();
}
else if(methodName.equalsIgnoreCase("VERSION-CONTROL")){
result = new VersionControlMethod();
}
else if(methodName.equalsIgnoreCase("UPDATE")){
result = new UpdateMethod();
}
else if(methodName.equalsIgnoreCase("SUBSCRIBE")){
result = new SubscribeMethod();
}
else if(methodName.equalsIgnoreCase("UNSUBSCRIBE")){
result = new UnsubscribeMethod();
}
else if(methodName.equalsIgnoreCase("POLL")){
result = new PollMethod();
}
if (result == null)
throw new IOException("Method " + methodName + " does not exist");
result.setFollowRedirects(true);
return result;
}
/**
* Factory method to return a method object based on the methodName.
* If the method name is not known, null is returned
*/
public static HttpMethod createHttpMethod(String methodName, String path) throws IOException {
HttpMethod result = createHttpMethod(methodName);
if (result != null){
result.setPath(URIUtil.encodePath(path, "utf-8"));
}
return result;
}
/**************************************************************/
/* Inner class to help the thread to execute the function */
/**************************************************************/
public class Runner implements Runnable{
Iterator items;
String name;
HashtableStack varsToBeUsed;
public Runner(Iterator items, Thread varsToBeUsed) {
this.items = items;
this.name = varsToBeUsed.getName();
this.varsToBeUsed = new HashtableStack(knownVariables.getEnvironment(varsToBeUsed));
}
public void run() {
knownVariables.createNewEnvironment(varsToBeUsed, name);
try {
exceuteStepOrRepeater(items);
}
catch (JDOMException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
};
knownVariables.removeEnvironment();
}
}
/**************************************************************/
/* Inner class to contain all variable sorted by thread name */
/**************************************************************/
private class KnownVariablesHashtable {
private Hashtable knownVarsByThread = new Hashtable();
public String get(String key) {
String result = "";
if (key.startsWith("globalVariable") ||
key.equals("host")||
key.equals("port")||
key.equals("workdb")||
key.equals("workhost") ) {
return properties.getProperty("xdav." + key, "");
}
else {
HashtableStack vars = (HashtableStack)knownVarsByThread.get(Thread.currentThread().getName());
if (vars != null){
result = (String)vars.get(key);
}
}
if (tracingRequest.indexOf("var") != (-1)) System.out.println("***VAR reading " + key + " = " + result + " in Thread " + Thread.currentThread().getName());
return result;
}
public void put(String key, String value) {
getEnvironment().put(key, value);
if (tracingRequest.indexOf("var") != (-1)) System.out.println("***VAR setting " + key + " = " + value + " in Thread " + Thread.currentThread().getName());
}
public int size() {
return getEnvironment().size()+1;
}
public void removeAllFramedVariables(int stackMarker) {
if (size() <= stackMarker) return;
int max = size();
for (int i = stackMarker; i <= max; i++) {
getEnvironment().pop();
}
}
public HashtableStack createNewEnvironment(HashtableStack varsToBeUsed, String name) {
HashtableStack vars;
if (varsToBeUsed != null) {
vars = new HashtableStack(varsToBeUsed);
} else {
vars = new HashtableStack();
}
knownVarsByThread.put(Thread.currentThread().getName(), vars);
if (tracingRequest.indexOf("var") != (-1)) System.out.println("***********Frame("+knownVarsByThread.size()+"): created new Variable frame for " + Thread.currentThread().getName() + " based on " + name);
return vars;
}
public void removeEnvironment() {
knownVarsByThread.remove(Thread.currentThread().getName());
if (tracingRequest.indexOf("var") != (-1)) System.out.println("***********Frame("+knownVarsByThread.size()+"): removed Variable frame for " + Thread.currentThread().getName() );
}
public HashtableStack getEnvironment(Thread scope) {
HashtableStack vars = (HashtableStack)knownVarsByThread.get(scope.getName());
if (vars == null){
vars = createNewEnvironment(null, scope.getName());
}
return vars;
}
private HashtableStack getEnvironment() {
return getEnvironment(Thread.currentThread());
}
}
/**************************************************************/
/* Inner class to have a HashMap act as a stack too */
/**************************************************************/
private class HashtableStack extends Hashtable {
private Stack stack = new Stack();
public HashtableStack() {
super();
}
public HashtableStack(Hashtable initValues) {
super.putAll(initValues);
}
public Object put(Object key, Object value) {
if (super.get(key) == null) {
stack.push(key);
}
return super.put(key, value);
}
public Object pop() {
if (tracingRequest.indexOf("var") != (-1)) System.out.println("***VAR removing " + stack.peek() + " = " + super.get(stack.peek()) + " in Thread " + Thread.currentThread());
return super.remove(stack.pop());
}
}
/**************************************************************/
/* Inner class to have some more function on HttpClient */
/**************************************************************/
private class HttpClientExtended extends HttpClient {
private String user = null;
public void setUser(String user) {
this.user = user;
}
public String getUser() {
return user;
}
private HttpClientExtended (String user, String password){
super();
// System.out.println("####### " + Thread.currentThread().getName() + " : Creating client " + user);
setUser(user);
WebdavState state = new WebdavState();
Credentials cred = new UsernamePasswordCredentials(user, password);
// state.setURLDecodingCharset(defaultUrlEncoding);
// state.setURLEncodingCharset(defaultUrlEncoding);
startSession((String)startUp.get("host"),
((Integer)startUp.get("port") ).intValue());
state.setCredentials(null, cred);
state.setAuthenticationPreemptive(true); // avoid non-authenticated method invocation
setState(state);
}
}
}