gt: 					if ( srvUser == null)
context: /*
   * Copyright (C) 2006-2010 Alfresco Software Limited.
   *
   * This file is part of Alfresco
   *
   * Alfresco is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * Alfresco is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.alfresco.jlan.test.cluster;
  
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  
  import org.alfresco.jlan.debug.DebugConfigSection;
  import org.alfresco.jlan.server.config.InvalidConfigurationException;
  import org.springframework.extensions.config.ConfigElement;
  import org.springframework.extensions.config.element.GenericConfigElement;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  import org.xml.sax.InputSource;
  
  /**
   * Cluster Test Configuration Class
   *
   * @author gkspencer
   */
  public class TestConfiguration {
  
  	// Constants
  	//
  	// Node type for an Element
  
  	private static final int ELEMENT_TYPE = 1;
  
  	// Maximum number of threads per server
  	
  	public static final int MaximumThreadsPerServer		=	25;
  	
  	// Test classes
  	
  	private static final String[][] _testClasses = {{ "createFile", 		"org.alfresco.jlan.test.cluster.CreateFileTest"},
  									   				{ "createFolder", 		"org.alfresco.jlan.test.cluster.CreateFolderTest"},
  									   				{ "oplockGrant", 		"org.alfresco.jlan.test.cluster.OplockGrantTest"},
  									   				{ "oplockBreak", 		"org.alfresco.jlan.test.cluster.OplockBreakTest"},
  									   				{ "deleteFile", 		"org.alfresco.jlan.test.cluster.DeleteFileTest"},
  									   				{ "deleteFolder", 		"org.alfresco.jlan.test.cluster.DeleteFolderTest"},
  									   				{ "openFile", 			"org.alfresco.jlan.test.cluster.OpenFileTest"},
  									   				{ "openFileSharedRead", "org.alfresco.jlan.test.cluster.OpenFileShareReadTest"},
  									   				{ "byteRangeLocking", 	"org.alfresco.jlan.test.cluster.ByteRangeLockingTest"},
  									   				{ "renameFile", 		"org.alfresco.jlan.test.cluster.RenameFileTest"},
  									   				{ "renameFolder", 		"org.alfresco.jlan.test.cluster.RenameFolderTest"},
  									   				{ "writeFileSequential","org.alfresco.jlan.test.cluster.WriteSequentialTest"},
  									   				{ "writeFileRandom", 	"org.alfresco.jlan.test.cluster.WriteRandomTest"},
  									   				{ "folderSearch", 		"org.alfresco.jlan.test.cluster.FolderSearchTest"},
  									   				{ "changeNotify", 		"org.alfresco.jlan.test.cluster.ChangeNotifyTest"},
  									   				{ "NTCreateFile",		"org.alfresco.jlan.test.cluster.NTCreateFileTest"},
  									   				{ "perfFilesPerFolder", "org.alfresco.jlan.test.cluster.PerfFilesPerFolderTest"},
  									   				{ "perfFolderTree",		"org.alfresco.jlan.test.cluster.PerfFolderTreeTest"},
  									   				{ "perfDataTransfer",	"org.alfresco.jlan.test.cluster.PerfDataTransferTest"},
  									   				{ "oplockLeak",			"org.alfresco.jlan.test.cluster.OplockLeakTest"},
  									   				{ "oplockLevelII",		"org.alfresco.jlan.test.cluster.OplockBreakLevelIITest"},
  									   				{ "attributesOnlyOplock","org.alfresco.jlan.test.cluster.AttributesOnlyOplockGrantTest"}
  	};
  
  	// List of remote servers
  	
  	private List<TestServer> m_serverList;
  	
  	// List of tests
  	
  	private List<Test> m_testList;
  
  	// Test run options
  	//
  	// Run tests sequentially or interleaved
  	
  	private boolean m_runInterleaved;
  	
  	// Number of test threads to create per server
  	
  	private int m_threadsPerServer	= 1;
  	
  	// Debug configuration
  	
  	private DebugConfigSection m_debugConfig;
  	
  	/**
  	 * Default constructor
  	 */
  	public TestConfiguration() {
  	}
  	
  	/**
  	 * Return the server list
  	 * 
  	 * @return List<TestServer>
  	 */
  	public List<TestServer> getServerList() {
  		return m_serverList;
  	}
  	
  	/**
  	 * Return the test list
  	 * 
  	 * @return List<Test>
  	 */
  	public List<Test> getTestList() {
  		return m_testList;
  	}
  	
  	/**
  	 * Check if the tests should be run interleaved or sequentially
  	 * 
  	 * @return boolean
  	 */
  	public final boolean runInterleaved() {
  		return m_runInterleaved;
  	}
  	
  	/**
  	 * Check how many test threads are to be created per server
  	 * 
  	 * @return int
  	 */
  	public final int getThreadsPerServer() {
  		return m_threadsPerServer;
  	}
  	
  	/**
  	 * Load the configuration from the specified file.
  	 * 
  	 * @param fname java.lang.String
  	 * @exception IOException
  	 * @exception InvalidConfigurationException
  	 */
  	public final void loadConfiguration(String fname)
  		throws IOException, InvalidConfigurationException {
  
  		// Open the configuration file
  
  		InputStream inFile = new FileInputStream(fname);
  		Reader inRead = new InputStreamReader(inFile);
  
  		// Call the main parsing method
  
  		loadConfiguration(inRead);
  	}
  
  	/**
  	 * Load the configuration from the specified input stream
  	 * 
  	 * @param in Reader
  	 * @exception IOException
  	 * @exception InvalidConfigurationException
  	 */
  	public final void loadConfiguration(Reader in)
  		throws IOException, InvalidConfigurationException {
  
  		// Load and parse the XML configuration document
  
  		try {
  
  			// Load the configuration from the XML file
  
  			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  			DocumentBuilder builder = factory.newDocumentBuilder();
  
  			InputSource xmlSource = new InputSource(in);
  			Document doc = builder.parse(xmlSource);
  
  			// Parse the document
  
  			loadConfiguration(doc);
  		}
  		catch (Exception ex) {
  
  			// Rethrow the exception as a configuration exeception
  
  			throw new InvalidConfigurationException("XML error", ex);
  		}
  		finally {
  
  			// Close the input file
  
  			in.close();
  		}
  	}
  
  	/**
  	 * Load the configuration from the specified document
  	 * 
  	 * @param doc Document
  	 * @exception IOException
  	 * @exception InvalidConfigurationException
  	 */
  	public void loadConfiguration(Document doc)
  		throws IOException, InvalidConfigurationException {
  
  		// Parse the XML configuration document
  
  		try {
  
  			// Access the root of the XML document, get a list of the child nodes
  
  			Element root = doc.getDocumentElement();
  			NodeList childNodes = root.getChildNodes();
  
  			// Process the server list element
  
  			procServerList( buildConfigElement( findChildNode("servers", childNodes)));
  			
  			// Process the test list
  			
  			procTestList( buildConfigElement( findChildNode("tests", childNodes)));
  			
  			// Process the run parameters
  			
  			procRunParameters( buildConfigElement( findChildNode( "run", childNodes)));
  			
  			// Process the debug output element
  			
  			procDebugSetup( buildConfigElement( findChildNode( "debug", childNodes)));
  		}
  		catch (Exception ex) {
  
  			// Rethrow the exception as a configuration exeception
  
  			throw new InvalidConfigurationException("XML error", ex);
  		}
  	}
  
  	/**
  	 * Process the server list
  	 * 
  	 * @param servers ConfigElement
  	 * @exception InvalidConfigurationException
  	 */
  	protected final void procServerList( ConfigElement servers)
  		throws InvalidConfigurationException {
  		
  		// Check if the server list is valid
  		
  		if ( servers == null)
  			throw new InvalidConfigurationException( "Server list must be specified");
  		
  		// Allocate the server list
  		
  		m_serverList = new ArrayList<TestServer>();
  		
  		// Check if default server settings have been specified
  		
  		ConfigElement defaultElem = servers.getChild( "default");
  		TestServer defaultSrv = null;
  		
  		if ( defaultElem != null) {
  			
  			// Check for default values for username, password, share
  			
  			String defUser = defaultElem.getAttribute( "username");
  			String defPass = defaultElem.getAttribute( "password");
  			String defShare= defaultElem.getAttribute( "share");
  			
  			// Create the default server details
  			
  			defaultSrv = new TestServer( "", defUser, defPass, defShare);
  		}
  		
  		// Process the server list
  
  		List<ConfigElement> srvElemList = servers.getChildren();
  		
  		for ( int idx = 0; idx < srvElemList.size(); idx++) {
  			
  			// Get the current server details
  			
  			ConfigElement curElem = srvElemList.get( idx);
  			if ( curElem.getName().equals( "server")) {
  				
  				// Create the server details
  				
  				String srvName = curElem.getAttribute( "name");
  				if ( srvName == null || srvName.length() == 0)
  					throw new InvalidConfigurationException( "Invalid server, name not specified");
  				
  				String srvUser = curElem.getAttribute( "username");
  				String srvPass = curElem.getAttribute( "password");
  				String srvShare= curElem.getAttribute( "share");
  				
  				// Add default values
  				
  				if ( defaultSrv != null) {
  