diff --git a/bundles/org.eclipse.releng.tests/src/org/eclipse/releng/tests/BuildTests.java b/bundles/org.eclipse.releng.tests/src/org/eclipse/releng/tests/BuildTests.java
index b48f0c8..e0824f7 100644
--- a/bundles/org.eclipse.releng.tests/src/org/eclipse/releng/tests/BuildTests.java
+++ b/bundles/org.eclipse.releng.tests/src/org/eclipse/releng/tests/BuildTests.java
@@ -1,13 +1,11 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
+ * Copyright (c) 2000, 2013 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
- * Contributors:
- *     IBM Corporation - initial API and implementation
+ * Contributors: IBM Corporation - initial API and implementation
  *******************************************************************************/
+
 package org.eclipse.releng.tests;
 
 import java.io.BufferedInputStream;
@@ -49,1059 +47,1087 @@
 
 public class BuildTests extends TestCase {
 
-	private String logFileName;
-	private static final int HTML = 0;
-	private static final int PROPERTIES = 1;
-	private static final int XML = 2;
+    private String           logFileName;
+    private static final int HTML       = 0;
+    private static final int PROPERTIES = 1;
+    private static final int XML        = 2;
 
-	private static FileTool.IZipFilter getTrueFilter() {
-		return new FileTool.IZipFilter() {
-			public boolean shouldExtract(String fullEntryName, String entryName, int depth) {
-				return true;
-			}
+    private static FileTool.IZipFilter getTrueFilter() {
+        return new FileTool.IZipFilter() {
 
-			public boolean shouldUnzip(String fullEntryName, String entryName, int depth) {
-				return true;
-			}
-		};
-	}
+            public boolean shouldExtract(String fullEntryName, String entryName, int depth) {
+                return true;
+            }
 
-	/**
-	 * Method hasErrors.
-	 * 
-	 * @param string
-	 * @return boolean
-	 */
-	private boolean hasErrors(String string) {
+            public boolean shouldUnzip(String fullEntryName, String entryName, int depth) {
+                return true;
+            }
+        };
+    }
 
-		boolean result = false;
-		BufferedReader aReader = null;
+    /**
+     * Method hasErrors.
+     * 
+     * @param string
+     * @return boolean
+     */
+    private boolean hasErrors(String string) {
 
-		try {
-			aReader = new BufferedReader(new InputStreamReader(new FileInputStream(string)));
-			String aLine = aReader.readLine();
-			while (aLine != null) {
-				int aNumber = parseLine(aLine);
-				if (aNumber > 0) {
-					result = true;
-				}
-				aLine = aReader.readLine();
-			}
-		} catch (FileNotFoundException e) {
-			System.out.println("Could not open log file: " + string);
-			result = true;
-		} catch (IOException e) {
-			System.out.println("Error reading log file: " + string);
-			result = true;
-		} finally {
-			if (aReader != null) {
-				try {
-					aReader.close();
-				} catch (IOException e) {
-					result = true;
-				}
-			}
-		}
+        boolean result = false;
+        BufferedReader aReader = null;
 
-		return result;
-	}
+        try {
+            aReader = new BufferedReader(new InputStreamReader(new FileInputStream(string)));
+            String aLine = aReader.readLine();
+            while (aLine != null) {
+                int aNumber = parseLine(aLine);
+                if (aNumber > 0) {
+                    result = true;
+                }
+                aLine = aReader.readLine();
+            }
+        }
+        catch (FileNotFoundException e) {
+            System.out.println("Could not open log file: " + string);
+            result = true;
+        }
+        catch (IOException e) {
+            System.out.println("Error reading log file: " + string);
+            result = true;
+        }
+        finally {
+            if (aReader != null) {
+                try {
+                    aReader.close();
+                }
+                catch (IOException e) {
+                    result = true;
+                }
+            }
+        }
 
-	public void testChkpii() {
+        return result;
+    }
 
-		try {
-			// test that chkpii is on path by printing chkpii help information
-			Runtime aRuntime = Runtime.getRuntime();
-			Process aProcess = aRuntime.exec(getExec() + " /?");
-			BufferedReader aBufferedReader = new BufferedReader(new InputStreamReader(aProcess.getInputStream()));
-			while (aBufferedReader.readLine() != null) {
-			}
-			aProcess.waitFor();
-		} catch (IOException e) {
-			// skip chkpii test if chkpii cannot be run.
-			setName("testChkpii-NotInstalled");
-			System.out.println(e.getMessage());
-			System.out.println("Skipping chkpii test.");
-			assertTrue(true);
-			return;
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		}
+    public void testChkpii() {
 
-		String zipFile = locateEclipseZip();
+        try {
+            // test that chkpii is on path by printing chkpii help information
+            Runtime aRuntime = Runtime.getRuntime();
+            Process aProcess = aRuntime.exec(getExec() + " /?");
+            BufferedReader aBufferedReader = new BufferedReader(new InputStreamReader(aProcess.getInputStream()));
+            while (aBufferedReader.readLine() != null) {
+            }
+            aProcess.waitFor();
+        }
+        catch (IOException e) {
+            // skip chkpii test if chkpii cannot be run.
+            setName("testChkpii-NotInstalled");
+            System.out.println(e.getMessage());
+            System.out.println("Skipping chkpii test.");
+            assertTrue(true);
+            return;
+        }
+        catch (InterruptedException e) {
+            e.printStackTrace();
+        }
 
-		// String sniffFolder = BootLoader.getInstallURL().getPath() +
-		// "releng_sniff_folder";
-		// String sniffFolder = "d:\\builds\\t";
-		String sniffFolder = Platform.getLocation().toOSString();
+        String zipFile = locateEclipseZip();
 
-		try {
-			if (zipFile.equals("")) {
-				FileTool.unzip(getTrueFilter(), new File(sniffFolder));
-			} else {
-				FileTool.unzip(getTrueFilter(), new ZipFile(zipFile), new File(sniffFolder));
-			}
-		} catch (IOException e) {
-			fail(zipFile + ": " + sniffFolder + ": " + "IOException unzipping Eclipse for chkpii");
-		}
+        // String sniffFolder = BootLoader.getInstallURL().getPath() +
+        // "releng_sniff_folder";
+        // String sniffFolder = "d:\\builds\\t";
+        String sniffFolder = Platform.getLocation().toOSString();
 
-		boolean result1 = testChkpii(HTML);
-		boolean result2 = testChkpii(XML);
-		boolean result3 = testChkpii(PROPERTIES);
-		assertTrue("Translation errors in files.  See the chkpii logs linked from the test results page for details.", (result1
-				&& result2 && result3));
-	}
+        try {
+            if (zipFile.equals("")) {
+                FileTool.unzip(getTrueFilter(), new File(sniffFolder));
+            } else {
+                FileTool.unzip(getTrueFilter(), new ZipFile(zipFile), new File(sniffFolder));
+            }
+        }
+        catch (IOException e) {
+            fail(zipFile + ": " + sniffFolder + ": " + "IOException unzipping Eclipse for chkpii");
+        }
 
-	private boolean testChkpii(int type) {
-		Runtime aRuntime = Runtime.getRuntime();
-		String chkpiiString = getChkpiiString(type);
-		try {
-			Process aProcess = aRuntime.exec(chkpiiString);
-			BufferedReader aBufferedReader = new BufferedReader(new InputStreamReader(aProcess.getInputStream()));
-			while (aBufferedReader.readLine() != null) {
-			}
-			aProcess.waitFor();
-		} catch (IOException e) {
-			e.printStackTrace();
-			return false;
-		} catch (InterruptedException e) {
-			return false;
-		}
-		return !hasErrors(getOutputFile(type));
-	}
+        boolean result1 = testChkpii(HTML);
+        boolean result2 = testChkpii(XML);
+        boolean result3 = testChkpii(PROPERTIES);
+        assertTrue("Translation errors in files.  See the chkpii logs linked from the test results page for details.",
+                (result1 && result2 && result3));
+    }
 
-	/**
-	 * Method getChkpiiString.
-	 * 
-	 * @param HTML
-	 * @return String
-	 */
-	private String getChkpiiString(int type) {
-		return getExec() + " " + getFilesToTest(type) + " -E -O " + getOutputFile(type) + " -XM @" + getExcludeErrors() + " -X "
-				+ getExcludeFile() + " -S /jsq /tex";
-	}
+    private boolean testChkpii(int type) {
+        Runtime aRuntime = Runtime.getRuntime();
+        String chkpiiString = getChkpiiString(type);
+        try {
+            Process aProcess = aRuntime.exec(chkpiiString);
+            BufferedReader aBufferedReader = new BufferedReader(new InputStreamReader(aProcess.getInputStream()));
+            while (aBufferedReader.readLine() != null) {
+            }
+            aProcess.waitFor();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        catch (InterruptedException e) {
+            return false;
+        }
+        return !hasErrors(getOutputFile(type));
+    }
 
-	/**
-	 * Method locateEclipseZip.
-	 * 
-	 * @return String
-	 */
-	private String locateEclipseZip() {
+    /**
+     * Method getChkpiiString.
+     * 
+     * @param HTML
+     * @return String
+     */
+    private String getChkpiiString(int type) {
+        return getExec() + " " + getFilesToTest(type) + " -E -O " + getOutputFile(type) + " -XM @" + getExcludeErrors() + " -X "
+                + getExcludeFile() + " -S /jsq /tex";
+    }
 
-		// String to use when running as an automated test.
-		String installDir = Platform.getInstallLocation().getURL().getPath() + ".." + File.separator + "..";
+    /**
+     * Method locateEclipseZip.
+     * 
+     * @return String
+     */
+    private String locateEclipseZip() {
 
-		// String to use when running in Eclipse
-		// String installDir = BootLoader.getInstallURL().getPath() + "..";
-		File aFile = new File(installDir);
+        // String to use when running as an automated test.
+        String installDir = Platform.getInstallLocation().getURL().getPath() + ".." + File.separator + "..";
 
-		File[] files = aFile.listFiles();
-		for (int i = 0; i < files.length; i++) {
-			File file = files[i];
-			String fileName = file.getName();
-			if (fileName.startsWith("eclipse-SDK-") && fileName.endsWith(".zip")) {
-				return file.getPath();
-			}
-		}
+        // String to use when running in Eclipse
+        // String installDir = BootLoader.getInstallURL().getPath() + "..";
+        File aFile = new File(installDir);
 
-		return "";
-	}
+        File[] files = aFile.listFiles();
+        for (int i = 0; i < files.length; i++) {
+            File file = files[i];
+            String fileName = file.getName();
+            if (fileName.startsWith("eclipse-SDK-") && fileName.endsWith(".zip")) {
+                return file.getPath();
+            }
+        }
 
-	/**
-	 * Method getExcludeFiles.
-	 * 
-	 * @return String
-	 */
-	private String getExcludeFile() {
-		String aString = System.getProperty("PLUGIN_PATH");
-		return aString + File.separator + "ignoreFiles.txt";
-	}
+        return "";
+    }
 
-	/**
-	 * Method getOutputFile.
-	 * 
-	 * @param HTML
-	 * @return String
-	 */
+    /**
+     * Method getExcludeFiles.
+     * 
+     * @return String
+     */
+    private String getExcludeFile() {
+        String aString = System.getProperty("PLUGIN_PATH");
+        return aString + File.separator + "ignoreFiles.txt";
+    }
 
-	private String getOutputFile(int type) {
+    /**
+     * Method getOutputFile.
+     * 
+     * @param HTML
+     * @return String
+     */
 
-		new File(logFileName).mkdirs();
+    private String getOutputFile(int type) {
 
-		String aString = logFileName + File.separator + "org.eclipse.nls.";
-		aString = new File(aString).getPath();
+        new File(logFileName).mkdirs();
 
-		switch (type) {
-		case HTML:
-			return aString + "html.txt";
-		case PROPERTIES:
-			return aString + "properties.txt";
+        String aString = logFileName + File.separator + "org.eclipse.nls.";
+        aString = new File(aString).getPath();
 
-		case XML:
-			return aString + "xml.txt";
+        switch (type) {
+            case HTML:
+                return aString + "html.txt";
+            case PROPERTIES:
+                return aString + "properties.txt";
 
-		default:
-			return aString + "other.txt";
-		}
-	}
+            case XML:
+                return aString + "xml.txt";
 
-	/**
-	 * Method getFilesToTest.
-	 * 
-	 * @param HTML
-	 * @return String
-	 */
+            default:
+                return aString + "other.txt";
+        }
+    }
 
-	private String getFilesToTest(int type) {
+    /**
+     * Method getFilesToTest.
+     * 
+     * @param HTML
+     * @return String
+     */
 
-		String sniffFolder = Platform.getLocation().toOSString();
+    private String getFilesToTest(int type) {
 
-		String aString = new File(sniffFolder).getPath() + File.separator;
+        String sniffFolder = Platform.getLocation().toOSString();
 
-		switch (type) {
-		case HTML:
-			return aString + "*.htm*";
-		case PROPERTIES:
-			return aString + "*.properties";
+        String aString = new File(sniffFolder).getPath() + File.separator;
 
-		case XML:
-			return aString + "*.xml";
+        switch (type) {
+            case HTML:
+                return aString + "*.htm*";
+            case PROPERTIES:
+                return aString + "*.properties";
 
-		default:
-			return aString + "*.*";
-		}
-	}
+            case XML:
+                return aString + "*.xml";
 
-	/**
-	 * Method getExec.
-	 * 
-	 * @return String
-	 */
+            default:
+                return aString + "*.*";
+        }
+    }
 
-	private String getExec() {
+    /**
+     * Method getExec.
+     * 
+     * @return String
+     */
 
-		return new File("chkpw1402.exe").getPath();
-	}
+    private String getExec() {
 
-	/**
-	 * Method getExcludeErrors.
-	 */
-	private String getExcludeErrors() {
+        return new File("chkpw1402.exe").getPath();
+    }
 
-		String os = Platform.getOS();
-		String fileName;
+    /**
+     * Method getExcludeErrors.
+     */
+    private String getExcludeErrors() {
 
-		if (os.equals("win32")) {
-			fileName = "ignoreErrorsWindows.txt";
-		} else {
-			fileName = "ignoreErrorsUnix.txt";
-		}
+        String os = Platform.getOS();
+        String fileName;
 
-		String aString = System.getProperty("PLUGIN_PATH");
-		return aString + File.separator + fileName;
-	}
+        if (os.equals("win32")) {
+            fileName = "ignoreErrorsWindows.txt";
+        } else {
+            fileName = "ignoreErrorsUnix.txt";
+        }
 
-	/**
-	 * Method parseLine.
-	 * 
-	 * @param aLine
-	 * @return -1 if not an error or warning line or the number of errors or
-	 *         warnings.
-	 */
-	private int parseLine(String aLine) {
-		int index = aLine.indexOf("Files Could Not Be Processed: ");
+        String aString = System.getProperty("PLUGIN_PATH");
+        return aString + File.separator + fileName;
+    }
 
-		if (index == -1) {
-			index = aLine.indexOf("Files Contain Error");
-		}
+    /**
+     * Method parseLine.
+     * 
+     * @param aLine
+     * @return -1 if not an error or warning line or the number of errors or warnings.
+     */
+    private int parseLine(String aLine) {
+        int index = aLine.indexOf("Files Could Not Be Processed: ");
 
-		if (index == -1) {
-			return -1;
-		} else {
-			String aString = aLine.substring(0, index).trim();
-			return Integer.parseInt(aString);
-		}
-	}
+        if (index == -1) {
+            index = aLine.indexOf("Files Contain Error");
+        }
 
-	public class FileSuffixFilter implements FilenameFilter {
+        if (index == -1) {
+            return -1;
+        } else {
+            String aString = aLine.substring(0, index).trim();
+            return Integer.parseInt(aString);
+        }
+    }
 
-		private String suffix;
+    public class FileSuffixFilter implements FilenameFilter {
 
-		public FileSuffixFilter(String suffix) {
-			this.suffix = suffix;
-		}
+        private String suffix;
 
-		/**
-		 * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
-		 */
-		public boolean accept(File dir, String name) {
-			int lastDot = name.lastIndexOf('.');
-			if (lastDot == -1) {
-				return false;
-			}
-			return name.substring(lastDot).equals(suffix);
-		}
+        public FileSuffixFilter(String suffix) {
+            this.suffix = suffix;
+        }
 
-	}
+        /**
+         * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+         */
+        public boolean accept(File dir, String name) {
+            int lastDot = name.lastIndexOf('.');
+            if (lastDot == -1) {
+                return false;
+            }
+            return name.substring(lastDot).equals(suffix);
+        }
 
-	public static final String[] REQUIRED_FEATURE_FILES = { "epl-v10.html", "feature.properties", "feature.xml", "license.html" };
-	public static final String REQUIRED_FEATURE_SUFFIX = "";
+    }
 
-	public static final String[] REQUIRED_PLUGIN_FILES = { "about.html", "plugin.properties", "plugin.xml" };
-	public static final String REQUIRED_PLUGIN_SUFFIX = ".jar";
+    public static final String[] REQUIRED_FEATURE_FILES  = { "epl-v10.html", "feature.properties", "feature.xml", "license.html" };
+    public static final String   REQUIRED_FEATURE_SUFFIX = "";
 
-	public static final String[] REQUIRED_FEATURE_PLUGIN_FILES = { "about.html", "about.ini", "about.mappings", "about.properties",
-			"plugin.properties", "plugin.xml" };
-	public static final String REQUIRED_FEATURE_PLUGIN_SUFFIX = ".gif";
+    public static final String[] REQUIRED_PLUGIN_FILES  = { "about.html", "plugin.properties", "plugin.xml" };
+    public static final String   REQUIRED_PLUGIN_SUFFIX = ".jar";
 
-	public static final String[] REQUIRED_FRAGMENT_FILES = { "fragment.xml" };
-	public static final String REQUIRED_FRAGMENT_SUFFIX = "";
+    public static final String[] REQUIRED_FEATURE_PLUGIN_FILES  = { "about.html", "about.ini", "about.mappings", "about.properties",
+            "plugin.properties", "plugin.xml" };
+    public static final String   REQUIRED_FEATURE_PLUGIN_SUFFIX = ".gif";
 
-	public static final String[] REQUIRED_SWT_FRAGMENT_FILES = { "fragment.properties" };
-	public static final String REQUIRED_SWT_FRAGMENT_SUFFIX = "";
+    public static final String[] REQUIRED_FRAGMENT_FILES  = { "fragment.xml" };
+    public static final String   REQUIRED_FRAGMENT_SUFFIX = "";
 
-	public static final String[] REQUIRED_SOURCE_FILES = { "about.html" };
-	public static final String REQUIRED_SOURCE_SUFFIX = ".zip";
+    public static final String[] REQUIRED_SWT_FRAGMENT_FILES  = { "fragment.properties" };
+    public static final String   REQUIRED_SWT_FRAGMENT_SUFFIX = "";
 
-	public static final String[] REQUIRED_BUNDLE_FILES = { "about.html" };
-	public static final String REQUIRED_BUNDLE_MANIFEST = "MANIFEST.MF";
-	public static final String REQUIRED_BUNDLE_SUFFIX = ".jar";
+    public static final String[] REQUIRED_SOURCE_FILES  = { "about.html" };
+    public static final String   REQUIRED_SOURCE_SUFFIX = ".zip";
 
-	public static final String[] SUFFIX_EXEMPT_LIST = { "org.eclipse.swt", "org.apache.ant" };
+    public static final String[] REQUIRED_BUNDLE_FILES    = { "about.html" };
+    public static final String   REQUIRED_BUNDLE_MANIFEST = "MANIFEST.MF";
+    public static final String   REQUIRED_BUNDLE_SUFFIX   = ".jar";
 
-	public static final int PLUGIN_COUNT = 84; // - 20; // Note this number
-	// must include non-shipping
-	// test plugins
-	public static final int FEATURE_COUNT = 9; // - 1; // Note this number must
+    public static final String[] SUFFIX_EXEMPT_LIST = { "org.eclipse.swt", "org.apache.ant" };
 
-	// include non-shipping test
-	// feature
+    public static final int PLUGIN_COUNT  = 84; // - 20; // Note this number
+    // must include non-shipping
+    // test plugins
+    public static final int FEATURE_COUNT = 9;  // - 1; // Note this number must
 
-	/**
-	 * Constructor for EmptyDirectoriesTest.
-	 * 
-	 * @param arg0
-	 */
-	public BuildTests(String arg0) {
-		super(arg0);
-	}
+    // include non-shipping test
+    // feature
 
-	/**
-	 * @see TestCase#setUp()
-	 */
-	protected void setUp() throws Exception {
-		// Automated Test
-		logFileName = Platform.getInstallLocation().getURL().getPath() + ".." + File.separator + ".." + File.separator + "results"
-				+ File.separator + "chkpii"; // A tad bogus but this is where
-												// the build wants to copy the
-												// results from!
+    /**
+     * Constructor for EmptyDirectoriesTest.
+     * 
+     * @param arg0
+     */
+    public BuildTests(String arg0) {
+        super(arg0);
+    }
 
-		// Runtime Workbench - TODO Put me back to Automated status
-		// logFileName = "d:\\results";
-		// sourceDirectoryName = "d:\\sourceFetch";
-	}
+    /**
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        // Automated Test
+        logFileName = Platform.getInstallLocation().getURL().getPath() + ".." + File.separator + ".." + File.separator + "results"
+                + File.separator + "chkpii"; // A tad bogus but this is where
+                                             // the build wants to copy the
+                                             // results from!
 
-	/**
-	 * @see TestCase#tearDown()
-	 */
-	protected void tearDown() throws Exception {
-		super.tearDown();
-	}
+        // Runtime Workbench - TODO Put me back to Automated status
+        // logFileName = "d:\\results";
+        // sourceDirectoryName = "d:\\sourceFetch";
+    }
 
-	public void testFeatureFiles() {
-		List result = new ArrayList();
-		String installDir = Platform.getInstallLocation().getURL().getPath();
+    /**
+     * @see TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
 
-		File featureDir = new File(installDir, "features");
-		File[] features = featureDir.listFiles();
-		for (int i = 0; i < features.length; i++) {
-			File aFeature = features[i];
-			if (!testDirectory(aFeature, REQUIRED_FEATURE_FILES, REQUIRED_FEATURE_SUFFIX)) {
-				result.add(aFeature.getPath());
-			}
+    public void testFeatureFiles() {
+        List result = new ArrayList();
+        String installDir = Platform.getInstallLocation().getURL().getPath();
 
-		}
+        File featureDir = new File(installDir, "features");
+        File[] features = featureDir.listFiles();
+        for (int i = 0; i < features.length; i++) {
+            File aFeature = features[i];
+            if (!testDirectory(aFeature, REQUIRED_FEATURE_FILES, REQUIRED_FEATURE_SUFFIX)) {
+                result.add(aFeature.getPath());
+            }
 
-		String aString = "";
-		if (result.size() > 0) {
+        }
 
-			Iterator iter = result.iterator();
-			while (iter.hasNext()) {
-				String element = (String) iter.next();
-				aString = aString + element + "; ";
-			}
-		}
-		assertTrue("Feature directory missing required files: " + aString, result.size() == 0);
-	}
+        String aString = "";
+        if (result.size() > 0) {
 
-	public void testPluginFiles() {
-		List result = new ArrayList();
-		String installDir = Platform.getInstallLocation().getURL().getPath();
-		File pluginDir = new File(installDir, "plugins");
-		File[] plugins = pluginDir.listFiles();
-		for (int i = 0; i < plugins.length; i++) {
-			File aPlugin = plugins[i];
-			if (aPlugin.getName().indexOf("test") == -1) {
-				if (!testPluginFile(aPlugin)) {
-					result.add(aPlugin.getPath());
-				}
-			}
-		}
+            Iterator iter = result.iterator();
+            while (iter.hasNext()) {
+                String element = (String) iter.next();
+                aString = aString + element + "; ";
+            }
+        }
+        assertTrue("Feature directory missing required files: " + aString, result.size() == 0);
+    }
 
-		String aString = "";
-		if (result.size() > 0) {
+    public void testPluginFiles() {
+        List result = new ArrayList();
+        String installDir = Platform.getInstallLocation().getURL().getPath();
+        File pluginDir = new File(installDir, "plugins");
+        File[] plugins = pluginDir.listFiles();
+        for (int i = 0; i < plugins.length; i++) {
+            File aPlugin = plugins[i];
+            if (aPlugin.getName().indexOf("test") == -1) {
+                if (!testPluginFile(aPlugin)) {
+                    result.add(aPlugin.getPath());
+                }
+            }
+        }
 
-			Iterator iter = result.iterator();
-			while (iter.hasNext()) {
-				String element = (String) iter.next();
-				aString = aString + element + "; ";
-			}
-		}
-		assertTrue("Plugin directory missing required files: " + aString, result.size() == 0);
-	}
+        String aString = "";
+        if (result.size() > 0) {
 
-	private boolean testPluginFile(File aPlugin) {
+            Iterator iter = result.iterator();
+            while (iter.hasNext()) {
+                String element = (String) iter.next();
+                aString = aString + element + "; ";
+            }
+        }
+        assertTrue("Plugin directory missing required files: " + aString, result.size() == 0);
+    }
 
-		// Are we a doc plugin?
-		if (testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, ".zip")) {
-			return true;
-		}
+    private boolean testPluginFile(File aPlugin) {
 
-		// Are we a feature plugin?
-		if (testDirectory(aPlugin, REQUIRED_FEATURE_PLUGIN_FILES, REQUIRED_FEATURE_PLUGIN_SUFFIX)) {
-			return true;
-		}
+        // Are we a doc plugin?
+        if (testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, ".zip")) {
+            return true;
+        }
 
-		// Are we a regular plugin
-		if (testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, REQUIRED_PLUGIN_SUFFIX)) {
-			return true;
-		}
+        // Are we a feature plugin?
+        if (testDirectory(aPlugin, REQUIRED_FEATURE_PLUGIN_FILES, REQUIRED_FEATURE_PLUGIN_SUFFIX)) {
+            return true;
+        }
 
-		// Are we a source plugin
-		if (testSourcePlugin(aPlugin)) {
-			return true;
-		}
+        // Are we a regular plugin
+        if (testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, REQUIRED_PLUGIN_SUFFIX)) {
+            return true;
+        }
 
-		// Are we a fragment
-		if ((testDirectory(aPlugin, REQUIRED_FRAGMENT_FILES, REQUIRED_FRAGMENT_SUFFIX))
-				|| (testBundleDirectory(aPlugin, REQUIRED_BUNDLE_FILES, REQUIRED_BUNDLE_MANIFEST, REQUIRED_FRAGMENT_SUFFIX))) {
-			return true;
-		}
+        // Are we a source plugin
+        if (testSourcePlugin(aPlugin)) {
+            return true;
+        }
 
-		// Are we an swt fragment
-		if (testDirectory(aPlugin, REQUIRED_SWT_FRAGMENT_FILES, REQUIRED_SWT_FRAGMENT_SUFFIX)) {
-			return true;
-		}
+        // Are we a fragment
+        if ((testDirectory(aPlugin, REQUIRED_FRAGMENT_FILES, REQUIRED_FRAGMENT_SUFFIX))
+                || (testBundleDirectory(aPlugin, REQUIRED_BUNDLE_FILES, REQUIRED_BUNDLE_MANIFEST, REQUIRED_FRAGMENT_SUFFIX))) {
+            return true;
+        }
 
-		// Are we a bundle?
-		if (testBundleDirectory(aPlugin, REQUIRED_BUNDLE_FILES, REQUIRED_BUNDLE_MANIFEST, REQUIRED_BUNDLE_SUFFIX)) {
-			return true;
-		}
+        // Are we an swt fragment
+        if (testDirectory(aPlugin, REQUIRED_SWT_FRAGMENT_FILES, REQUIRED_SWT_FRAGMENT_SUFFIX)) {
+            return true;
+        }
 
-		// No then we are bad
-		return false;
-	}
+        // Are we a bundle?
+        if (testBundleDirectory(aPlugin, REQUIRED_BUNDLE_FILES, REQUIRED_BUNDLE_MANIFEST, REQUIRED_BUNDLE_SUFFIX)) {
+            return true;
+        }
 
-	private boolean testPluginJar(File aDirectory, String[] requiredFiles) {
-		ArrayList list = new ArrayList();
-		try {
-			ZipFile jarredPlugin = new ZipFile(aDirectory);
-			Enumeration _enum = jarredPlugin.entries();
-			while (_enum.hasMoreElements()) {
-				list.add(_enum.nextElement().toString());
-			}
-		} catch (ZipException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-		if (!list.containsAll(Arrays.asList(requiredFiles))) {
-			return false;
-		}
-		return true;
-	}
+        // No then we are bad
+        return false;
+    }
 
-	private boolean testDirectory(File aDirectory, String[] requiredFiles, String requiredSuffix) {
-		if (aDirectory.getName().endsWith(".jar")) {
-			return testPluginJar(aDirectory, requiredFiles);
-		} else {
-			if (!Arrays.asList(aDirectory.list()).containsAll(Arrays.asList(requiredFiles))) {
-				return false;
-			}
+    private boolean testPluginJar(File aDirectory, String[] requiredFiles) {
+        ArrayList list = new ArrayList();
+        try {
+            ZipFile jarredPlugin = new ZipFile(aDirectory);
+            Enumeration _enum = jarredPlugin.entries();
+            while (_enum.hasMoreElements()) {
+                list.add(_enum.nextElement().toString());
+            }
+        }
+        catch (ZipException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        if (!list.containsAll(Arrays.asList(requiredFiles))) {
+            return false;
+        }
+        return true;
+    }
 
-			int index = aDirectory.getName().indexOf('_');
-			if (index == -1) {
-				index = aDirectory.getName().length();
-			}
+    private boolean testDirectory(File aDirectory, String[] requiredFiles, String requiredSuffix) {
+        if (aDirectory.getName().endsWith(".jar")) {
+            return testPluginJar(aDirectory, requiredFiles);
+        } else {
+            if (!Arrays.asList(aDirectory.list()).containsAll(Arrays.asList(requiredFiles))) {
+                return false;
+            }
 
-			String plainName = aDirectory.getName().substring(0, index);
+            int index = aDirectory.getName().indexOf('_');
+            if (index == -1) {
+                index = aDirectory.getName().length();
+            }
 
-			if (requiredSuffix.equals("") || Arrays.asList(SUFFIX_EXEMPT_LIST).contains(plainName)) {
-				return true;
-			} else if (aDirectory.listFiles(new FileSuffixFilter(requiredSuffix)).length == 0) {
-				return false;
-			}
-		}
-		return true;
-	}
+            String plainName = aDirectory.getName().substring(0, index);
 
-	private boolean testBundleDirectory(File aDirectory, String[] requiredFiles, String manifestFile, String requiredSuffix) {
-		if (aDirectory.getName().endsWith(".jar")) {
-			return testPluginJar(aDirectory, requiredFiles);
-		} else {
-			if (!Arrays.asList(aDirectory.list()).containsAll(Arrays.asList(requiredFiles))) {
-				return false;
-			}
+            if (requiredSuffix.equals("") || Arrays.asList(SUFFIX_EXEMPT_LIST).contains(plainName)) {
+                return true;
+            } else if (aDirectory.listFiles(new FileSuffixFilter(requiredSuffix)).length == 0) {
+                return false;
+            }
+        }
+        return true;
+    }
 
-			int index = aDirectory.getName().indexOf('_');
-			if (index == -1) {
-				index = aDirectory.getName().length();
-			}
+    private boolean testBundleDirectory(File aDirectory, String[] requiredFiles, String manifestFile, String requiredSuffix) {
+        if (aDirectory.getName().endsWith(".jar")) {
+            return testPluginJar(aDirectory, requiredFiles);
+        } else {
+            if (!Arrays.asList(aDirectory.list()).containsAll(Arrays.asList(requiredFiles))) {
+                return false;
+            }
 
-			String plainName = aDirectory.getName().substring(0, index);
+            int index = aDirectory.getName().indexOf('_');
+            if (index == -1) {
+                index = aDirectory.getName().length();
+            }
 
-			File metaDir = new File(aDirectory, "META-INF");
+            String plainName = aDirectory.getName().substring(0, index);
 
-			String[] metaFiles = metaDir.list();
-			if (metaFiles == null) {
-				return (false);
-			} else {
-				for (int i = 0; i < metaFiles.length; i++) {
-					String filename = metaFiles[i];
-					if (filename == manifestFile) {
-						return true;
-					}
-				}
-			}
+            File metaDir = new File(aDirectory, "META-INF");
 
-			if (!metaDir.exists()) {
-				return false;
-			}
+            String[] metaFiles = metaDir.list();
+            if (metaFiles == null) {
+                return (false);
+            } else {
+                for (int i = 0; i < metaFiles.length; i++) {
+                    String filename = metaFiles[i];
+                    if (filename == manifestFile) {
+                        return true;
+                    }
+                }
+            }
 
-			if (requiredSuffix.equals("") || Arrays.asList(SUFFIX_EXEMPT_LIST).contains(plainName)) {
-				return true;
-			} else if (aDirectory.listFiles(new FileSuffixFilter(requiredSuffix)).length == 0) {
-				return false;
-			}
-		}
-		return true;
-	}
+            if (!metaDir.exists()) {
+                return false;
+            }
+
+            if (requiredSuffix.equals("") || Arrays.asList(SUFFIX_EXEMPT_LIST).contains(plainName)) {
+                return true;
+            } else if (aDirectory.listFiles(new FileSuffixFilter(requiredSuffix)).length == 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Return true if the receiver is a source plugin, false otherwise A separate method because this is a little tricky.
+     * 
+     * @param aPlugin
+     * @return boolean
+     */
+    private boolean testSourcePlugin(File aPlugin) {
+        if (!testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, "")) {
+            return false;
+        }
+
+        File sourceDir = new File(aPlugin, "src");
+        File[] sourceDirs = sourceDir.listFiles();
+        if (sourceDirs == null) {
+            return false;
+        }
+
+        for (int i = 0; i < sourceDirs.length; i++) {
+            File aSourceDir = sourceDirs[i];
+            if (!testDirectory(aSourceDir, REQUIRED_SOURCE_FILES, REQUIRED_SOURCE_SUFFIX)) {
+                return false;
+            }
+        }
+        return true;
+    }
 
-	/**
-	 * Return true if the receiver is a source plugin, false otherwise A
-	 * separate method because this is a little tricky.
-	 * 
-	 * @param aPlugin
-	 * @return boolean
-	 */
-	private boolean testSourcePlugin(File aPlugin) {
-		if (!testDirectory(aPlugin, REQUIRED_PLUGIN_FILES, "")) {
-			return false;
-		}
+    public void testJavadocLogs() throws Exception {
+        String javadocUrls = System.getProperty("RELENGTEST.JAVADOC.URLS");
+        // Skip this test if there are no logs to check
+        if (javadocUrls == null) {
+            System.err.println("WARNING: no javadoc logs to test, since RELENGTEST.JAVADOC.URLS property was not set");
+            return;
+        } else {
+            System.err.println("RELENGTEST.JAVADOC.URLS: " + javadocUrls);
+        }
 
-		File sourceDir = new File(aPlugin, "src");
-		File[] sourceDirs = sourceDir.listFiles();
-		if (sourceDirs == null) {
-			return false;
-		}
+        String[] urls = javadocUrls.split(",");
+        URL[] javadocLogs = new URL[urls.length];
+        for (int i = 0; i < urls.length; i++) {
+            javadocLogs[i] = new URL(urls[i]);
+            System.err.println("javadocLogs[" + i + "]: " + javadocLogs[i]);
+        }
 
-		for (int i = 0; i < sourceDirs.length; i++) {
-			File aSourceDir = sourceDirs[i];
-			if (!testDirectory(aSourceDir, REQUIRED_SOURCE_FILES, REQUIRED_SOURCE_SUFFIX)) {
-				return false;
-			}
-		}
-		return true;
-	}
+        JavadocLog javadocLog = new JavadocLog(javadocLogs);
+        String message = "javadoc errors and/or warnings in: \n";
+        boolean problemLogsExist = javadocLog.logs.size() > 0;
+        if (problemLogsExist) {
+            for (int i = 0; i < javadocLog.logs.size(); i++)
+                message = message.concat(javadocLog.logs.get(i).toString() + "\n");
+        }
+        message = message.concat("See the javadoc logs linked from the test results page for details");
+        assertTrue(message, !problemLogsExist);
+    }
 
-	public void testJavadocLogs() throws Exception {
-		String javadocUrls = System.getProperty("RELENGTEST.JAVADOC.URLS");
-		// Skip this test if there are no logs to check
-		if (javadocUrls == null) {
-			System.err.println("WARNING: no javadoc logs to test, since RELENGTEST.JAVADOC.URLS property was not set");
-			return;
-		} else {
-			System.err.println("RELENGTEST.JAVADOC.URLS: " + javadocUrls);
-		}
+    public void testDirtyLogSize() throws Exception {
+        final boolean DEBUG_DIRTY_TEST = true;
+        // MAX_ALLOWED_BYTES will never be 'zero', even if "no dirt" because the
+        // "dirReport" always contains some information
+        // in response to the "git status" command. The goal, here, is to
+        // "hard code" previously observed values, to make sure
+        // there is no regressions, which would be implied by a report larger
+        // than those that had been produced before.
+        // The "size" should be expressed in exact bytes as "increases" in
+        // size might be small ... if just a file or two.
+        URL standardReportURL = this.getClass().getResource("standardDirtReport.txt");
+        URLConnection standardReportURLConnection = standardReportURL.openConnection();
+        // No need to get contents (yet, most of the time) unless getContentLenth doesn't work for plugin resources?
+        long MAX_ALLOWED_BYTES = standardReportURLConnection.getContentLength();
+        // long MAX_ALLOWED_BYTES = 37179;
+        System.out.println("DEBUG: MAX_ALLOWED_BYTES: " + MAX_ALLOWED_BYTES);
+        String buildId = System.getProperty("buildId");
+        assertNotNull("buildId property must be specified for testDirtyLogSize test", buildId);
+        String downloadHost = getDownloadHost();
+        String urlOfFile = "http://" + downloadHost + "/eclipse/downloads/drops4/" + buildId + "/buildlogs/dirtReport.txt";
+        URL logURL = new URL(urlOfFile);
 
-		String[] urls = javadocUrls.split(",");
-		URL[] javadocLogs = new URL[urls.length];
-		for (int i = 0; i < urls.length; i++) {
-			javadocLogs[i] = new URL(urls[i]);
-			System.err.println("javadocLogs[" + i + "]: " + javadocLogs[i]);
-		}
+        URLConnection urlConnection = logURL.openConnection();
+        // getContentLength calls "connect" if needed.
+        // urlConnection.connect();
+        // Note, if expect more than "2 Gig", use getContentLengthLong (in Java 7).
+        long nBytes = urlConnection.getContentLength();
+        if (DEBUG_DIRTY_TEST) {
+            System.out.println("Debug info for testDirtyLogSize");
+            System.out.println("Debug: nBytes: " + nBytes);
+            printHeaders(urlConnection);
+        }
+        // if find "response does not contain length, on a regular basis, for
+        // some servers, will have to read contents.
+        assertTrue(
+                "Either file (url) does not exist (build may have been removed?), or HTTP response does not contain content length. urlOfFile: "
+                        + urlOfFile,
+                (!(-1 == nBytes)));
+        assertFalse("dirtReport file has increased in size, indicating a regression. See " + urlOfFile, nBytes > MAX_ALLOWED_BYTES);
+        assertFalse(
+                "Good news! dirtReport file has decreased in size, compared to standard, so the standardDirtReport.txt file should be replaced with the one at "
+                        + urlOfFile
+                        + ". But NOTE: results may not be accurate, if there are other errors in build, so diff is recommended.",
+                nBytes < MAX_ALLOWED_BYTES);
 
-		JavadocLog javadocLog = new JavadocLog(javadocLogs);
-		String message = "javadoc errors and/or warnings in: \n";
-		boolean problemLogsExist = javadocLog.logs.size() > 0;
-		if (problemLogsExist) {
-			for (int i = 0; i < javadocLog.logs.size(); i++)
-				message = message.concat(javadocLog.logs.get(i).toString() + "\n");
-		}
-		message = message.concat("See the javadoc logs linked from the test results page for details");
-		assertTrue(message, !problemLogsExist);
-	}
+    }
 
-	public void testDirtyLogSize() throws Exception {
-		final boolean DEBUG_DIRTY_TEST = true;
-		// MAX_ALLOWED_BYTES will never be 'zero', even if "no dirt" because the
-		// "dirReport" always contains some information
-		// in response to the "git status" command. The goal, here, is to
-		// "hard code" previously observed values, to make sure
-		// there is no regressions, which would be implied by a report larger
-		// than those that had been produced before.
-		// The "size" should be expressed in exact bytes as "increases" in
-		// size might be small ... if just a file or two.
-		URL standardReportURL = this.getClass().getResource("standardDirtReport.txt");
-		URLConnection standardReportURLConnection = standardReportURL.openConnection();
-		// No need to get contents (yet, most of the time) unless getContentLenth doesn't work for plugin resources?
-		long MAX_ALLOWED_BYTES = standardReportURLConnection.getContentLength();
-		//long MAX_ALLOWED_BYTES = 37179;
-		System.out.println("DEBUG: MAX_ALLOWED_BYTES: " + MAX_ALLOWED_BYTES);
-		String buildId = System.getProperty("buildId");
-		assertNotNull("buildId property must be specified for testDirtyLogSize test", buildId);
-		String downloadHost = getDownloadHost();
-		String urlOfFile = "http://"+ downloadHost + "/eclipse/downloads/drops4/" + buildId + "/buildlogs/dirtReport.txt";
-		URL logURL = new URL(urlOfFile);
+    private String getDownloadHost() {
+        String downloadHost = System.getProperty("downloadHost");
+        if (downloadHost == null) {
+            downloadHost = "download.eclipse.org";
+        }
+        return downloadHost;
+    }
 
-		URLConnection urlConnection = logURL.openConnection();
-		// getContentLength calls "connect" if needed. 
-		// urlConnection.connect();
-		// Note, if expect more than "2 Gig", use getContentLengthLong (in Java 7).
-		long nBytes = urlConnection.getContentLength();
-		if (DEBUG_DIRTY_TEST) {
-			System.out.println("Debug info for testDirtyLogSize");
-			System.out.println("Debug: nBytes: " + nBytes);
-			printHeaders(urlConnection);
-		}
-		// if find "response does not contain length, on a regular basis, for
-		// some servers, will have to read contents.
-		assertTrue("Either file (url) does not exist (build may have been removed?), or HTTP response does not contain content length. urlOfFile: " + urlOfFile,
-				(!(-1 == nBytes)));
-		assertFalse("dirtReport file has increased in size, indicating a regression. See " + urlOfFile, nBytes > MAX_ALLOWED_BYTES);
-        assertFalse("Good news! dirtReport file has decreased in size, compared to standard, so the standardDirtReport.txt file should be replaced with the one at " + urlOfFile + ". But NOTE: results may not be accurate, if there are other errors in build, so diff is recommended.", nBytes < MAX_ALLOWED_BYTES);
+    private void printHeaders(URLConnection urlConnection) {
+        System.out.println("Debug: Headers for urlConnection to " + urlConnection.getURL());
+        Map<String, List<String>> allFields = urlConnection.getHeaderFields();
+        Set<String> keys = allFields.keySet();
+        for (String key : keys) {
+            List<String> values = allFields.get(key);
+            for (String value : values) {
+                System.out.printf("Debug: %-20s %-30s %n", "key: " + key, "value: " + value);
+            }
+        }
+    }
 
-	}
+    public void testComparatorLogSize() throws Exception {
+        final boolean DEBUG_TEST = true;
+        // MAX_ALLOWED_BYTES will never be 'zero', even if no unexpected comparator warnings, because the
+        // report always contains some information, such as identifying which build it was for.
+        // The goal, here, is to
+        // "hard code" nominal values, to make sure
+        // there is no regressions, which would be implied by a report larger
+        // than that nominal value.
+        long MAX_ALLOWED_BYTES = 210;
+        String buildId = System.getProperty("buildId");
+        assertNotNull("buildId property must be specified for testComparatorLogSize test", buildId);
+        String buildType = buildId.substring(0, 1);
+        // Comparator logs are not generated for N builds
+        if (!buildType.equals("N")) {
+            String downloadHost = getDownloadHost();
+            String urlOfFile = "http://" + downloadHost + "/eclipse/downloads/drops4/" + buildId
+                    + "/buildlogs/comparatorlogs/buildtimeComparatorUnanticipated.log.txt";
+            URL logURL = new URL(urlOfFile);
 
-	private String getDownloadHost() {
-		String downloadHost = System.getProperty("downloadHost");
-		if (downloadHost == null) {
-			downloadHost = "download.eclipse.org";
-		}
-		return downloadHost;
-	}
+            URLConnection urlConnection = logURL.openConnection();
+            // urlConnection.connect();
+            long nBytes = urlConnection.getContentLength();
+            if (DEBUG_TEST) {
+                System.out.println("Debug info for testComparatorLogSize");
+                System.out.println("Debug: nBytes: " + nBytes);
+                printHeaders(urlConnection);
+            }
+            // if find "response does not contain length, on a regular basis, for
+            // some servers, will have to read contents.
+            assertTrue(
+                    "Either file (url) does not exist, or HTTP response does not contain content length. urlOfFile: " + urlOfFile,
+                    (!(-1 == nBytes)));
+            assertTrue("Unanticipated comparator log file has increased in size, indicating a regression. See " + urlOfFile,
+                    nBytes <= MAX_ALLOWED_BYTES);
+            if (MAX_ALLOWED_BYTES > (nBytes + 20)) {
+                System.out.println("WARNING: MAX_ALLOWED_BYTES was larger than bytes found, by " + (MAX_ALLOWED_BYTES - nBytes)
+                        + ", which may indicate MAX_ALLOWED_BYTES needs to be lowered, to catch regressions.");
+            }
+        } else {
+            setName("noComparatorTestsForNBuilds");
+        }
+    }
 
-	private void printHeaders(URLConnection urlConnection) {
-		System.out.println("Debug: Headers for urlConnection to " + urlConnection.getURL());
-		Map<String, List<String>> allFields = urlConnection.getHeaderFields();
-		Set<String> keys = allFields.keySet();
-		for (String key : keys) {
-			List<String> values = allFields.get(key);
-			for (String value : values) {
-				System.out.printf("Debug: %-20s %-30s %n", "key: " + key, "value: " + value);
-			}
-		}
-	}
-	public void testComparatorLogSize() throws Exception {
-		final boolean DEBUG_TEST = true;
-		// MAX_ALLOWED_BYTES will never be 'zero', even if no unexpected comparator warnings, because the
-		// report always contains some information, such as identifying which build it was for.
-		// The goal, here, is to
-		// "hard code" nominal values, to make sure
-		// there is no regressions, which would be implied by a report larger
-		// than that nominal value.
-		long MAX_ALLOWED_BYTES = 210;
-		String buildId = System.getProperty("buildId");
-		assertNotNull("buildId property must be specified for testDirtyLogSize test", buildId);
-		String downloadHost = getDownloadHost();
-		String urlOfFile = "http://" + downloadHost + "/eclipse/downloads/drops4/" + buildId + "/buildlogs/comparatorlogs/buildtimeComparatorUnanticipated.log.txt";
-		URL logURL = new URL(urlOfFile);
+    private class JavadocLog {
 
-		URLConnection urlConnection = logURL.openConnection();
-		// urlConnection.connect();
-		long nBytes = urlConnection.getContentLength();
-		if (DEBUG_TEST) {
-			System.out.println("Debug info for testComparatorLogSize");
-			System.out.println("Debug: nBytes: " + nBytes);
-			printHeaders(urlConnection);
-		}
-		// if find "response does not contain length, on a regular basis, for
-		// some servers, will have to read contents.
-		assertTrue("Either file (url) does not exist, or HTTP response does not contain content length. urlOfFile: " + urlOfFile,
-				(!(-1 == nBytes)));
-		assertTrue("Unanticipated comparator log file has increased in size, indicating a regression. See " + urlOfFile, nBytes <= MAX_ALLOWED_BYTES);
-		if (MAX_ALLOWED_BYTES > (nBytes + 20)) {
-			System.out.println("WARNING: MAX_ALLOWED_BYTES was larger than bytes found, by " + (MAX_ALLOWED_BYTES - nBytes)
-					+ ", which may indicate MAX_ALLOWED_BYTES needs to be lowered, to catch regressions.");
-		}
-	}
+        private ArrayList logs = new ArrayList();
 
-	private class JavadocLog {
-		private ArrayList logs = new ArrayList();
+        private JavadocLog(URL[] logs) {
+            findProblems(logs);
+        }
 
-		private JavadocLog(URL[] logs) {
-			findProblems(logs);
-		}
+        private void findProblems(URL[] javadocLogs) {
+            String JAVADOC_WARNING = ": warning";
+            String JAVADOC_ERROR = ": error";
+            String JAVADOC_JAVA = ".java:";
 
-		private void findProblems(URL[] javadocLogs) {
-			String JAVADOC_WARNING = ": warning";
-			String JAVADOC_ERROR = ": error";
-			String JAVADOC_JAVA = ".java:";
+            BufferedReader in = null;
+            for (int i = 0; i < javadocLogs.length; i++) {
+                try {
+                    in = new BufferedReader(new InputStreamReader(javadocLogs[i].openStream()));
+                    String tmp;
+                    while ((tmp = in.readLine()) != null) {
+                        tmp = tmp.toLowerCase();
+                        if (tmp.indexOf(JAVADOC_ERROR) != -1 || tmp.indexOf(JAVADOC_WARNING) != -1
+                                || tmp.indexOf(JAVADOC_JAVA) != -1) {
+                            String fileName = new File(javadocLogs[i].getFile()).getName();
+                            if (!logs.contains(fileName))
+                                logs.add(fileName);
+                        }
+                    }
+                    in.close();
 
-			BufferedReader in = null;
-			for (int i = 0; i < javadocLogs.length; i++) {
-				try {
-					in = new BufferedReader(new InputStreamReader(javadocLogs[i].openStream()));
-					String tmp;
-					while ((tmp = in.readLine()) != null) {
-						tmp = tmp.toLowerCase();
-						if (tmp.indexOf(JAVADOC_ERROR) != -1 || tmp.indexOf(JAVADOC_WARNING) != -1
-								|| tmp.indexOf(JAVADOC_JAVA) != -1) {
-							String fileName = new File(javadocLogs[i].getFile()).getName();
-							if (!logs.contains(fileName))
-								logs.add(fileName);
-						}
-					}
-					in.close();
+                }
+                catch (FileNotFoundException e) {
+                    logs.add("Unable to find " + new File(javadocLogs[i].getFile()).getName() + " to read.");
+                    e.printStackTrace();
+                }
+                catch (IOException e) {
+                    logs.add("Unable to read " + new File(javadocLogs[i].getFile()).getName());
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
 
-				} catch (FileNotFoundException e) {
-					logs.add("Unable to find " + new File(javadocLogs[i].getFile()).getName() + " to read.");
-					e.printStackTrace();
-				} catch (IOException e) {
-					logs.add("Unable to read " + new File(javadocLogs[i].getFile()).getName());
-					e.printStackTrace();
-				}
-			}
-		}
-	}
+    public void _testComparatorLogs() throws Exception {
+        String os = System.getProperty("os.name");
+        // Only run compare tool on Linux to save time during tests
+        if (os == null || !os.equalsIgnoreCase("Linux")) {
+            return;
+        }
 
-	public void _testComparatorLogs() throws Exception {
-		String os = System.getProperty("os.name");
-		// Only run compare tool on Linux to save time during tests
-		if (os == null || !os.equalsIgnoreCase("Linux")) {
-			return;
-		}
+        // Load the configuration and ensure the mandatory parameters were
+        // specified
+        Properties properties = loadCompareConfiguration();
+        assertNotNull("could not load configuration", properties);
 
-		// Load the configuration and ensure the mandatory parameters were
-		// specified
-		Properties properties = loadCompareConfiguration();
-		assertNotNull("could not load configuration", properties);
+        String compareOldPath = properties.getProperty("compare.old");
+        if (compareOldPath == null || compareOldPath.indexOf("N2") > 0) {
+            return; // Nightly build, skip test
+        }
 
-		String compareOldPath = properties.getProperty("compare.old");
-		if (compareOldPath == null || compareOldPath.indexOf("N2") > 0) {
-			return; // Nightly build, skip test
-		}
+        String comparatorUrl = System.getProperty("RELENGTEST.COMPARATOR.URL");
+        if (comparatorUrl == null) {
+            return; // No logs to check, skip test
+        }
+        URL comparatorLogs = new URL(comparatorUrl);
+        ComparatorLog comparatorLog = new ComparatorLog(comparatorLogs);
+        String message = "comparator warnings in: \n";
+        boolean problemLogsExist = comparatorLog.logs.size() > 0;
+        message = message.concat("See the 'comparatorlog.txt' in 'Release engineering build logs' for details.");
+        assertTrue(message, !problemLogsExist);
+    }
 
-		String comparatorUrl = System.getProperty("RELENGTEST.COMPARATOR.URL");
-		if (comparatorUrl == null) {
-			return; // No logs to check, skip test
-		}
-		URL comparatorLogs = new URL(comparatorUrl);
-		ComparatorLog comparatorLog = new ComparatorLog(comparatorLogs);
-		String message = "comparator warnings in: \n";
-		boolean problemLogsExist = comparatorLog.logs.size() > 0;
-		message = message.concat("See the 'comparatorlog.txt' in 'Release engineering build logs' for details.");
-		assertTrue(message, !problemLogsExist);
-	}
+    private class ComparatorLog {
 
-	private class ComparatorLog {
-		private ArrayList logs = new ArrayList();
+        private ArrayList logs = new ArrayList();
 
-		private ComparatorLog(URL comparatorLogs) {
-			findProblems(comparatorLogs);
-		}
+        private ComparatorLog(URL comparatorLogs) {
+            findProblems(comparatorLogs);
+        }
 
-		private void findProblems(URL comparatorLogs) {
+        private void findProblems(URL comparatorLogs) {
 
-			String COMPARATOR_ERROR = "difference found";
+            String COMPARATOR_ERROR = "difference found";
 
-			BufferedReader in = null;
+            BufferedReader in = null;
 
-			try {
-				in = new BufferedReader(new InputStreamReader(comparatorLogs.openStream()));
-				String tmp;
-				while ((tmp = in.readLine()) != null) {
-					tmp = tmp.toLowerCase();
-					if (tmp.indexOf(COMPARATOR_ERROR) != -1) {
-						String fileName = new File(comparatorLogs.getFile()).getName();
-						if (!logs.contains(fileName))
-							logs.add(fileName);
-					}
-				}
-				in.close();
+            try {
+                in = new BufferedReader(new InputStreamReader(comparatorLogs.openStream()));
+                String tmp;
+                while ((tmp = in.readLine()) != null) {
+                    tmp = tmp.toLowerCase();
+                    if (tmp.indexOf(COMPARATOR_ERROR) != -1) {
+                        String fileName = new File(comparatorLogs.getFile()).getName();
+                        if (!logs.contains(fileName))
+                            logs.add(fileName);
+                    }
+                }
+                in.close();
 
-			} catch (FileNotFoundException e) {
-				logs.add("Unable to find " + new File(comparatorLogs.getFile()).getName() + " to read.");
-				e.printStackTrace();
-			} catch (IOException e) {
-				logs.add("Unable to read " + new File(comparatorLogs.getFile()).getName());
-				e.printStackTrace();
-			}
-		}
-	}
+            }
+            catch (FileNotFoundException e) {
+                logs.add("Unable to find " + new File(comparatorLogs.getFile()).getName() + " to read.");
+                e.printStackTrace();
+            }
+            catch (IOException e) {
+                logs.add("Unable to read " + new File(comparatorLogs.getFile()).getName());
+                e.printStackTrace();
+            }
+        }
+    }
 
-	/*
-	 * Load the configuration file which should be included in this bundle
-	 */
-	private Properties loadCompareConfiguration() {
-		String aString = System.getProperty("PLUGIN_PATH");
-		if (aString == null)
-			return null;
+    /*
+     * Load the configuration file which should be included in this bundle
+     */
+    private Properties loadCompareConfiguration() {
+        String aString = System.getProperty("PLUGIN_PATH");
+        if (aString == null)
+            return null;
 
-		final String CONFIG_FILENAME = aString + File.separator + "compare.properties";
-		Properties properties = new Properties();
-		try {
-			properties.load(new BufferedInputStream(new FileInputStream(CONFIG_FILENAME)));
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-			return null;
-		} catch (IOException e) {
-			e.printStackTrace();
-			return null;
-		}
+        final String CONFIG_FILENAME = aString + File.separator + "compare.properties";
+        Properties properties = new Properties();
+        try {
+            properties.load(new BufferedInputStream(new FileInputStream(CONFIG_FILENAME)));
+        }
+        catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return null;
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
 
-		return properties;
-	}
+        return properties;
+    }
 
-	private String getVersionCompareCommand() {
-		String javadir = System.getProperty("java.home");
-		return javadir + File.separator + "bin" + File.separator + "java";
-	}
+    private String getVersionCompareCommand() {
+        String javadir = System.getProperty("java.home");
+        return javadir + File.separator + "bin" + File.separator + "java";
+    }
 
-	// private String buildCommandLine(String source, String destination, String
-	// options, String output) {
-	private String getVersionCompareArguments(String source, String destination, String output, String option) {
+    // private String buildCommandLine(String source, String destination, String
+    // options, String output) {
+    private String getVersionCompareArguments(String source, String destination, String output, String option) {
 
-		Bundle bundle = Platform.getBundle("org.eclipse.equinox.launcher");
-		URL u = null;
-		String temp, t = null;
-		try {
-			u = FileLocator.resolve(bundle.getEntry("/"));
-			temp = u.toString();
-			// remove extraneous characters from string that specifies equinox
-			// launcher filesystem location!
-			t = temp.substring(temp.indexOf("/"), temp.lastIndexOf("/") - 1);
-		} catch (IOException e) {
-			e.printStackTrace();
-			return null;
-		}
+        Bundle bundle = Platform.getBundle("org.eclipse.equinox.launcher");
+        URL u = null;
+        String temp, t = null;
+        try {
+            u = FileLocator.resolve(bundle.getEntry("/"));
+            temp = u.toString();
+            // remove extraneous characters from string that specifies equinox
+            // launcher filesystem location!
+            t = temp.substring(temp.indexOf("/"), temp.lastIndexOf("/") - 1);
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
 
-		String command = "-cp " + t
-				+ " org.eclipse.core.launcher.Main -application org.eclipse.pde.tools.versioning.application -clean";
+        String command = "-cp " + t
+                + " org.eclipse.core.launcher.Main -application org.eclipse.pde.tools.versioning.application -clean";
 
-		command += " -new " + source;
-		command += " -old " + destination;
-		command += " -output " + output;
-		if (option != null) {
-			command += " -option " + option;
-		}
+        command += " -new " + source;
+        command += " -old " + destination;
+        command += " -output " + output;
+        if (option != null) {
+            command += " -option " + option;
+        }
 
-		System.out.println("arguments " + command);
-		System.out.println("option " + option);
+        System.out.println("arguments " + command);
+        System.out.println("option " + option);
 
-		return command;
-	}
+        return command;
+    }
 
-	private void verifyCompareResults(String source, String destination, String output) {
-		Document doc = parseResultXML(new File(output));
-		if (doc == null) {
-			String msg = "output file is null";
-			assertTrue(msg, msg == null);
-			return;
-		}
-		NodeList list = doc.getElementsByTagName("Category");
-		int errorNumber = getSubElementNumber("Error", list);
-		int warningNumber = getSubElementNumber("Warning", list);
-		if (errorNumber != 0 || warningNumber != 0) {
-			String msg = "Features included in \"" + source + "\" has been compared to those included in \"" + destination
-					+ "\".\n";
-			msg += "There are " + errorNumber + " error messages and " + warningNumber + " warning messages.\n";
-			msg += "See the version compare logs linked from the test results page for details";
-			assertTrue(msg, msg == null);
-		}
-	}
+    private void verifyCompareResults(String source, String destination, String output) {
+        Document doc = parseResultXML(new File(output));
+        if (doc == null) {
+            String msg = "output file is null";
+            assertTrue(msg, msg == null);
+            return;
+        }
+        NodeList list = doc.getElementsByTagName("Category");
+        int errorNumber = getSubElementNumber("Error", list);
+        int warningNumber = getSubElementNumber("Warning", list);
+        if (errorNumber != 0 || warningNumber != 0) {
+            String msg = "Features included in \"" + source + "\" has been compared to those included in \"" + destination
+                    + "\".\n";
+            msg += "There are " + errorNumber + " error messages and " + warningNumber + " warning messages.\n";
+            msg += "See the version compare logs linked from the test results page for details";
+            assertTrue(msg, msg == null);
+        }
+    }
 
-	/*
-	 * Helper method to perform some action when we are unable to run the
-	 * version compare mechanism.
-	 * 
-	 * For now just print out a message to the console and return.
-	 */
-	private void unableToRunCompare(String message) {
-		System.out.println(message);
-	}
+    /*
+     * Helper method to perform some action when we are unable to run the version compare mechanism.
+     * 
+     * For now just print out a message to the console and return.
+     */
+    private void unableToRunCompare(String message) {
+        System.out.println(message);
+    }
 
-	/**
-	 * Compares the feature and plug-in versions contained in this Eclipse
-	 * configuration, against a known previous Eclipse configuration.
-	 */
-	public void _testVersionCompare() {
+    /**
+     * Compares the feature and plug-in versions contained in this Eclipse configuration, against a known previous Eclipse
+     * configuration.
+     */
+    public void _testVersionCompare() {
 
-		String os = System.getProperty("os.name");
+        String os = System.getProperty("os.name");
 
-		/* Only run compare tool on Linux to save time during tests */
-		if (!os.equalsIgnoreCase("Linux")) {
-			return;
-		}
-		String msg = null;
+        /* Only run compare tool on Linux to save time during tests */
+        if (!os.equalsIgnoreCase("Linux")) {
+            return;
+        }
+        String msg = null;
 
-		Bundle bundle = Platform.getBundle("org.eclipse.pde.tools.versioning");
-		if (bundle == null) {
-			msg = "Version comparison bundle (org.eclipse.pde.tools.versioning) not installed.";
-			unableToRunCompare(msg);
-			assertTrue(msg, msg == null);
-			return;
-		}
-		// load the configuration and ensure the mandatory parameters were
-		// specified
-		Properties properties = loadCompareConfiguration();
-		// assume that #load printed out error message and just return
-		if (properties == null) {
-			msg = "Properties file is null";
-			assertTrue(msg, msg == null);
-			return;
-		}
+        Bundle bundle = Platform.getBundle("org.eclipse.pde.tools.versioning");
+        if (bundle == null) {
+            msg = "Version comparison bundle (org.eclipse.pde.tools.versioning) not installed.";
+            unableToRunCompare(msg);
+            assertTrue(msg, msg == null);
+            return;
+        }
+        // load the configuration and ensure the mandatory parameters were
+        // specified
+        Properties properties = loadCompareConfiguration();
+        // assume that #load printed out error message and just return
+        if (properties == null) {
+            msg = "Properties file is null";
+            assertTrue(msg, msg == null);
+            return;
+        }
 
-		String compareOldPath = properties.getProperty("compare.old");
-		File compareOldFile = compareOldPath == null ? null : new File(compareOldPath);
-		if (compareOldFile == null) {
-			msg = "Old directory not specified.";
-			unableToRunCompare(msg);
-			assertTrue(msg, msg == null);
-			return;
-		}
+        String compareOldPath = properties.getProperty("compare.old");
+        File compareOldFile = compareOldPath == null ? null : new File(compareOldPath);
+        if (compareOldFile == null) {
+            msg = "Old directory not specified.";
+            unableToRunCompare(msg);
+            assertTrue(msg, msg == null);
+            return;
+        }
 
-		/*
-		 * Determine if the build is a nightly Nightly builds have qualifiers
-		 * identical the buildId - for instance N200612080010 which means that
-		 * they are lower than v20060921-1945 from an promoted integration build
-		 * and thus cannot be compared
-		 */
+        /*
+         * Determine if the build is a nightly Nightly builds have qualifiers identical the buildId - for instance N200612080010
+         * which means that they are lower than v20060921-1945 from an promoted integration build and thus cannot be compared
+         */
 
-		// disable temporarily
-		if (compareOldPath == null || compareOldPath.indexOf("N2") > 0) {
-			// if nightly build, skip test
-			return;
-		}
+        // disable temporarily
+        if (compareOldPath == null || compareOldPath.indexOf("N2") > 0) {
+            // if nightly build, skip test
+            return;
+        }
 
-		String compareNewPath = properties.getProperty("compare.new");
-		File compareNewFile = compareNewPath == null ? null : new File(compareNewPath);
-		if (compareNewFile == null) {
-			msg = "New directory not specified.";
-			unableToRunCompare(msg);
-			assertTrue(msg, msg == null);
-			return;
-		}
+        String compareNewPath = properties.getProperty("compare.new");
+        File compareNewFile = compareNewPath == null ? null : new File(compareNewPath);
+        if (compareNewFile == null) {
+            msg = "New directory not specified.";
+            unableToRunCompare(msg);
+            assertTrue(msg, msg == null);
+            return;
+        }
 
-		String outputFileName = properties.getProperty("compare.output");
-		File compareOutputFile = outputFileName == null ? null : new File(outputFileName);
-		if (compareOutputFile == null) {
-			msg = "Output directory not specified.";
-			unableToRunCompare(msg);
-			assertTrue(msg, msg == null);
-			return;
-		}
+        String outputFileName = properties.getProperty("compare.output");
+        File compareOutputFile = outputFileName == null ? null : new File(outputFileName);
+        if (compareOutputFile == null) {
+            msg = "Output directory not specified.";
+            unableToRunCompare(msg);
+            assertTrue(msg, msg == null);
+            return;
+        }
 
-		String compareOptions = properties.getProperty("compare.options");
+        String compareOptions = properties.getProperty("compare.options");
 
-		/*
-		 * String outputFileName =
-		 * Platform.getInstallLocation().getURL().getPath() + ".." +
-		 * File.separator + ".." + File.separator + "results" + File.separator +
-		 * "results.xml"; // A tad bogus but this is where the build wants to
-		 * copy the results from!
-		 * 
-		 * //create the output file try { File outputfile = new
-		 * File(outputFileName); boolean created = outputfile.createNewFile();
-		 * if (created) { } else { msg = "Output dir could not be created.";
-		 * assertTrue(msg, msg == null); } } catch (IOException e) {
-		 * e.printStackTrace(); }
-		 */
+        /*
+         * String outputFileName = Platform.getInstallLocation().getURL().getPath() + ".." + File.separator + ".." + File.separator
+         * + "results" + File.separator + "results.xml"; // A tad bogus but this is where the build wants to copy the results from!
+         * 
+         * //create the output file try { File outputfile = new File(outputFileName); boolean created = outputfile.createNewFile();
+         * if (created) { } else { msg = "Output dir could not be created."; assertTrue(msg, msg == null); } } catch (IOException e)
+         * { e.printStackTrace(); }
+         */
 
-		String command = getVersionCompareCommand();
-		String arguments = getVersionCompareArguments(compareNewPath, compareOldPath, outputFileName, compareOptions);
+        String command = getVersionCompareCommand();
+        String arguments = getVersionCompareArguments(compareNewPath, compareOldPath, outputFileName, compareOptions);
 
-		StringTokenizer tokenizer = new StringTokenizer(arguments);
-		String[] commandArray = new String[tokenizer.countTokens() + 1];
-		commandArray[0] = command;
-		for (int i = 1; tokenizer.hasMoreTokens(); i++)
-			commandArray[i] = tokenizer.nextToken();
+        StringTokenizer tokenizer = new StringTokenizer(arguments);
+        String[] commandArray = new String[tokenizer.countTokens() + 1];
+        commandArray[0] = command;
+        for (int i = 1; tokenizer.hasMoreTokens(); i++)
+            commandArray[i] = tokenizer.nextToken();
 
-		try {
-			Process aProcess = Runtime.getRuntime().exec(commandArray);
-			try {
-				// wait until the comparison finishes
-				aProcess.waitFor();
-			} catch (InterruptedException e) {
-				// ignore
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
+        try {
+            Process aProcess = Runtime.getRuntime().exec(commandArray);
+            try {
+                // wait until the comparison finishes
+                aProcess.waitFor();
+            }
+            catch (InterruptedException e) {
+                // ignore
+            }
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
 
-		// analyze compare result
-		verifyCompareResults(compareNewPath, compareOldPath, outputFileName);
+        // analyze compare result
+        verifyCompareResults(compareNewPath, compareOldPath, outputFileName);
 
-	}
+    }
 
-	/**
-	 * parses the given XML file denoted by <code>file</code> and return
-	 * Document instance of it
-	 * 
-	 * @param file
-	 *            File instance which denoted an XML file
-	 * @return Document instance
-	 */
-	private Document parseResultXML(File file) {
-		try {
-			DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-			return docBuilder.parse(file);
-		} catch (ParserConfigurationException e) {
-			System.out.println("Unable to parse comparison result file.");
-			e.printStackTrace();
-		} catch (FactoryConfigurationError e) {
-			System.out.println("Unable to create XML parser.");
-			e.printStackTrace();
-		} catch (SAXException e) {
-			System.out.println("Unable to parse comparison result file.");
-			e.printStackTrace();
-		} catch (IOException e) {
-			System.out.println("Exception trying to parse comparison result file.");
-			e.printStackTrace();
-		}
-		return null;
-	}
+    /**
+     * parses the given XML file denoted by <code>file</code> and return Document instance of it
+     * 
+     * @param file
+     *            File instance which denoted an XML file
+     * @return Document instance
+     */
+    private Document parseResultXML(File file) {
+        try {
+            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            return docBuilder.parse(file);
+        }
+        catch (ParserConfigurationException e) {
+            System.out.println("Unable to parse comparison result file.");
+            e.printStackTrace();
+        }
+        catch (FactoryConfigurationError e) {
+            System.out.println("Unable to create XML parser.");
+            e.printStackTrace();
+        }
+        catch (SAXException e) {
+            System.out.println("Unable to parse comparison result file.");
+            e.printStackTrace();
+        }
+        catch (IOException e) {
+            System.out.println("Exception trying to parse comparison result file.");
+            e.printStackTrace();
+        }
+        return null;
+    }
 
-	/**
-	 * searches for element whose name attribute equals <code>elementName</code>
-	 * , and return the number of its child nodes if it has been found
-	 * 
-	 * @param elementName
-	 *            value of <code>name</code> attribute
-	 * @param nodeList
-	 *            NodeList instance
-	 * @return number of child nodes of the element whose <code>name</code>
-	 *         attribute equals <code>elementName</code>
-	 */
-	private int getSubElementNumber(String elementName, NodeList nodeList) {
-		for (int i = 0; i < nodeList.getLength(); i++) {
-			Element element = ((Element) nodeList.item(i));
-			if (element.getAttribute("Name").equals(elementName))
-				return element.getChildNodes().getLength();
-		}
-		return 0;
-	}
+    /**
+     * searches for element whose name attribute equals <code>elementName</code> , and return the number of its child nodes if it
+     * has been found
+     * 
+     * @param elementName
+     *            value of <code>name</code> attribute
+     * @param nodeList
+     *            NodeList instance
+     * @return number of child nodes of the element whose <code>name</code> attribute equals <code>elementName</code>
+     */
+    private int getSubElementNumber(String elementName, NodeList nodeList) {
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Element element = ((Element) nodeList.item(i));
+            if (element.getAttribute("Name").equals(elementName))
+                return element.getChildNodes().getLength();
+        }
+        return 0;
+    }
 
-	/**
-	 * check whether or not the given file potentially represents a platform
-	 * configuration file on the file-system.
-	 * 
-	 * @return <code>true</code> if <code>file</code> is a configuration file
-	 *         <code>false</code> otherwise
-	 * 
-	 *         private boolean isConfiguration(File file) { IPath path = new
-	 *         Path(file.getAbsolutePath()); return file.isFile() &&
-	 *         "platform.xml".equalsIgnoreCase(path.lastSegment()); }
-	 */
+    /**
+     * check whether or not the given file potentially represents a platform configuration file on the file-system.
+     * 
+     * @return <code>true</code> if <code>file</code> is a configuration file <code>false</code> otherwise
+     * 
+     *         private boolean isConfiguration(File file) { IPath path = new Path(file.getAbsolutePath()); return file.isFile() &&
+     *         "platform.xml".equalsIgnoreCase(path.lastSegment()); }
+     */
 }
