diff options
author | Andy Clement <aclement@pivotal.io> | 2019-11-29 11:36:58 -0800 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-11-29 11:36:58 -0800 |
commit | 17026e35243f229c2e3c07c292f2caaac65503a4 (patch) | |
tree | ac7d72940ca7c36e3358c8bf341a36d560741ef2 /testing | |
parent | c3c07fdb4b93cc483317d8a314233f0b9dcf4d8b (diff) | |
download | aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.tar.gz aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.zip |
polish
Diffstat (limited to 'testing')
4 files changed, 1765 insertions, 1723 deletions
diff --git a/testing/src/test/java/org/aspectj/testing/harness/bridge/AbstractRunSpec.java b/testing/src/test/java/org/aspectj/testing/harness/bridge/AbstractRunSpec.java index 4e61a512c..9e302f41f 100644 --- a/testing/src/test/java/org/aspectj/testing/harness/bridge/AbstractRunSpec.java +++ b/testing/src/test/java/org/aspectj/testing/harness/bridge/AbstractRunSpec.java @@ -1,14 +1,14 @@ /* ******************************************************************* - * Copyright (c) 1999-2001 Xerox Corporation, + * Copyright (c) 1999-2001 Xerox Corporation, * 2002 Palo Alto Research Center, Incorporated (PARC). - * 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: - * Xerox/PARC initial implementation + * 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: + * Xerox/PARC initial implementation * Wes Isberg 2004 updates * ******************************************************************/ @@ -62,7 +62,7 @@ import org.aspectj.util.LangUtil; * <u>Coordination with writers</u>: because this reads the contents of values written by IXmlWritable, they should ensure their * values are readable. When flattening and unflattening lists, the convention is to use the {un}flattenList(..) methods in * XMLWriter. - * + * * @see XMLWriter@unflattenList(String) * @see XMLWriter@flattenList(List) */ @@ -114,7 +114,7 @@ abstract public class AbstractRunSpec implements IRunSpec { // XXXXXunused sourceLocations = new ArrayList(); keywords = new ArrayList<String>(); children = new ArrayList<IRunSpec>(); - dirChanges = new ArrayList(); + dirChanges = new ArrayList<>(); xmlNames = XMLNames.DEFAULT; runtime = new RT(); this.skipIfAnyChildSkipped = skipIfAnyChildSkipped; @@ -191,8 +191,8 @@ abstract public class AbstractRunSpec implements IRunSpec { public void addKeywords(String[] ra) { if (null != ra) { - for (int i = 0; i < ra.length; i++) { - addKeyword(ra[i]); + for (String element : ra) { + addKeyword(element); } } } @@ -210,7 +210,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** @return String[] of options */ public String[] getOptionsArray() { - return (String[]) options.toArray(new String[0]); + return options.toArray(new String[0]); } public void setOption(String option) { @@ -231,7 +231,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Set options, removing any existing options. - * + * * @param options String[] options to use - may be null or empty */ public void setOptionsArray(String[] options) { @@ -249,8 +249,8 @@ abstract public class AbstractRunSpec implements IRunSpec { public void addOptions(String[] ra) { if (null != ra) { - for (int i = 0; i < ra.length; i++) { - addOption(ra[i]); + for (String element : ra) { + addOption(element); } } } @@ -263,7 +263,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** @return String[] of paths */ public String[] getPathsArray() { - return (String[]) paths.toArray(new String[0]); + return paths.toArray(new String[0]); } public void setPath(String path) { @@ -288,8 +288,8 @@ abstract public class AbstractRunSpec implements IRunSpec { public void addPaths(String[] ra) { if (null != ra) { - for (int i = 0; i < ra.length; i++) { - addPath(ra[i]); + for (String element : ra) { + addPath(element); } } } @@ -327,8 +327,8 @@ abstract public class AbstractRunSpec implements IRunSpec { public void addMessages(String items) { if (null != items) { String[] ra = XMLWriter.unflattenList(items); - for (int i = 0; i < ra.length; i++) { - addMessage(ra[i]); + for (String element : ra) { + addMessage(element); } } } @@ -395,7 +395,7 @@ abstract public class AbstractRunSpec implements IRunSpec { * or the child's adoptParentValues(..) should add one info message with the reason this is being skipped. The only reason to * override this would be to NOT invoke the same for children, or to do something similar for children which are not * AbstractRunSpec. - * + * * @param parentRuntime the RT values to adopt - ignored if null * @param handler the IMessageHandler for info messages when skipping * @return false if this wants to be skipped, true otherwise @@ -437,7 +437,7 @@ abstract public class AbstractRunSpec implements IRunSpec { * adds any non-null options we don't already have. setting verbose and adding to parent options. Implementors override this to * affect how parent values are adopted. Implementors should not recurse into children. This method may be called multiple * times, so implementors should not destroy any spec information. Always add an info message when returning false to skip - * + * * @param parentRuntime the RT values to adopt - never null * @return false if this wants to be skipped, true otherwise */ @@ -456,7 +456,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Implementations call this when signalling skips to ensure consistency in message formatting - * + * * @param handler the IMessageHandler sink - not null * @param reason the String reason to skip - not null */ @@ -473,7 +473,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Control XML output by renaming or suppressing output for attributes and subelements. Subelements are skipped by setting the * XMLNames booleans to false. Attributes are skipped by setting their name to null. - * + * * @param names XMLNames with new names and/or suppress flags. */ protected void setXMLNames(XMLNames names) { @@ -504,7 +504,7 @@ abstract public class AbstractRunSpec implements IRunSpec { return ((!LangUtil.isEmpty(xmlNames.descriptionName) && !LangUtil.isEmpty(description)) || (!LangUtil.isEmpty(xmlNames.keywordsName) && !LangUtil.isEmpty(keywords)) || (!LangUtil.isEmpty(xmlNames.optionsName) && !LangUtil.isEmpty(options)) || (!LangUtil - .isEmpty(xmlNames.pathsName) && !LangUtil.isEmpty(paths))); + .isEmpty(xmlNames.pathsName) && !LangUtil.isEmpty(paths))); } /** @@ -539,11 +539,12 @@ abstract public class AbstractRunSpec implements IRunSpec { * The default implementation writes everything as attributes, then subelements for dirChanges, messages, then subelements for * children. Subclasses that override may delegate back for any of these. Subclasses may also set XMLNames to name or suppress * any attribute or subelement. - * + * * @see writeMessages(XMLWriter) * @see writeChildren(XMLWriter) * @see IXmlWritable#writeXml(XMLWriter) */ + @Override public void writeXml(XMLWriter out) { out.startElement(xmlElementName, false); writeAttributes(out); @@ -572,8 +573,8 @@ abstract public class AbstractRunSpec implements IRunSpec { */ protected void writeChildren(XMLWriter out) { if (0 < children.size()) { - for (Iterator<IRunSpec> iter = children.iterator(); iter.hasNext();) { - IXmlWritable self = (IXmlWritable) iter.next(); + for (IRunSpec iRunSpec : children) { + IXmlWritable self = iRunSpec; self.writeXml(out); } } @@ -583,8 +584,8 @@ abstract public class AbstractRunSpec implements IRunSpec { public void printAll(PrintStream out, String prefix) { out.println(prefix + toString()); - for (Iterator<IRunSpec> iter = children.iterator(); iter.hasNext();) { - AbstractRunSpec child = (AbstractRunSpec) iter.next(); // IRunSpec + for (IRunSpec iRunSpec : children) { + AbstractRunSpec child = (AbstractRunSpec) iRunSpec; // IRunSpec child.printAll(out, prefix + " "); } } @@ -592,7 +593,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * default implementation returns the description if not empty or the unqualified class name otherwise. Subclasses should not * call toString from here unless they reimplement it. - * + * * @return name of this thing or type */ protected String getPrintName() { @@ -604,6 +605,7 @@ abstract public class AbstractRunSpec implements IRunSpec { } /** @return summary count of spec elements */ + @Override public String toString() { return getPrintName() + "(" + containedSummary() + ")"; } @@ -646,9 +648,7 @@ abstract public class AbstractRunSpec implements IRunSpec { */ spec.badInput = badInput; spec.children.clear(); - for (Iterator<IRunSpec> iter = children.iterator(); iter.hasNext();) { - // clone these... - IRunSpec child = iter.next(); + for (IRunSpec child : children) { // require all child classes to support clone? if (child instanceof AbstractRunSpec) { spec.addChild((AbstractRunSpec) ((AbstractRunSpec) child).clone()); @@ -728,6 +728,7 @@ abstract public class AbstractRunSpec implements IRunSpec { final boolean skipMessages; final boolean skipChildren; + @Override protected Object clone() { return new XMLNames(null, descriptionName, sourceLocationName, keywordsName, optionsName, pathsName, commentName, stagingName, badInputName, skipDirChanges, skipMessages, skipChildren); @@ -767,6 +768,7 @@ abstract public class AbstractRunSpec implements IRunSpec { } /** subclasses implement this to create and set up a run */ + @Override abstract public IRunIterator makeRunIterator(Sandbox sandbox, Validator validator); /** segregate runtime-only state in spec */ @@ -788,15 +790,15 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Set parent options - old options destroyed. Will result in duplicates if duplicates added. Null or empty entries are * ignored - * + * * @param options ignored if null or empty */ public void setOptions(String[] options) { parentOptions.clear(); if (!LangUtil.isEmpty(options)) { - for (int i = 0; i < options.length; i++) { - if (!LangUtil.isEmpty(options[i])) { - parentOptions.add(options[i]); + for (String option : options) { + if (!LangUtil.isEmpty(option)) { + parentOptions.add(option); } } } @@ -804,7 +806,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Copy values from another RT - * + * * @param toCopy the RT to copy from * @throws IllegalArgumentException if toCopy is null */ @@ -817,11 +819,11 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Return any parent option accepted by validOptions, optionally removing the parent option. - * + * * @param validOptions String[] of options to extract * @param remove if true, then remove any parent option matched * @return String[] containing any validOptions[i] in parentOptions - * + * */ public Values extractOptions(Options validOptions, boolean remove, StringBuffer errors) { Values result = Values.EMPTY; @@ -836,7 +838,7 @@ abstract public class AbstractRunSpec implements IRunSpec { return result; } // boolean haveOption = false; - String[] parents = (String[]) parentOptions.toArray(new String[0]); + String[] parents = parentOptions.toArray(new String[0]); try { result = validOptions.acceptInput(parents); } catch (InvalidInputException e) { @@ -869,7 +871,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Return any parent option which has one of validOptions as a prefix, optionally absorbing (removing) the parent option. - * + * * @param validOptions String[] of options to extract * @param absorb if true, then remove any parent option matched * @return String[] containing any validOptions[i] in parentOptions (at most once) @@ -880,8 +882,7 @@ abstract public class AbstractRunSpec implements IRunSpec { } ArrayList<String> result = new ArrayList<String>(); // boolean haveOption = false; - for (int i = 0; i < validOptions.length; i++) { - String option = validOptions[i]; + for (String option : validOptions) { if (LangUtil.isEmpty(option)) { continue; } @@ -895,7 +896,7 @@ abstract public class AbstractRunSpec implements IRunSpec { } } } - return (String[]) result.toArray(new String[0]); + return result.toArray(new String[0]); } /** Get ListIterator that permits removals */ @@ -905,7 +906,7 @@ abstract public class AbstractRunSpec implements IRunSpec { /** * Enable verbose logging - * + * * @param verbose if true, do verbose logging */ public void setVerbose(boolean verbose) { diff --git a/testing/src/test/java/org/aspectj/testing/harness/bridge/AjcSpecTest.java b/testing/src/test/java/org/aspectj/testing/harness/bridge/AjcSpecTest.java index 36ade5f2a..4d1a47ceb 100644 --- a/testing/src/test/java/org/aspectj/testing/harness/bridge/AjcSpecTest.java +++ b/testing/src/test/java/org/aspectj/testing/harness/bridge/AjcSpecTest.java @@ -1,14 +1,14 @@ /* ******************************************************************* - * Copyright (c) 1999-2001 Xerox Corporation, + * Copyright (c) 1999-2001 Xerox Corporation, * 2002 Palo Alto Research Center, Incorporated (PARC). - * 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: - * Xerox/PARC initial implementation + * 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: + * Xerox/PARC initial implementation * ******************************************************************/ package org.aspectj.testing.harness.bridge; @@ -32,310 +32,310 @@ import junit.framework.TestCase; * Primarily used by others to test AjcTest */ public class AjcSpecTest extends TestCase { - public static final String NOTSAME = " != "; - public static void sameAjcSuiteSpec( - AjcTest.Suite.Spec lhsSpec, - AjcTest.Suite.Spec rhsSpec, - Assert a) { - assertNotNull(lhsSpec); - assertNotNull(rhsSpec); - Iterator lhs = lhsSpec.getChildren().iterator(); - Iterator rhs = rhsSpec.getChildren().iterator(); - while (lhs.hasNext() && rhs.hasNext()) { - AjcTest.Spec lhsTest = (AjcTest.Spec) lhs.next(); - AjcTest.Spec rhsTest = (AjcTest.Spec) rhs.next(); - AjcSpecTest.sameAjcTestSpec(lhsTest, rhsTest, a); - } - assertTrue(!lhs.hasNext()); - assertTrue(!rhs.hasNext()); - } + public static final String NOTSAME = " != "; + public static void sameAjcSuiteSpec( + AjcTest.Suite.Spec lhsSpec, + AjcTest.Suite.Spec rhsSpec, + Assert a) { + assertNotNull(lhsSpec); + assertNotNull(rhsSpec); + Iterator lhs = lhsSpec.getChildren().iterator(); + Iterator rhs = rhsSpec.getChildren().iterator(); + while (lhs.hasNext() && rhs.hasNext()) { + AjcTest.Spec lhsTest = (AjcTest.Spec) lhs.next(); + AjcTest.Spec rhsTest = (AjcTest.Spec) rhs.next(); + AjcSpecTest.sameAjcTestSpec(lhsTest, rhsTest, a); + } + assertTrue(!lhs.hasNext()); + assertTrue(!rhs.hasNext()); + } public static void sameAjcTestSpec( - AjcTest.Spec lhsTest, - AjcTest.Spec rhsTest, - Assert a) { - assertNotNull(lhsTest); - assertNotNull(rhsTest); - assertEquals(lhsTest.getBugId(), rhsTest.getBugId()); - assertEquals(lhsTest.getTestDirOffset(), rhsTest.getTestDirOffset()); - // XXX suiteDir varies by run.. - // description, options, paths, comments, keywords - sameAbstractRunSpec(lhsTest, rhsTest, a); + AjcTest.Spec lhsTest, + AjcTest.Spec rhsTest, + Assert a) { + assertNotNull(lhsTest); + assertNotNull(rhsTest); + assertEquals(lhsTest.getBugId(), rhsTest.getBugId()); + assertEquals(lhsTest.getTestDirOffset(), rhsTest.getTestDirOffset()); + // XXX suiteDir varies by run.. + // description, options, paths, comments, keywords + sameAbstractRunSpec(lhsTest, rhsTest, a); } public static void sameAbstractRunSpec( - AbstractRunSpec lhs, - AbstractRunSpec rhs, - Assert a) { - assertEquals(lhs.description, rhs.description); - // XXX keywords added in .txt reading - - //sameList(lhs.getKeywordsList(), rhs.getKeywordsList(), a); - // XXX sameList(lhs.globalOptions, rhs.globalOptions, a); - sameList(lhs.getOptionsList(), rhs.getOptionsList(), a); - sameList(lhs.getPathsList(), rhs.getPathsList(), a); - assertEquals(lhs.isStaging(), rhs.isStaging()); - sameList(lhs.keywords, rhs.keywords, a); - assertEquals(lhs.comment, rhs.comment); - assertEquals(lhs.badInput, rhs.badInput); - // xml adds sourceloc? - //sameSourceLocation(lhs.getSourceLocation(), rhs.getSourceLocation(), a); - // XXX also sourceLocations? - sameMessages(lhs.getMessages(), rhs.getMessages(), a); + AbstractRunSpec lhs, + AbstractRunSpec rhs, + Assert a) { + assertEquals(lhs.description, rhs.description); + // XXX keywords added in .txt reading - + //sameList(lhs.getKeywordsList(), rhs.getKeywordsList(), a); + // XXX sameList(lhs.globalOptions, rhs.globalOptions, a); + sameList(lhs.getOptionsList(), rhs.getOptionsList(), a); + sameList(lhs.getPathsList(), rhs.getPathsList(), a); + assertEquals(lhs.isStaging(), rhs.isStaging()); + sameList(lhs.keywords, rhs.keywords, a); + assertEquals(lhs.comment, rhs.comment); + assertEquals(lhs.badInput, rhs.badInput); + // xml adds sourceloc? + //sameSourceLocation(lhs.getSourceLocation(), rhs.getSourceLocation(), a); + // XXX also sourceLocations? + sameMessages(lhs.getMessages(), rhs.getMessages(), a); + } + + /** @return normal form - null is "", "" is "", and others are {fully.qualified.class}.toString().trim() */ + static String normal(Object input) { + if ((null == input) || ("".equals(input))) { + return ""; + } else { + return input.getClass().getName() + "." + input.toString().trim(); + } } - /** @return normal form - null is "", "" is "", and others are {fully.qualified.class}.toString().trim() */ - static String normal(Object input) { - if ((null == input) || ("".equals(input))) { - return ""; - } else { - return input.getClass().getName() + "." + input.toString().trim(); - } - } + /** @return true if these match after normalizing */ + public static void same(Object lhs, Object rhs, Assert a) { + lhs = normal(lhs); + rhs = normal(rhs); + assertTrue(lhs + NOTSAME + rhs, lhs.equals(rhs)); + } - /** @return true if these match after normalizing */ - public static void same(Object lhs, Object rhs, Assert a) { - lhs = normal(lhs); - rhs = normal(rhs); - assertTrue(lhs + NOTSAME + rhs, lhs.equals(rhs)); - } - - /** @return true if both are empty (null or no entries) or if all match */ - public static void sameRA(String[] lhs, String[] rhs, Assert a) { - if (null == lhs) { - assertTrue((null == rhs) || (0 == rhs.length)); - } else if (null == rhs) { - assertTrue(0 == lhs.length); - } else { - String l = normal(lhs); - String r = normal(rhs); - assertTrue(l + NOTSAME + r, l.equals(r)); - } - } - - /** @return normal form for String[] items*/ - static String normal(String[] items) { - return (null == items ? "[]" : normal(Arrays.asList(items))); - } - - /** @return normal form for list items */ - static String normal(List list) { - StringBuffer sb = new StringBuffer(); - sb.append("["); - boolean first = true; - for (Iterator iter = list.iterator(); iter.hasNext();) { - Object o = iter.next(); - if (!first) { - sb.append(", "); - } else { - first = false; - } - sb.append(normal(o)); - } - sb.append("]"); - return sb.toString(); - } - - /** @return true if both are empty (null or no entries) or if all match after trimming */ - public static void sameListSize(List lhs, List rhs) { - if (null == lhs) { - assertTrue((null == rhs) || (0 == rhs.size())); - } else if (null == rhs) { - assertTrue(0 == lhs.size()); - } else { - assertTrue(rhs.size() == lhs.size()); - } - } + /** @return true if both are empty (null or no entries) or if all match */ + public static void sameRA(String[] lhs, String[] rhs, Assert a) { + if (null == lhs) { + assertTrue((null == rhs) || (0 == rhs.length)); + } else if (null == rhs) { + assertTrue(0 == lhs.length); + } else { + String l = normal(lhs); + String r = normal(rhs); + assertTrue(l + NOTSAME + r, l.equals(r)); + } + } - /** @return true if both are empty (null or no entries) or if all match after trimming */ - public static void sameList(List lhs, List rhs, Assert a) { - sameListSize(lhs, rhs); - String l = normal(lhs); - String r = normal(rhs); - String label = l + NOTSAME + r; - assertTrue(label, l.equals(r)); - } - -// /** -// * Normalize and compare: -// * <li>bug id's are not compared since extracted during xml writing</li> -// * <li>keyword compare is disabled since keywords are generated during xml reading.</li> -// * <li>description compare is normalized by stripping bug ids</li> -// * <li>String and arrays are equal when empty (null or 0-length)</li> -// * @see Ajctest#stripBugId(String) -// */ -// public static void sameAjcTest(AjcTest lhs, AjcTest rhs, Assert reporter) { -// Assert a = reporter; -// String label = lhs + NOTSAME + rhs; -// assertTrue(label, null != lhs); -// assertTrue(label, null != rhs); -// //assertTrue(label, lhs.ignoreWarnings == rhs.ignoreWarnings); -// // XXX disabled - not in .txt -// // sameStringList(lhs.keywords, rhs.keywords, a); -// // sameString(lhs.bugId, rhs.bugId, a); -// // argh - bugid stripped from description -// //same(AjcTest.stripBugId(lhs.description), AjcTest.stripBugId(lhs.description), a); -// //sameRA(lhs.globals, rhs.globals, a); -// //lhs.reset(); -// //rhs.reset(); -// boolean gotOne = false; -// IMessageHolder holder = new MessageHandler(); -// assertTrue(label, !holder.hasAnyMessage(IMessage.FAIL, IMessageHolder.ORGREATER)); -// while (lhs.hasNextRun() && rhs.hasNextRun()) { -// sameIAjcRun((IAjcRun) lhs.nextRun(holder), (IAjcRun) rhs.nextRun(holder), reporter); -// assertTrue(label, !holder.hasAnyMessage(IMessage.FAIL, IMessageHolder.ORGREATER)); -// if (!gotOne) { -// gotOne = true; -// } -// } -// assertTrue(label, gotOne); -// assertTrue(label, !lhs.hasNextRun()); -// assertTrue(label, !rhs.hasNextRun()); -// } + /** @return normal form for String[] items*/ + static String normal(String[] items) { + return (null == items ? "[]" : normal(Arrays.asList(items))); + } + + /** @return normal form for list items */ + static String normal(List list) { + StringBuffer sb = new StringBuffer(); + sb.append("["); + boolean first = true; + for (Iterator iter = list.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (!first) { + sb.append(", "); + } else { + first = false; + } + sb.append(normal(o)); + } + sb.append("]"); + return sb.toString(); + } + + /** @return true if both are empty (null or no entries) or if all match after trimming */ + public static void sameListSize(List lhs, List rhs) { + if (null == lhs) { + assertTrue((null == rhs) || (0 == rhs.size())); + } else if (null == rhs) { + assertTrue(0 == lhs.size()); + } else { + assertTrue(rhs.size() == lhs.size()); + } + } + + /** @return true if both are empty (null or no entries) or if all match after trimming */ + public static void sameList(List lhs, List rhs, Assert a) { + sameListSize(lhs, rhs); + String l = normal(lhs); + String r = normal(rhs); + String label = l + NOTSAME + r; + assertTrue(label, l.equals(r)); + } + + // /** + // * Normalize and compare: + // * <li>bug id's are not compared since extracted during xml writing</li> + // * <li>keyword compare is disabled since keywords are generated during xml reading.</li> + // * <li>description compare is normalized by stripping bug ids</li> + // * <li>String and arrays are equal when empty (null or 0-length)</li> + // * @see Ajctest#stripBugId(String) + // */ + // public static void sameAjcTest(AjcTest lhs, AjcTest rhs, Assert reporter) { + // Assert a = reporter; + // String label = lhs + NOTSAME + rhs; + // assertTrue(label, null != lhs); + // assertTrue(label, null != rhs); + // //assertTrue(label, lhs.ignoreWarnings == rhs.ignoreWarnings); + // // XXX disabled - not in .txt + // // sameStringList(lhs.keywords, rhs.keywords, a); + // // sameString(lhs.bugId, rhs.bugId, a); + // // argh - bugid stripped from description + // //same(AjcTest.stripBugId(lhs.description), AjcTest.stripBugId(lhs.description), a); + // //sameRA(lhs.globals, rhs.globals, a); + // //lhs.reset(); + // //rhs.reset(); + // boolean gotOne = false; + // IMessageHolder holder = new MessageHandler(); + // assertTrue(label, !holder.hasAnyMessage(IMessage.FAIL, IMessageHolder.ORGREATER)); + // while (lhs.hasNextRun() && rhs.hasNextRun()) { + // sameIAjcRun((IAjcRun) lhs.nextRun(holder), (IAjcRun) rhs.nextRun(holder), reporter); + // assertTrue(label, !holder.hasAnyMessage(IMessage.FAIL, IMessageHolder.ORGREATER)); + // if (!gotOne) { + // gotOne = true; + // } + // } + // assertTrue(label, gotOne); + // assertTrue(label, !lhs.hasNextRun()); + // assertTrue(label, !rhs.hasNextRun()); + // } public static void sameIAjcRun(IAjcRun lhs, IAjcRun rhs, Assert reporter) { -// Assert a = reporter; - assertTrue(lhs != null); - assertTrue(rhs != null); - Class c = lhs.getClass(); - assertTrue(c == rhs.getClass()); - AbstractRunSpec lhsSpec; - AbstractRunSpec rhsSpec; - - if (c == CompilerRun.class) { - CompilerRun.Spec l = ((CompilerRun) lhs).spec; - CompilerRun.Spec r = ((CompilerRun) rhs).spec; - lhsSpec = l; - rhsSpec = r; - assertEquals(l.argfiles, r.argfiles); - assertEquals(l.aspectpath, r.aspectpath); - assertEquals(l.testSrcDirOffset, r.testSrcDirOffset); - assertEquals(l.compiler, r.compiler); - assertEquals(l.includeClassesDir, r.includeClassesDir); - assertEquals(l.reuseCompiler, r.reuseCompiler); - assertEquals(l.sourceroots, r.sourceroots); - assertEquals(l.extdirs, r.extdirs); - } else if (c == JavaRun.class) { - JavaRun.Spec l = ((JavaRun) lhs).spec; - JavaRun.Spec r = ((JavaRun) rhs).spec; - lhsSpec = l; - rhsSpec = r; - assertTrue(l.skipTester == r.skipTester); - assertEquals(l.className, r.className); - assertEquals(l.javaVersion, r.javaVersion); - assertEquals(l.skipTester, r.skipTester); - assertEquals(l.outStreamIsError, r.outStreamIsError); - assertEquals(l.errStreamIsError, r.errStreamIsError); - } else if (c == IncCompilerRun.class) { - IncCompilerRun.Spec l = ((IncCompilerRun) lhs).spec; - IncCompilerRun.Spec r = ((IncCompilerRun) rhs).spec; - lhsSpec = l; - rhsSpec = r; - assertEquals(l.tag, r.tag); - assertEquals(l.fresh, r.fresh); - } else { - assertTrue(lhs.equals(rhs)); - return; - } - sameSpec(lhsSpec, rhsSpec, reporter); + // Assert a = reporter; + assertTrue(lhs != null); + assertTrue(rhs != null); + Class c = lhs.getClass(); + assertTrue(c == rhs.getClass()); + AbstractRunSpec lhsSpec; + AbstractRunSpec rhsSpec; + + if (c == CompilerRun.class) { + CompilerRun.Spec l = ((CompilerRun) lhs).spec; + CompilerRun.Spec r = ((CompilerRun) rhs).spec; + lhsSpec = l; + rhsSpec = r; + assertEquals(l.argfiles, r.argfiles); + assertEquals(l.aspectpath, r.aspectpath); + assertEquals(l.testSrcDirOffset, r.testSrcDirOffset); + assertEquals(l.compiler, r.compiler); + assertEquals(l.includeClassesDir, r.includeClassesDir); + assertEquals(l.reuseCompiler, r.reuseCompiler); + assertEquals(l.sourceroots, r.sourceroots); + assertEquals(l.extdirs, r.extdirs); + } else if (c == JavaRun.class) { + JavaRun.Spec l = ((JavaRun) lhs).spec; + JavaRun.Spec r = ((JavaRun) rhs).spec; + lhsSpec = l; + rhsSpec = r; + assertTrue(l.skipTester == r.skipTester); + assertEquals(l.className, r.className); + assertEquals(l.javaVersion, r.javaVersion); + assertEquals(l.skipTester, r.skipTester); + assertEquals(l.outStreamIsError, r.outStreamIsError); + assertEquals(l.errStreamIsError, r.errStreamIsError); + } else if (c == IncCompilerRun.class) { + IncCompilerRun.Spec l = ((IncCompilerRun) lhs).spec; + IncCompilerRun.Spec r = ((IncCompilerRun) rhs).spec; + lhsSpec = l; + rhsSpec = r; + assertEquals(l.tag, r.tag); + assertEquals(l.fresh, r.fresh); + } else { + assertTrue(lhs.equals(rhs)); + return; + } + sameSpec(lhsSpec, rhsSpec, reporter); } public static void sameSpec(AbstractRunSpec lhs, AbstractRunSpec rhs, Assert a) { - if ((null == lhs) && (null == rhs)) { - return; - } - assertTrue(lhs != null); - assertTrue(rhs != null); - assertEquals(""+lhs.getOptionsList(), ""+rhs.getOptionsList()); - sameList(lhs.getPathsList(), rhs.getPathsList(), a); - sameMessages(lhs.getMessages(), rhs.getMessages(), a); - sameDirChangesList(lhs.dirChanges, rhs.dirChanges, a); + if ((null == lhs) && (null == rhs)) { + return; + } + assertTrue(lhs != null); + assertTrue(rhs != null); + assertEquals(""+lhs.getOptionsList(), ""+rhs.getOptionsList()); + sameList(lhs.getPathsList(), rhs.getPathsList(), a); + sameMessages(lhs.getMessages(), rhs.getMessages(), a); + sameDirChangesList(lhs.dirChanges, rhs.dirChanges, a); + } + + public static void sameDirChangesList(ArrayList<DirChanges.Spec> lhs, ArrayList<DirChanges.Spec> rhs, Assert a) { + if ((null == lhs) && (null == rhs)) { + return; + } + assertTrue(rhs != null); + assertTrue(lhs != null); + sameListSize(lhs, rhs); + Iterator<DirChanges.Spec> lhsIter = lhs.iterator(); + Iterator<DirChanges.Spec> rhsIter = rhs.iterator(); + while (lhsIter.hasNext() && rhsIter.hasNext()) { + sameDirChangesSpec(lhsIter.next(), rhsIter.next(), a); + } } - public static void sameDirChangesList(ArrayList lhs, ArrayList rhs, Assert a) { - if ((null == lhs) && (null == rhs)) { - return; - } - assertTrue(rhs != null); - assertTrue(lhs != null); - sameListSize(lhs, rhs); - Iterator lhsIter = lhs.iterator(); - Iterator rhsIter = rhs.iterator(); - while (lhsIter.hasNext() && rhsIter.hasNext()) { - sameDirChangesSpec((DirChanges.Spec) lhsIter.next(), (DirChanges.Spec) rhsIter.next(), a); - } + public static void sameDirChangesSpec(DirChanges.Spec lhs, DirChanges.Spec rhs, Assert a) { + if ((null == lhs) && (null == rhs)) { + return; + } + assertTrue(rhs != null); + assertTrue(lhs != null); + assertEquals(lhs.defaultSuffix, rhs.defaultSuffix); + assertEquals(lhs.dirToken, rhs.dirToken); + assertEquals(lhs.fastFail, rhs.fastFail); + assertEquals(lhs.expDir, rhs.expDir); // XXX normalize? + sameList(lhs.updated, rhs.updated, a); + sameList(lhs.removed, rhs.removed, a); + sameList(lhs.added, rhs.added, a); } - public static void sameDirChangesSpec(DirChanges.Spec lhs, DirChanges.Spec rhs, Assert a) { - if ((null == lhs) && (null == rhs)) { - return; - } - assertTrue(rhs != null); - assertTrue(lhs != null); - assertEquals(lhs.defaultSuffix, rhs.defaultSuffix); - assertEquals(lhs.dirToken, rhs.dirToken); - assertEquals(lhs.fastFail, rhs.fastFail); - assertEquals(lhs.expDir, rhs.expDir); // XXX normalize? - sameList(lhs.updated, rhs.updated, a); - sameList(lhs.removed, rhs.removed, a); - sameList(lhs.added, rhs.added, a); - } + public static void sameMessages(IMessageHolder one, IMessageHolder two, Assert a) { + if ((null == one) && (null == two)) { + return; + } + // order matters here + ListIterator lhs = one.getUnmodifiableListView().listIterator(); + ListIterator rhs = two.getUnmodifiableListView().listIterator(); + while (lhs.hasNext() && rhs.hasNext()) { + sameMessage((IMessage) lhs.next(), (IMessage) rhs.next(), a); + } + assertTrue(!lhs.hasNext()); + assertTrue(!rhs.hasNext()); + } - public static void sameMessages(IMessageHolder one, IMessageHolder two, Assert a) { - if ((null == one) && (null == two)) { - return; - } - // order matters here - ListIterator lhs = one.getUnmodifiableListView().listIterator(); - ListIterator rhs = two.getUnmodifiableListView().listIterator(); - while (lhs.hasNext() && rhs.hasNext()) { - sameMessage((IMessage) lhs.next(), (IMessage) rhs.next(), a); - } - assertTrue(!lhs.hasNext()); - assertTrue(!rhs.hasNext()); - } + public static void sameMessage(IMessage lhs, IMessage rhs, Assert a) { + if ((null == lhs) && (null == rhs)) { + return; + } + assertTrue(lhs != null); + assertTrue(rhs != null); + assertTrue(lhs.getKind() == rhs.getKind()); + same(lhs.getMessage(), rhs.getMessage(), a); + same(lhs.getDetails(), rhs.getDetails(), a); + assertEquals(lhs.getThrown(), rhs.getThrown()); + sameSourceLocation(lhs.getSourceLocation(), rhs.getSourceLocation()); + sameSourceLocations(lhs.getExtraSourceLocations(), rhs.getExtraSourceLocations()); + } + public static void sameSourceLocations(List lhs, List rhs) { + sameListSize(lhs, rhs); + if ((null == lhs) || (0 == lhs.size())) { + return; + } + // ok, do order-dependent check.. + ListIterator iterLeft = lhs.listIterator(); + ListIterator iterRight = rhs.listIterator(); + while (iterLeft.hasNext() && iterRight.hasNext()) { + ISourceLocation left = (ISourceLocation) iterLeft.next(); + ISourceLocation right = (ISourceLocation) iterRight.next(); + sameSourceLocation(left, right); + } + assertTrue(!iterLeft.hasNext()); + assertTrue(!iterRight.hasNext()); - public static void sameMessage(IMessage lhs, IMessage rhs, Assert a) { - if ((null == lhs) && (null == rhs)) { - return; - } - assertTrue(lhs != null); - assertTrue(rhs != null); - assertTrue(lhs.getKind() == rhs.getKind()); - same(lhs.getMessage(), rhs.getMessage(), a); - same(lhs.getDetails(), rhs.getDetails(), a); - assertEquals(lhs.getThrown(), rhs.getThrown()); - sameSourceLocation(lhs.getSourceLocation(), rhs.getSourceLocation()); - sameSourceLocations(lhs.getExtraSourceLocations(), rhs.getExtraSourceLocations()); } - public static void sameSourceLocations(List lhs, List rhs) { - sameListSize(lhs, rhs); - if ((null == lhs) || (0 == lhs.size())) { - return; - } - // ok, do order-dependent check.. - ListIterator iterLeft = lhs.listIterator(); - ListIterator iterRight = rhs.listIterator(); - while (iterLeft.hasNext() && iterRight.hasNext()) { - ISourceLocation left = (ISourceLocation) iterLeft.next(); - ISourceLocation right = (ISourceLocation) iterRight.next(); - sameSourceLocation(left, right); - } - assertTrue(!iterLeft.hasNext()); - assertTrue(!iterRight.hasNext()); - - } public static void sameSourceLocation(ISourceLocation lhs, ISourceLocation rhs) { - if ((null == lhs) && (null == rhs)) { - return; - } - assertTrue(lhs != null); - assertTrue(rhs != null); - assertTrue(lhs.getLine() == rhs.getLine()); - assertTrue(lhs.getColumn() == rhs.getColumn()); - assertTrue(lhs.getOffset() == rhs.getOffset()); - assertTrue(lhs.getEndLine() == rhs.getEndLine()); - // XXX need to compare files, permitting null == NONE + if ((null == lhs) && (null == rhs)) { + return; + } + assertTrue(lhs != null); + assertTrue(rhs != null); + assertTrue(lhs.getLine() == rhs.getLine()); + assertTrue(lhs.getColumn() == rhs.getColumn()); + assertTrue(lhs.getOffset() == rhs.getOffset()); + assertTrue(lhs.getEndLine() == rhs.getEndLine()); + // XXX need to compare files, permitting null == NONE } /** @@ -345,34 +345,34 @@ public class AjcSpecTest extends TestCase { public AjcSpecTest(String name) { super(name); } - - public void testMinimal() { - AjcTest.Spec one = new AjcTest.Spec(); - AjcTest.Spec two = new AjcTest.Spec(); - // empty/identity tests - sameAjcTestSpec(one, two, this); - - one.addOption("-one"); - one.addKeyword("keyword"); - one.addPath("path"); - IMessage m = MessageUtil.info("info message"); - one.addMessage(m); - DirChanges.Spec dcspec = new DirChanges.Spec(); - dcspec.setDirToken("dirToken"); - dcspec.setDefaultSuffix(".suffix"); - one.addDirChanges(dcspec); - // full/identity tests - sameAjcTestSpec(one, one, this); - // XXX need to clone... + public void testMinimal() { + AjcTest.Spec one = new AjcTest.Spec(); + AjcTest.Spec two = new AjcTest.Spec(); + // empty/identity tests + sameAjcTestSpec(one, two, this); + + one.addOption("-one"); + one.addKeyword("keyword"); + one.addPath("path"); + IMessage m = MessageUtil.info("info message"); + one.addMessage(m); + DirChanges.Spec dcspec = new DirChanges.Spec(); + dcspec.setDirToken("dirToken"); + dcspec.setDefaultSuffix(".suffix"); + one.addDirChanges(dcspec); - // XXX need to test that more differences are detected - boolean passed = false; - try { - sameAjcTestSpec(one, two, this); - } catch (AssertionFailedError e) { - passed = true; - } - assertTrue("did not get expected exception", passed); - } + // full/identity tests + sameAjcTestSpec(one, one, this); + // XXX need to clone... + + // XXX need to test that more differences are detected + boolean passed = false; + try { + sameAjcTestSpec(one, two, this); + } catch (AssertionFailedError e) { + passed = true; + } + assertTrue("did not get expected exception", passed); + } } diff --git a/testing/src/test/java/org/aspectj/testing/harness/bridge/JavaRun.java b/testing/src/test/java/org/aspectj/testing/harness/bridge/JavaRun.java index c7e282040..7aa817f05 100644 --- a/testing/src/test/java/org/aspectj/testing/harness/bridge/JavaRun.java +++ b/testing/src/test/java/org/aspectj/testing/harness/bridge/JavaRun.java @@ -1,13 +1,13 @@ /* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * 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: - * Xerox/PARC initial implementation + * 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: + * Xerox/PARC initial implementation * ******************************************************************/ package org.aspectj.testing.harness.bridge; @@ -50,856 +50,897 @@ import org.aspectj.weaver.loadtime.WeavingURLClassLoader; */ public class JavaRun implements IAjcRun { - private static void appendClasspath(StringBuffer cp, Object[] entries) { - if (!LangUtil.isEmpty(entries)) { - for (int i = 0; i < entries.length; i++) { - Object entry = entries[i]; - if (entry instanceof String) { - cp.append((String) entry); - cp.append(File.pathSeparator); - } else if (entry instanceof File) { - String s = FileUtil.getBestPath((File) entry); - if (null != s) { - cp.append(s); - cp.append(File.pathSeparator); - } - } - } - } - } - - Spec spec; - private Sandbox sandbox; - - /** programmatic initialization per spec */ - public JavaRun(Spec spec) { - this.spec = spec; - } - // XXX init(Spec) - - /** - * This checks the spec for a class name - * and checks the sandbox for a readable test source directory, - * a writable run dir, and (non-null, possibly-empty) lists - * of readable classpath dirs and jars, - * and, if fork is enabled, that java can be read. + private static void appendClasspath(StringBuffer cp, Object[] entries) { + if (!LangUtil.isEmpty(entries)) { + for (Object entry : entries) { + if (entry instanceof String) { + cp.append((String) entry); + cp.append(File.pathSeparator); + } else if (entry instanceof File) { + String s = FileUtil.getBestPath((File) entry); + if (null != s) { + cp.append(s); + cp.append(File.pathSeparator); + } + } + } + } + } + + Spec spec; + private Sandbox sandbox; + + /** programmatic initialization per spec */ + public JavaRun(Spec spec) { + this.spec = spec; + } + // XXX init(Spec) + + /** + * This checks the spec for a class name + * and checks the sandbox for a readable test source directory, + * a writable run dir, and (non-null, possibly-empty) lists + * of readable classpath dirs and jars, + * and, if fork is enabled, that java can be read. * @return true if all checks pass - * @see org.aspectj.testing.harness.bridge.AjcTest.IAjcRun#setup(File, File) + * @see org.aspectj.testing.harness.bridge.AjcTest.IAjcRun#setup(File, File) */ + @Override public boolean setupAjcRun(Sandbox sandbox, Validator validator) { this.sandbox = sandbox; - sandbox.javaRunInit(this); + sandbox.javaRunInit(this); return (validator.nullcheck(spec.className, "class name") - && validator.nullcheck(sandbox, "sandbox") - && validator.canReadDir(sandbox.getTestBaseSrcDir(this), "testBaseSrc dir") - && validator.canWriteDir(sandbox.runDir, "run dir") - && validator.canReadFiles(sandbox.getClasspathJars(true, this), "classpath jars") - && validator.canReadDirs(sandbox.getClasspathDirectories(true, this, true), "classpath dirs") - && (!spec.forkSpec.fork - || validator.canRead(spec.forkSpec.java, "java")) - ); - + && validator.nullcheck(sandbox, "sandbox") + && validator.canReadDir(sandbox.getTestBaseSrcDir(this), "testBaseSrc dir") + && validator.canWriteDir(sandbox.runDir, "run dir") + && validator.canReadFiles(sandbox.getClasspathJars(true, this), "classpath jars") + && validator.canReadDirs(sandbox.getClasspathDirectories(true, this, true), "classpath dirs") + && (!spec.forkSpec.fork + || validator.canRead(spec.forkSpec.java, "java")) + ); + + } + + /** caller must record any exceptions */ + @Override + public boolean run(IRunStatus status) + throws IllegalAccessException, + InvocationTargetException, + ClassNotFoundException, + NoSuchMethodException { + boolean completedNormally = false; + boolean passed = false; + if (!LangUtil.isEmpty(spec.dirChanges)) { + MessageUtil.info(status, "XXX dirChanges not implemented in JavaRun"); + } + try { + final boolean readable = true; + File[] libs = sandbox.getClasspathJars(readable, this); + boolean includeClassesDir = true; + File[] dirs = sandbox.getClasspathDirectories(readable, this, includeClassesDir); + completedNormally = (spec.forkSpec.fork) + ? runInOtherVM(status, libs, dirs) + : runInSameVM(status, libs, dirs); + passed = completedNormally; + } finally { + if (!passed || !status.runResult()) { + MessageUtil.info(status, spec.toLongString()); + MessageUtil.info(status, "sandbox: " + sandbox); + } + } + return passed; + } + protected boolean runInSameVM(IRunStatus status, File[] libs, File[] dirs) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { + ClassLoader loader = null; + boolean completedNormally = false; + boolean passed = false; + ByteArrayOutputStream outSnoop = null; + PrintStream oldOut = null; + ByteArrayOutputStream errSnoop = null; + PrintStream oldErr = null; + if (spec.outStreamIsError) { + outSnoop = new ByteArrayOutputStream(); + oldOut = System.out; + System.setOut(new PrintStream(outSnoop, true)); + } + if (spec.errStreamIsError) { + errSnoop = new ByteArrayOutputStream(); + oldErr = System.err; + System.setErr(new PrintStream(errSnoop, true)); + } + Class targetClass = null; + try { + final URL[] clAndLibs; + { + File[] files = sandbox.findFiles(spec.classpath); + URL[] clURLs = FileUtil.getFileURLs(files); + URL[] libURLs = FileUtil.getFileURLs(libs); + clAndLibs = new URL[clURLs.length + libURLs.length]; + System.arraycopy(clURLs, 0, clAndLibs , 0, clURLs.length); + System.arraycopy(libURLs, 0, clAndLibs, clURLs.length, libURLs.length); + } + if (!spec.isLTW()) { + loader = new TestClassLoader(clAndLibs, dirs); + } else { + final URL[] aspectURLs; + { + File[] files = sandbox.findFiles(spec.aspectpath); + aspectURLs = FileUtil.getFileURLs(files); + } + ArrayList classpath = new ArrayList(); + classpath.addAll(Arrays.asList(aspectURLs)); + final URL[] classURLs; + { + classpath.addAll(Arrays.asList(clAndLibs)); + URL[] urls = FileUtil.getFileURLs(dirs); + classpath.addAll(Arrays.asList(urls)); + classpath.add(FileUtil.getFileURL(Globals.F_aspectjrt_jar)); + classpath.add(FileUtil.getFileURL(Globals.F_testingclient_jar)); + classURLs = (URL[]) classpath.toArray(new URL[0]); + } + + ClassLoader parent = JavaRun.class.getClassLoader(); + loader = new WeavingURLClassLoader(classURLs, aspectURLs, parent); + } + // make the following load test optional + // Class testAspect = loader.loadClass("org.aspectj.lang.JoinPoint"); + targetClass = loader.loadClass(spec.className); + Method main = targetClass.getMethod("main", Globals.MAIN_PARM_TYPES); + setupTester(sandbox.getTestBaseSrcDir(this), loader, status); + RunSecurityManager.ME.setJavaRunThread(this); + main.invoke(null, new Object[] { spec.getOptionsArray() }); + completedNormally = true; + boolean snoopFailure = + ((null != errSnoop) && 0 < errSnoop.size()) + || ((null != outSnoop) && 0 < outSnoop.size()); + passed = !snoopFailure && (null == spec.expectedException); + } catch (AbortException e) { + if (expectedException(e)) { + passed = true; + } else { + throw e; + } + } catch (InvocationTargetException e) { + // this and following clauses catch ExitCalledException + Throwable thrown = LangUtil.unwrapException(e); + if (null == thrown) { + throw e; + } + if (thrown instanceof RunSecurityManager.ExitCalledException) { + int i = ((RunSecurityManager.ExitCalledException) thrown).exitCode; + status.finish(new Integer(i)); + } else if (thrown instanceof RunSecurityManager.AwtUsedException) { + MessageUtil.fail(status, "test code should not use the AWT event queue"); + throw (RunSecurityManager.AwtUsedException) thrown; + // same as: status.thrown(thrown); + } else if (expectedException(thrown)) { + passed = true; + } else if (thrown instanceof RuntimeException) { + throw (RuntimeException) thrown; + } else if (thrown instanceof Error) { + throw (Error) thrown; + } else { + throw e; + } + } catch (RunSecurityManager.ExitCalledException e) { + // XXX need to update run validator (a) to accept null result or (b) to require zero result, and set 0 if completed normally + status.finish(new Integer(e.exitCode)); + } catch (ClassNotFoundException e) { + String[] classes = FileUtil.listFiles(sandbox.classesDir); + MessageUtil.info(status, "sandbox.classes: " + Arrays.asList(classes)); + MessageUtil.fail(status, null, e); + } finally { + if (null != oldOut) { + System.setOut(oldOut); + } + if (null != oldErr) { + System.setErr(oldErr); + } + RunSecurityManager.ME.releaseJavaRunThread(this); + if (!completedNormally) { + MessageUtil.info(status, "targetClass: " + targetClass); + MessageUtil.info(status, "loader: " + loader); + } + } + return passed; + } + + /** + * Run in another VM by grabbing Java, bootclasspath, classpath, etc. + * This assumes any exception or output to System.err is a failure, + * and any normal completion is a pass. + * @param status + * @param libs + * @param dirs + * @return + */ + protected boolean runInOtherVM(IRunStatus status, File[] libs, File[] dirs) { + // assert spec.fork || !LangUtil.isEmpty(spec.aspectpath); + ArrayList<String> cmd = new ArrayList<>(); + cmd.add(FileUtil.getBestPath(spec.forkSpec.java)); + if (!LangUtil.isEmpty(spec.forkSpec.vmargs)) { + cmd.addAll(Arrays.asList(spec.forkSpec.vmargs)); + } + final String classpath; + { + StringBuffer cp = new StringBuffer(); + appendClasspath(cp, spec.forkSpec.bootclasspath); + appendClasspath(cp, dirs); + appendClasspath(cp, libs); + File[] classpathFiles = sandbox.findFiles(spec.classpath); + int cpLength = (null == classpathFiles ? 0 : classpathFiles.length); + int spLength = (null == spec.classpath ? 0 : spec.classpath.length); + if (cpLength != spLength) { + throw new Error("unable to find " + Arrays.asList(spec.classpath) + + " got " + Arrays.asList(classpathFiles)); + } + appendClasspath(cp, classpathFiles); + File[] stdlibs = {Globals.F_aspectjrt_jar, Globals.F_testingclient_jar}; + appendClasspath(cp, stdlibs); + classpath = cp.toString(); + } + if (!spec.isLTW()) { + cmd.add("-classpath"); + cmd.add(classpath); + } else { + // verify 1.4 or above, assuming same vm as running this + if (!Globals.supportsJava("1.4")) { + throw new Error("load-time weaving test requires Java 1.4+"); + } + cmd.add("-Djava.system.class.loader=org.aspectj.weaver.WeavingURLClassLoader"); + // assume harness VM classpath has WeavingURLClassLoader (but not others) + cmd.add("-classpath"); + cmd.add(System.getProperty("java.class.path")); + + File[] aspectJars = sandbox.findFiles(spec.aspectpath); + if (aspectJars.length != spec.aspectpath.length) { + throw new Error("unable to find " + Arrays.asList(spec.aspectpath)); + } + StringBuffer cp = new StringBuffer(); + appendClasspath(cp, aspectJars); + cmd.add("-Daj.aspect.path=" + cp.toString()); + cp.append(classpath); // appendClasspath writes trailing delimiter + cmd.add("-Daj.class.path=" + cp.toString()); + } + cmd.add(spec.className); + cmd.addAll(spec.options); + String[] command = cmd.toArray(new String[0]); + + final IMessageHandler handler = status; + // setup to run asynchronously, pipe streams through, and report errors + class DoneFlag { + boolean done; + boolean failed; + int code; + } + final StringBuffer commandLabel = new StringBuffer(); + final DoneFlag doneFlag = new DoneFlag(); + LangUtil.ProcessController controller + = new LangUtil.ProcessController() { + @Override + protected void doCompleting(Thrown ex, int result) { + if (!ex.thrown && (0 == result)) { + doneFlag.done = true; + return; // no errors + } + // handle errors + String context = spec.className + + " command \"" + + commandLabel + + "\""; + if (null != ex.fromProcess) { + if (!expectedException(ex.fromProcess)) { + String m = "Exception running " + context; + MessageUtil.abort(handler, m, ex.fromProcess); + doneFlag.failed = true; + } + } else if (0 != result) { + doneFlag.code = result; + } + if (null != ex.fromInPipe) { + String m = "Error processing input pipe for " + context; + MessageUtil.abort(handler, m, ex.fromInPipe); + doneFlag.failed = true; + } + if (null != ex.fromOutPipe) { + String m = "Error processing output pipe for " + context; + MessageUtil.abort(handler, m, ex.fromOutPipe); + doneFlag.failed = true; + } + if (null != ex.fromErrPipe) { + String m = "Error processing error pipe for " + context; + MessageUtil.abort(handler, m, ex.fromErrPipe); + doneFlag.failed = true; + } + doneFlag.done = true; + } + }; + controller.init(command, spec.className); + if (null != spec.forkSpec.javaHome) { + controller.setEnvp(new String[] {"JAVA_HOME=" + spec.forkSpec.javaHome}); + } + commandLabel.append(Arrays.asList(controller.getCommand()).toString()); + final ByteArrayOutputStream errSnoop + = new ByteArrayOutputStream(); + final ByteArrayOutputStream outSnoop + = new ByteArrayOutputStream(); + controller.setErrSnoop(errSnoop); + controller.setOutSnoop(outSnoop); + controller.start(); + // give it 3 minutes... + long maxTime = System.currentTimeMillis() + 3 * 60 * 1000; + boolean waitingForStop = false; + while (!doneFlag.done) { + if (maxTime < System.currentTimeMillis()) { + if (waitingForStop) { // hit second timeout - bail + break; + } + MessageUtil.fail(status, "timeout waiting for process"); + doneFlag.failed = true; + controller.stop(); + // wait 1 minute to evaluate results of stopping + waitingForStop = true; + maxTime = System.currentTimeMillis() + 1 * 60 * 1000; + } + try { + Thread.sleep(300); + } catch (InterruptedException e) { + // ignore + } + } + + boolean foundException = false; + if (0 < errSnoop.size()) { + if (expectedException(errSnoop)) { + foundException = true; + } else if (spec.errStreamIsError) { + MessageUtil.error(handler, errSnoop.toString()); + if (!doneFlag.failed) { + doneFlag.failed = true; + } + } else { + MessageUtil.info(handler, "Error stream: " + errSnoop.toString()); + } + } + if (0 < outSnoop.size()) { + if (expectedException(outSnoop)) { + foundException = true; + } else if (spec.outStreamIsError) { + MessageUtil.error(handler, outSnoop.toString()); + if (!doneFlag.failed) { + doneFlag.failed = true; + } + } else { + MessageUtil.info(handler, "Output stream: " + outSnoop.toString()); + } + } + if (!foundException) { + if (null != spec.expectedException) { + String m = " expected exception " + spec.expectedException; + MessageUtil.fail(handler, m); + doneFlag.failed = true; + } else if (0 != doneFlag.code) { + String m = doneFlag.code + " result from " + commandLabel; + MessageUtil.fail(handler, m); + doneFlag.failed = true; + } + } + if (doneFlag.failed) { + MessageUtil.info(handler, "other-vm command-line: " + commandLabel); + } + return !doneFlag.failed; + } + + protected boolean expectedException(Throwable thrown) { + if (null != spec.expectedException) { + String cname = thrown.getClass().getName(); + if (-1 != cname.indexOf(spec.expectedException)) { + return true; // caller sets value for returns normally + } + } + return false; + } + + protected boolean expectedException(ByteArrayOutputStream bout) { + return ((null != spec.expectedException) + && (-1 != bout.toString().indexOf(spec.expectedException))); + } + + /** + * Clear (static) testing state and setup base directory, + * unless spec.skipTesting. + * @return null if successful, error message otherwise + */ + protected void setupTester(File baseDir, ClassLoader loader, IMessageHandler handler) { + if (null == loader) { + setupTester(baseDir, handler); + return; + } + File baseDirSet = null; + try { + if (!spec.skipTester) { + Class tc = loader.loadClass("org.aspectj.testing.Tester"); + // Tester.clear(); + Method m = tc.getMethod("clear", new Class[0]); + m.invoke(null, new Object[0]); + // Tester.setMessageHandler(handler); + m = tc.getMethod("setMessageHandler", new Class[] {IMessageHandler.class}); + m.invoke(null, new Object[] { handler}); + + //Tester.setBASEDIR(baseDir); + m = tc.getMethod("setBASEDIR", new Class[] {File.class}); + m.invoke(null, new Object[] { baseDir}); + + //baseDirSet = Tester.getBASEDIR(); + m = tc.getMethod("getBASEDIR", new Class[0]); + baseDirSet = (File) m.invoke(null, new Object[0]); + + if (!baseDirSet.equals(baseDir)) { + String l = "AjcScript.setupTester() setting " + + baseDir + " returned " + baseDirSet; + MessageUtil.debug(handler, l); + } + } + } catch (Throwable t) { + MessageUtil.abort(handler, "baseDir=" + baseDir, t); + } } - - /** caller must record any exceptions */ - public boolean run(IRunStatus status) - throws IllegalAccessException, - InvocationTargetException, - ClassNotFoundException, - NoSuchMethodException { - boolean completedNormally = false; - boolean passed = false; - if (!LangUtil.isEmpty(spec.dirChanges)) { - MessageUtil.info(status, "XXX dirChanges not implemented in JavaRun"); - } - try { - final boolean readable = true; - File[] libs = sandbox.getClasspathJars(readable, this); - boolean includeClassesDir = true; - File[] dirs = sandbox.getClasspathDirectories(readable, this, includeClassesDir); - completedNormally = (spec.forkSpec.fork) - ? runInOtherVM(status, libs, dirs) - : runInSameVM(status, libs, dirs); - passed = completedNormally; - } finally { - if (!passed || !status.runResult()) { - MessageUtil.info(status, spec.toLongString()); - MessageUtil.info(status, "sandbox: " + sandbox); - } - } - return passed; - } - protected boolean runInSameVM(IRunStatus status, File[] libs, File[] dirs) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { - ClassLoader loader = null; - boolean completedNormally = false; - boolean passed = false; - ByteArrayOutputStream outSnoop = null; - PrintStream oldOut = null; - ByteArrayOutputStream errSnoop = null; - PrintStream oldErr = null; - if (spec.outStreamIsError) { - outSnoop = new ByteArrayOutputStream(); - oldOut = System.out; - System.setOut(new PrintStream(outSnoop, true)); - } - if (spec.errStreamIsError) { - errSnoop = new ByteArrayOutputStream(); - oldErr = System.err; - System.setErr(new PrintStream(errSnoop, true)); - } - Class targetClass = null; - try { - final URL[] clAndLibs; - { - File[] files = sandbox.findFiles(spec.classpath); - URL[] clURLs = FileUtil.getFileURLs(files); - URL[] libURLs = FileUtil.getFileURLs(libs); - clAndLibs = new URL[clURLs.length + libURLs.length]; - System.arraycopy(clURLs, 0, clAndLibs , 0, clURLs.length); - System.arraycopy(libURLs, 0, clAndLibs, clURLs.length, libURLs.length); - } - if (!spec.isLTW()) { - loader = new TestClassLoader(clAndLibs, dirs); - } else { - final URL[] aspectURLs; - { - File[] files = sandbox.findFiles(spec.aspectpath); - aspectURLs = FileUtil.getFileURLs(files); - } - ArrayList classpath = new ArrayList(); - classpath.addAll(Arrays.asList(aspectURLs)); - final URL[] classURLs; - { - classpath.addAll(Arrays.asList(clAndLibs)); - URL[] urls = FileUtil.getFileURLs(dirs); - classpath.addAll(Arrays.asList(urls)); - classpath.add(FileUtil.getFileURL(Globals.F_aspectjrt_jar)); - classpath.add(FileUtil.getFileURL(Globals.F_testingclient_jar)); - classURLs = (URL[]) classpath.toArray(new URL[0]); - } - - ClassLoader parent = JavaRun.class.getClassLoader(); - loader = new WeavingURLClassLoader(classURLs, aspectURLs, parent); - } - // make the following load test optional - // Class testAspect = loader.loadClass("org.aspectj.lang.JoinPoint"); - targetClass = loader.loadClass(spec.className); - Method main = targetClass.getMethod("main", Globals.MAIN_PARM_TYPES); - setupTester(sandbox.getTestBaseSrcDir(this), loader, status); - RunSecurityManager.ME.setJavaRunThread(this); - main.invoke(null, new Object[] { spec.getOptionsArray() }); - completedNormally = true; - boolean snoopFailure = - ((null != errSnoop) && 0 < errSnoop.size()) - || ((null != outSnoop) && 0 < outSnoop.size()); - passed = !snoopFailure && (null == spec.expectedException); - } catch (AbortException e) { - if (expectedException(e)) { - passed = true; - } else { - throw e; - } - } catch (InvocationTargetException e) { - // this and following clauses catch ExitCalledException - Throwable thrown = LangUtil.unwrapException(e); - if (null == thrown) { - throw e; - } - if (thrown instanceof RunSecurityManager.ExitCalledException) { - int i = ((RunSecurityManager.ExitCalledException) thrown).exitCode; - status.finish(new Integer(i)); - } else if (thrown instanceof RunSecurityManager.AwtUsedException) { - MessageUtil.fail(status, "test code should not use the AWT event queue"); - throw (RunSecurityManager.AwtUsedException) thrown; - // same as: status.thrown(thrown); - } else if (expectedException(thrown)) { - passed = true; - } else if (thrown instanceof RuntimeException) { - throw (RuntimeException) thrown; - } else if (thrown instanceof Error) { - throw (Error) thrown; - } else { - throw e; - } - } catch (RunSecurityManager.ExitCalledException e) { - // XXX need to update run validator (a) to accept null result or (b) to require zero result, and set 0 if completed normally - status.finish(new Integer(e.exitCode)); - } catch (ClassNotFoundException e) { - String[] classes = FileUtil.listFiles(sandbox.classesDir); - MessageUtil.info(status, "sandbox.classes: " + Arrays.asList(classes)); - MessageUtil.fail(status, null, e); - } finally { - if (null != oldOut) { - System.setOut(oldOut); - } - if (null != oldErr) { - System.setErr(oldErr); - } - RunSecurityManager.ME.releaseJavaRunThread(this); - if (!completedNormally) { - MessageUtil.info(status, "targetClass: " + targetClass); - MessageUtil.info(status, "loader: " + loader); - } - } - return passed; - } - - /** - * Run in another VM by grabbing Java, bootclasspath, classpath, etc. - * This assumes any exception or output to System.err is a failure, - * and any normal completion is a pass. - * @param status - * @param libs - * @param dirs - * @return - */ - protected boolean runInOtherVM(IRunStatus status, File[] libs, File[] dirs) { - // assert spec.fork || !LangUtil.isEmpty(spec.aspectpath); - ArrayList cmd = new ArrayList(); - cmd.add(FileUtil.getBestPath(spec.forkSpec.java)); - if (!LangUtil.isEmpty(spec.forkSpec.vmargs)) { - cmd.addAll(Arrays.asList(spec.forkSpec.vmargs)); - } - final String classpath; - { - StringBuffer cp = new StringBuffer(); - appendClasspath(cp, spec.forkSpec.bootclasspath); - appendClasspath(cp, dirs); - appendClasspath(cp, libs); - File[] classpathFiles = sandbox.findFiles(spec.classpath); - int cpLength = (null == classpathFiles ? 0 : classpathFiles.length); - int spLength = (null == spec.classpath ? 0 : spec.classpath.length); - if (cpLength != spLength) { - throw new Error("unable to find " + Arrays.asList(spec.classpath) - + " got " + Arrays.asList(classpathFiles)); - } - appendClasspath(cp, classpathFiles); - File[] stdlibs = {Globals.F_aspectjrt_jar, Globals.F_testingclient_jar}; - appendClasspath(cp, stdlibs); - classpath = cp.toString(); - } - if (!spec.isLTW()) { - cmd.add("-classpath"); - cmd.add(classpath); - } else { - // verify 1.4 or above, assuming same vm as running this - if (!Globals.supportsJava("1.4")) { - throw new Error("load-time weaving test requires Java 1.4+"); - } - cmd.add("-Djava.system.class.loader=org.aspectj.weaver.WeavingURLClassLoader"); - // assume harness VM classpath has WeavingURLClassLoader (but not others) - cmd.add("-classpath"); - cmd.add(System.getProperty("java.class.path")); - - File[] aspectJars = sandbox.findFiles(spec.aspectpath); - if (aspectJars.length != spec.aspectpath.length) { - throw new Error("unable to find " + Arrays.asList(spec.aspectpath)); - } - StringBuffer cp = new StringBuffer(); - appendClasspath(cp, aspectJars); - cmd.add("-Daj.aspect.path=" + cp.toString()); - cp.append(classpath); // appendClasspath writes trailing delimiter - cmd.add("-Daj.class.path=" + cp.toString()); - } - cmd.add(spec.className); - cmd.addAll(spec.options); - String[] command = (String[]) cmd.toArray(new String[0]); - - final IMessageHandler handler = status; - // setup to run asynchronously, pipe streams through, and report errors - class DoneFlag { - boolean done; - boolean failed; - int code; - } - final StringBuffer commandLabel = new StringBuffer(); - final DoneFlag doneFlag = new DoneFlag(); - LangUtil.ProcessController controller - = new LangUtil.ProcessController() { - protected void doCompleting(Thrown ex, int result) { - if (!ex.thrown && (0 == result)) { - doneFlag.done = true; - return; // no errors - } - // handle errors - String context = spec.className - + " command \"" - + commandLabel - + "\""; - if (null != ex.fromProcess) { - if (!expectedException(ex.fromProcess)) { - String m = "Exception running " + context; - MessageUtil.abort(handler, m, ex.fromProcess); - doneFlag.failed = true; - } - } else if (0 != result) { - doneFlag.code = result; - } - if (null != ex.fromInPipe) { - String m = "Error processing input pipe for " + context; - MessageUtil.abort(handler, m, ex.fromInPipe); - doneFlag.failed = true; - } - if (null != ex.fromOutPipe) { - String m = "Error processing output pipe for " + context; - MessageUtil.abort(handler, m, ex.fromOutPipe); - doneFlag.failed = true; - } - if (null != ex.fromErrPipe) { - String m = "Error processing error pipe for " + context; - MessageUtil.abort(handler, m, ex.fromErrPipe); - doneFlag.failed = true; - } - doneFlag.done = true; - } - }; - controller.init(command, spec.className); - if (null != spec.forkSpec.javaHome) { - controller.setEnvp(new String[] {"JAVA_HOME=" + spec.forkSpec.javaHome}); - } - commandLabel.append(Arrays.asList(controller.getCommand()).toString()); - final ByteArrayOutputStream errSnoop - = new ByteArrayOutputStream(); - final ByteArrayOutputStream outSnoop - = new ByteArrayOutputStream(); - controller.setErrSnoop(errSnoop); - controller.setOutSnoop(outSnoop); - controller.start(); - // give it 3 minutes... - long maxTime = System.currentTimeMillis() + 3 * 60 * 1000; - boolean waitingForStop = false; - while (!doneFlag.done) { - if (maxTime < System.currentTimeMillis()) { - if (waitingForStop) { // hit second timeout - bail - break; - } - MessageUtil.fail(status, "timeout waiting for process"); - doneFlag.failed = true; - controller.stop(); - // wait 1 minute to evaluate results of stopping - waitingForStop = true; - maxTime = System.currentTimeMillis() + 1 * 60 * 1000; - } - try { - Thread.sleep(300); - } catch (InterruptedException e) { - // ignore - } - } - - boolean foundException = false; - if (0 < errSnoop.size()) { - if (expectedException(errSnoop)) { - foundException = true; - } else if (spec.errStreamIsError) { - MessageUtil.error(handler, errSnoop.toString()); - if (!doneFlag.failed) { - doneFlag.failed = true; - } - } else { - MessageUtil.info(handler, "Error stream: " + errSnoop.toString()); - } - } - if (0 < outSnoop.size()) { - if (expectedException(outSnoop)) { - foundException = true; - } else if (spec.outStreamIsError) { - MessageUtil.error(handler, outSnoop.toString()); - if (!doneFlag.failed) { - doneFlag.failed = true; - } - } else { - MessageUtil.info(handler, "Output stream: " + outSnoop.toString()); - } - } - if (!foundException) { - if (null != spec.expectedException) { - String m = " expected exception " + spec.expectedException; - MessageUtil.fail(handler, m); - doneFlag.failed = true; - } else if (0 != doneFlag.code) { - String m = doneFlag.code + " result from " + commandLabel; - MessageUtil.fail(handler, m); - doneFlag.failed = true; - } - } - if (doneFlag.failed) { - MessageUtil.info(handler, "other-vm command-line: " + commandLabel); - } - return !doneFlag.failed; - } - - protected boolean expectedException(Throwable thrown) { - if (null != spec.expectedException) { - String cname = thrown.getClass().getName(); - if (-1 != cname.indexOf(spec.expectedException)) { - return true; // caller sets value for returns normally - } - } - return false; - } - - protected boolean expectedException(ByteArrayOutputStream bout) { - return ((null != spec.expectedException) - && (-1 != bout.toString().indexOf(spec.expectedException))); - } - - /** - * Clear (static) testing state and setup base directory, - * unless spec.skipTesting. - * @return null if successful, error message otherwise - */ - protected void setupTester(File baseDir, ClassLoader loader, IMessageHandler handler) { - if (null == loader) { - setupTester(baseDir, handler); - return; - } - File baseDirSet = null; - try { - if (!spec.skipTester) { - Class tc = loader.loadClass("org.aspectj.testing.Tester"); - // Tester.clear(); - Method m = tc.getMethod("clear", new Class[0]); - m.invoke(null, new Object[0]); - // Tester.setMessageHandler(handler); - m = tc.getMethod("setMessageHandler", new Class[] {IMessageHandler.class}); - m.invoke(null, new Object[] { handler}); - - //Tester.setBASEDIR(baseDir); - m = tc.getMethod("setBASEDIR", new Class[] {File.class}); - m.invoke(null, new Object[] { baseDir}); - - //baseDirSet = Tester.getBASEDIR(); - m = tc.getMethod("getBASEDIR", new Class[0]); - baseDirSet = (File) m.invoke(null, new Object[0]); - - if (!baseDirSet.equals(baseDir)) { - String l = "AjcScript.setupTester() setting " - + baseDir + " returned " + baseDirSet; - MessageUtil.debug(handler, l); - } - } - } catch (Throwable t) { - MessageUtil.abort(handler, "baseDir=" + baseDir, t); - } - } - - /** - * Clear (static) testing state and setup base directory, - * unless spec.skipTesting. - * This implementation assumes that Tester is defined for the - * same class loader as this class. - * @return null if successful, error message otherwise - */ - protected void setupTester(File baseDir, IMessageHandler handler) { - File baseDirSet = null; - try { - if (!spec.skipTester) { - Tester.clear(); - Tester.setMessageHandler(handler); - Tester.setBASEDIR(baseDir); - baseDirSet = Tester.getBASEDIR(); - if (!baseDirSet.equals(baseDir)) { - String l = "AjcScript.setupTester() setting " - + baseDir + " returned " + baseDirSet; - MessageUtil.debug(handler, l); - } - } - } catch (Throwable t) { - MessageUtil.abort(handler, "baseDir=" + baseDir, t); - } - } + + /** + * Clear (static) testing state and setup base directory, + * unless spec.skipTesting. + * This implementation assumes that Tester is defined for the + * same class loader as this class. + * @return null if successful, error message otherwise + */ + protected void setupTester(File baseDir, IMessageHandler handler) { + File baseDirSet = null; + try { + if (!spec.skipTester) { + Tester.clear(); + Tester.setMessageHandler(handler); + Tester.setBASEDIR(baseDir); + baseDirSet = Tester.getBASEDIR(); + if (!baseDirSet.equals(baseDir)) { + String l = "AjcScript.setupTester() setting " + + baseDir + " returned " + baseDirSet; + MessageUtil.debug(handler, l); + } + } + } catch (Throwable t) { + MessageUtil.abort(handler, "baseDir=" + baseDir, t); + } + } + @Override public String toString() { - return "JavaRun(" + spec + ")"; + return "JavaRun(" + spec + ")"; + } + + /** + * Struct class for fork attributes and initialization. + * This supports defaults for forking using system properties + * which will be overridden by any specification. + * (It differs from CompilerRun, which supports option + * overriding by passing values as harness arguments.) + */ + public static class ForkSpec { + /** + * key for system property for default value for forking + * (true if set to true) + */ + public static String FORK_KEY = "javarun.fork"; + public static String JAVA_KEY = "javarun.java"; + public static String VM_ARGS_KEY = "javarun.vmargs"; + public static String JAVA_HOME_KEY = "javarun.java.home"; + public static String BOOTCLASSPATH_KEY = "javarun.bootclasspath"; + static final ForkSpec FORK; + static { + ForkSpec fork = new ForkSpec(); + fork.fork = Boolean.getBoolean(FORK_KEY); + fork.java = getFile(JAVA_KEY); + if (null == fork.java) { + fork.java = LangUtil.getJavaExecutable(); + } + fork.javaHome = getFile(JAVA_HOME_KEY); + fork.bootclasspath = XMLWriter.unflattenList(getProperty(BOOTCLASSPATH_KEY)); + fork.vmargs = XMLWriter.unflattenList(getProperty(VM_ARGS_KEY)); + FORK = fork; + } + private static File getFile(String key) { + String path = getProperty(key); + if (null != path) { + File result = new File(path); + if (result.exists()) { + return result; + } + } + return null; + } + private static String getProperty(String key) { + try { + return System.getProperty(key); + } catch (Throwable t) { + return null; + } + } + private boolean fork; + private String[] bootclasspath; + private File java; + private File javaHome; + private String[] vmargs; + + private ForkSpec() { + copy(FORK); + } + + private void copy(ForkSpec forkSpec) { + if (null != forkSpec) { + fork = forkSpec.fork; + bootclasspath = forkSpec.bootclasspath; + java = forkSpec.java; + javaHome = forkSpec.javaHome; + vmargs = forkSpec.vmargs; + } + } + + /** + * @return "" or bootclasspath with File.pathSeparator internal delimiters + */ + String getBootclasspath() { + if (LangUtil.isEmpty(bootclasspath)) { + return ""; + } + return FileUtil.flatten(bootclasspath, null); + } + } + + /** + * Initializer/factory for JavaRun. + * The classpath is not here but precalculated in the Sandbox. + */ + public static class Spec extends AbstractRunSpec { + static { + try { + System.setSecurityManager(RunSecurityManager.ME); + } catch (Throwable t) { + System.err.println("JavaRun: Security manager set - no System.exit() protection"); + } + } + public static final String XMLNAME = "run"; + /** + * skip description, skip sourceLocation, + * do keywords, do options, skip paths, do comment, + * skip staging, skip badInput, + * do dirChanges, do messages but skip children. + */ + private static final XMLNames NAMES = new XMLNames(XMLNames.DEFAULT, + "", "", null, null, "", null, "", "", false, false, true); + + /** fully-qualified name of the class to run */ + protected String className; + + /** Alternative to classname for specifying what to run modulename/type */ + protected String module; + + /** minimum required version of Java, if any */ + protected String javaVersion; + + /** if true, skip Tester setup (e.g., if Tester n/a) */ + protected boolean skipTester; + + /** if true, report text to output stream as error */ + protected boolean outStreamIsError; + + /** if true, report text to error stream as error */ + protected boolean errStreamIsError = true; + + protected final ForkSpec forkSpec; + protected String[] aspectpath; + protected boolean useLTW; + protected String[] classpath; + protected String expectedException; + + public Spec() { + super(XMLNAME); + setXMLNames(NAMES); + forkSpec = new ForkSpec(); + } + + protected void initClone(Spec spec) + throws CloneNotSupportedException { + super.initClone(spec); + spec.className = className; + spec.errStreamIsError = errStreamIsError; + spec.javaVersion = javaVersion; + spec.outStreamIsError = outStreamIsError; + spec.skipTester = skipTester; + spec.forkSpec.copy(forkSpec); + } + + @Override + public Object clone() throws CloneNotSupportedException { + Spec result = new Spec(); + initClone(result); + return result; + } + + public boolean isLTW() { + return useLTW || (null != aspectpath); + } + + /** + * @param version "1.1", "1.2", "1.3", "1.4" + * @throws IllegalArgumentException if version is not recognized + */ + public void setJavaVersion(String version) { + Globals.supportsJava(version); + this.javaVersion = version; + } + + /** @className fully-qualified name of the class to run */ + public void setClassName(String className) { + this.className = className; + } + + public void setModule(String module) { + this.module = module; + } + + public void setLTW(String ltw) { + useLTW = TestUtil.parseBoolean(ltw); + } + + public void setAspectpath(String path) { + this.aspectpath = XMLWriter.unflattenList(path); + } + public void setException(String exception) { + this.expectedException = exception; + } + + public void setClasspath(String path) { + this.classpath = XMLWriter.unflattenList(path); + } + public void setErrStreamIsError(String errStreamIsError) { + this.errStreamIsError = TestUtil.parseBoolean(errStreamIsError); + } + + public void setOutStreamIsError(String outStreamIsError) { + this.outStreamIsError = TestUtil.parseBoolean(outStreamIsError); + } + + /** @param skip if true, then do not set up Tester */ + public void setSkipTester(boolean skip) { + skipTester = skip; + } + + public void setFork(boolean fork) { + forkSpec.fork = fork; + } + + /** + * @param vmargs comma-delimited list of arguments for java, + * typically -Dname=value,-DanotherName="another value" + */ + public void setVmArgs(String vmargs) { + forkSpec.vmargs = XMLWriter.unflattenList(vmargs); + } + + /** override to set dirToken to Sandbox.RUN_DIR */ + @Override + public void addDirChanges(DirChanges.Spec spec) { + if (null == spec) { + return; + } + spec.setDirToken(Sandbox.RUN_DIR); + super.addDirChanges(spec); + } + + /** @return a JavaRun with this as spec if setup completes successfully. */ + @Override + public IRunIterator makeRunIterator(Sandbox sandbox, Validator validator) { + JavaRun run = new JavaRun(this); + if (run.setupAjcRun(sandbox, validator)) { + // XXX need name for JavaRun + return new WrappedRunIterator(this, run); + } + return null; + } + + /** + * Write this out as a run element as defined in + * AjcSpecXmlReader.DOCTYPE. + * @see AjcSpecXmlReader#DOCTYPE + * @see IXmlWritable#writeXml(XMLWriter) + */ + @Override + public void writeXml(XMLWriter out) { + String attr = XMLWriter.makeAttribute("class", className); + out.startElement(xmlElementName, attr, false); + if (skipTester) { + out.printAttribute("skipTester", "true"); + } + if (null != javaVersion) { + out.printAttribute("vm", javaVersion); + } + if (outStreamIsError) { + out.printAttribute("outStreamIsError", "true"); + } + if (!errStreamIsError) { // defaults to true + out.printAttribute("errStreamIsError", "false"); + } + super.writeAttributes(out); + out.endAttributes(); + if (!LangUtil.isEmpty(dirChanges)) { + DirChanges.Spec.writeXml(out, dirChanges); + } + SoftMessage.writeXml(out, getMessages()); + out.endElement(xmlElementName); + } + @Override + public String toLongString() { + return toString() + "[" + super.toLongString() + "]"; + } + + @Override + public String toString() { + if (skipTester) { + return "JavaRun(" + className + ", skipTester)"; + } else { + return "JavaRun(" + className + ")"; + } + } + + /** + * This implementation skips if: + * <ul> + * <li>current VM is not at least any specified javaVersion </li> + * </ul> + * @return false if this wants to be skipped, true otherwise + */ + @Override + protected boolean doAdoptParentValues(RT parentRuntime, IMessageHandler handler) { + if (!super.doAdoptParentValues(parentRuntime, handler)) { + return false; + } + if ((null != javaVersion) && (!Globals.supportsJava(javaVersion))) { + skipMessage(handler, "requires Java version " + javaVersion); + return false; + } + return true; + } + } + /** + * This permits everything but System.exit() in the context of a + * thread set by JavaRun. + * XXX need to update for thread spawned by that thread + * XXX need to update for awt thread use after AJDE wrapper doesn't + */ + public static class RunSecurityManager extends SecurityManager { + public static RunSecurityManager ME = new RunSecurityManager(); + private Thread runThread; + private RunSecurityManager(){} + private synchronized void setJavaRunThread(JavaRun run) { + LangUtil.throwIaxIfNull(run, "run"); + runThread = Thread.currentThread(); + } + private synchronized void releaseJavaRunThread(JavaRun run) { + LangUtil.throwIaxIfNull(run, "run"); + runThread = null; + } + /** @throws ExitCalledException if called from the JavaRun-set thread */ + @Override + public void checkExit(int exitCode) throws ExitCalledException { + if ((null != runThread) && runThread.equals(Thread.currentThread())) { + throw new ExitCalledException(exitCode); + } + } + @Override + public void checkAwtEventQueueAccess() { + if ((null != runThread) && runThread.equals(Thread.currentThread())) { + throw new AwtUsedException(); + } + } + @Override + public void checkSystemClipboardAccess() { + // permit + } + // used by constrained calls + public static class ExitCalledException extends SecurityException { + public final int exitCode; + public ExitCalledException(int exitCode) { + this.exitCode = exitCode; + } + } + public static class AwtUsedException extends SecurityException { + public AwtUsedException() { } + } + // permit everything else + @Override + public void checkAccept(String arg0, int arg1) { + } + @Override + public void checkAccess(Thread arg0) { + } + @Override + public void checkAccess(ThreadGroup arg0) { + } + @Override + public void checkConnect(String arg0, int arg1) { + } + @Override + public void checkConnect(String arg0, int arg1, Object arg2) { + } + @Override + public void checkCreateClassLoader() { + } + @Override + public void checkDelete(String arg0) { + } + @Override + public void checkExec(String arg0) { + } + @Override + public void checkLink(String arg0) { + } + @Override + public void checkListen(int arg0) { + } + @Override + public void checkMemberAccess(Class arg0, int arg1) { + } + @Override + public void checkMulticast(InetAddress arg0) { + } + @Override + public void checkMulticast(InetAddress arg0, byte arg1) { + } + @Override + public void checkPackageAccess(String arg0) { + } + @Override + public void checkPackageDefinition(String arg0) { + } + @Override + public void checkPermission(Permission arg0) { + } + @Override + public void checkPermission(Permission arg0, Object arg1) { + } + @Override + public void checkPrintJobAccess() { + } + @Override + public void checkPropertiesAccess() { + } + @Override + public void checkPropertyAccess(String arg0) { + } + @Override + public void checkRead(FileDescriptor arg0) { + } + @Override + public void checkRead(String arg0) { + } + @Override + public void checkRead(String arg0, Object arg1) { + } + @Override + public void checkSecurityAccess(String arg0) { + } + @Override + public void checkSetFactory() { + } + @Override + public boolean checkTopLevelWindow(Object arg0) { + return true; + } + @Override + public void checkWrite(FileDescriptor arg0) { + } + @Override + public void checkWrite(String arg0) { + } + } - - /** - * Struct class for fork attributes and initialization. - * This supports defaults for forking using system properties - * which will be overridden by any specification. - * (It differs from CompilerRun, which supports option - * overriding by passing values as harness arguments.) - */ - public static class ForkSpec { - /** - * key for system property for default value for forking - * (true if set to true) - */ - public static String FORK_KEY = "javarun.fork"; - public static String JAVA_KEY = "javarun.java"; - public static String VM_ARGS_KEY = "javarun.vmargs"; - public static String JAVA_HOME_KEY = "javarun.java.home"; - public static String BOOTCLASSPATH_KEY = "javarun.bootclasspath"; - static final ForkSpec FORK; - static { - ForkSpec fork = new ForkSpec(); - fork.fork = Boolean.getBoolean(FORK_KEY); - fork.java = getFile(JAVA_KEY); - if (null == fork.java) { - fork.java = LangUtil.getJavaExecutable(); - } - fork.javaHome = getFile(JAVA_HOME_KEY); - fork.bootclasspath = XMLWriter.unflattenList(getProperty(BOOTCLASSPATH_KEY)); - fork.vmargs = XMLWriter.unflattenList(getProperty(VM_ARGS_KEY)); - FORK = fork; - } - private static File getFile(String key) { - String path = getProperty(key); - if (null != path) { - File result = new File(path); - if (result.exists()) { - return result; - } - } - return null; - } - private static String getProperty(String key) { - try { - return System.getProperty(key); - } catch (Throwable t) { - return null; - } - } - private boolean fork; - private String[] bootclasspath; - private File java; - private File javaHome; - private String[] vmargs; - - private ForkSpec() { - copy(FORK); - } - - private void copy(ForkSpec forkSpec) { - if (null != forkSpec) { - fork = forkSpec.fork; - bootclasspath = forkSpec.bootclasspath; - java = forkSpec.java; - javaHome = forkSpec.javaHome; - vmargs = forkSpec.vmargs; - } - } - - /** - * @return "" or bootclasspath with File.pathSeparator internal delimiters - */ - String getBootclasspath() { - if (LangUtil.isEmpty(bootclasspath)) { - return ""; - } - return FileUtil.flatten(bootclasspath, null); - } - } - - /** - * Initializer/factory for JavaRun. - * The classpath is not here but precalculated in the Sandbox. - */ - public static class Spec extends AbstractRunSpec { - static { - try { - System.setSecurityManager(RunSecurityManager.ME); - } catch (Throwable t) { - System.err.println("JavaRun: Security manager set - no System.exit() protection"); - } - } - public static final String XMLNAME = "run"; - /** - * skip description, skip sourceLocation, - * do keywords, do options, skip paths, do comment, - * skip staging, skip badInput, - * do dirChanges, do messages but skip children. - */ - private static final XMLNames NAMES = new XMLNames(XMLNames.DEFAULT, - "", "", null, null, "", null, "", "", false, false, true); - - /** fully-qualified name of the class to run */ - protected String className; - - /** Alternative to classname for specifying what to run modulename/type */ - protected String module; - - /** minimum required version of Java, if any */ - protected String javaVersion; - - /** if true, skip Tester setup (e.g., if Tester n/a) */ - protected boolean skipTester; - - /** if true, report text to output stream as error */ - protected boolean outStreamIsError; - - /** if true, report text to error stream as error */ - protected boolean errStreamIsError = true; - - protected final ForkSpec forkSpec; - protected String[] aspectpath; - protected boolean useLTW; - protected String[] classpath; - protected String expectedException; - - public Spec() { - super(XMLNAME); - setXMLNames(NAMES); - forkSpec = new ForkSpec(); - } - - protected void initClone(Spec spec) - throws CloneNotSupportedException { - super.initClone(spec); - spec.className = className; - spec.errStreamIsError = errStreamIsError; - spec.javaVersion = javaVersion; - spec.outStreamIsError = outStreamIsError; - spec.skipTester = skipTester; - spec.forkSpec.copy(forkSpec); - } - - public Object clone() throws CloneNotSupportedException { - Spec result = new Spec(); - initClone(result); - return result; - } - - public boolean isLTW() { - return useLTW || (null != aspectpath); - } - - /** - * @param version "1.1", "1.2", "1.3", "1.4" - * @throws IllegalArgumentException if version is not recognized - */ - public void setJavaVersion(String version) { - Globals.supportsJava(version); - this.javaVersion = version; - } - - /** @className fully-qualified name of the class to run */ - public void setClassName(String className) { - this.className = className; - } - - public void setModule(String module) { - this.module = module; - } - - public void setLTW(String ltw) { - useLTW = TestUtil.parseBoolean(ltw); - } - - public void setAspectpath(String path) { - this.aspectpath = XMLWriter.unflattenList(path); - } - public void setException(String exception) { - this.expectedException = exception; - } - - public void setClasspath(String path) { - this.classpath = XMLWriter.unflattenList(path); - } - public void setErrStreamIsError(String errStreamIsError) { - this.errStreamIsError = TestUtil.parseBoolean(errStreamIsError); - } - - public void setOutStreamIsError(String outStreamIsError) { - this.outStreamIsError = TestUtil.parseBoolean(outStreamIsError); - } - - /** @param skip if true, then do not set up Tester */ - public void setSkipTester(boolean skip) { - skipTester = skip; - } - - public void setFork(boolean fork) { - forkSpec.fork = fork; - } - - /** - * @param vmargs comma-delimited list of arguments for java, - * typically -Dname=value,-DanotherName="another value" - */ - public void setVmArgs(String vmargs) { - forkSpec.vmargs = XMLWriter.unflattenList(vmargs); - } - - /** override to set dirToken to Sandbox.RUN_DIR */ - public void addDirChanges(DirChanges.Spec spec) { - if (null == spec) { - return; - } - spec.setDirToken(Sandbox.RUN_DIR); - super.addDirChanges(spec); - } - - /** @return a JavaRun with this as spec if setup completes successfully. */ - public IRunIterator makeRunIterator(Sandbox sandbox, Validator validator) { - JavaRun run = new JavaRun(this); - if (run.setupAjcRun(sandbox, validator)) { - // XXX need name for JavaRun - return new WrappedRunIterator(this, run); - } - return null; - } - - /** - * Write this out as a run element as defined in - * AjcSpecXmlReader.DOCTYPE. - * @see AjcSpecXmlReader#DOCTYPE - * @see IXmlWritable#writeXml(XMLWriter) - */ - public void writeXml(XMLWriter out) { - String attr = XMLWriter.makeAttribute("class", className); - out.startElement(xmlElementName, attr, false); - if (skipTester) { - out.printAttribute("skipTester", "true"); - } - if (null != javaVersion) { - out.printAttribute("vm", javaVersion); - } - if (outStreamIsError) { - out.printAttribute("outStreamIsError", "true"); - } - if (!errStreamIsError) { // defaults to true - out.printAttribute("errStreamIsError", "false"); - } - super.writeAttributes(out); - out.endAttributes(); - if (!LangUtil.isEmpty(dirChanges)) { - DirChanges.Spec.writeXml(out, dirChanges); - } - SoftMessage.writeXml(out, getMessages()); - out.endElement(xmlElementName); - } - public String toLongString() { - return toString() + "[" + super.toLongString() + "]"; - } - - public String toString() { - if (skipTester) { - return "JavaRun(" + className + ", skipTester)"; - } else { - return "JavaRun(" + className + ")"; - } - } - - /** - * This implementation skips if: - * <ul> - * <li>current VM is not at least any specified javaVersion </li> - * </ul> - * @return false if this wants to be skipped, true otherwise - */ - protected boolean doAdoptParentValues(RT parentRuntime, IMessageHandler handler) { - if (!super.doAdoptParentValues(parentRuntime, handler)) { - return false; - } - if ((null != javaVersion) && (!Globals.supportsJava(javaVersion))) { - skipMessage(handler, "requires Java version " + javaVersion); - return false; - } - return true; - } - } - /** - * This permits everything but System.exit() in the context of a - * thread set by JavaRun. - * XXX need to update for thread spawned by that thread - * XXX need to update for awt thread use after AJDE wrapper doesn't - */ - public static class RunSecurityManager extends SecurityManager { - public static RunSecurityManager ME = new RunSecurityManager(); - private Thread runThread; - private RunSecurityManager(){} - private synchronized void setJavaRunThread(JavaRun run) { - LangUtil.throwIaxIfNull(run, "run"); - runThread = Thread.currentThread(); - } - private synchronized void releaseJavaRunThread(JavaRun run) { - LangUtil.throwIaxIfNull(run, "run"); - runThread = null; - } - /** @throws ExitCalledException if called from the JavaRun-set thread */ - public void checkExit(int exitCode) throws ExitCalledException { - if ((null != runThread) && runThread.equals(Thread.currentThread())) { - throw new ExitCalledException(exitCode); - } - } - public void checkAwtEventQueueAccess() { - if ((null != runThread) && runThread.equals(Thread.currentThread())) { - throw new AwtUsedException(); - } - } - public void checkSystemClipboardAccess() { - // permit - } - // used by constrained calls - public static class ExitCalledException extends SecurityException { - public final int exitCode; - public ExitCalledException(int exitCode) { - this.exitCode = exitCode; - } - } - public static class AwtUsedException extends SecurityException { - public AwtUsedException() { } - } - // permit everything else - public void checkAccept(String arg0, int arg1) { - } - public void checkAccess(Thread arg0) { - } - public void checkAccess(ThreadGroup arg0) { - } - public void checkConnect(String arg0, int arg1) { - } - public void checkConnect(String arg0, int arg1, Object arg2) { - } - public void checkCreateClassLoader() { - } - public void checkDelete(String arg0) { - } - public void checkExec(String arg0) { - } - public void checkLink(String arg0) { - } - public void checkListen(int arg0) { - } - public void checkMemberAccess(Class arg0, int arg1) { - } - public void checkMulticast(InetAddress arg0) { - } - public void checkMulticast(InetAddress arg0, byte arg1) { - } - public void checkPackageAccess(String arg0) { - } - public void checkPackageDefinition(String arg0) { - } - public void checkPermission(Permission arg0) { - } - public void checkPermission(Permission arg0, Object arg1) { - } - public void checkPrintJobAccess() { - } - public void checkPropertiesAccess() { - } - public void checkPropertyAccess(String arg0) { - } - public void checkRead(FileDescriptor arg0) { - } - public void checkRead(String arg0) { - } - public void checkRead(String arg0, Object arg1) { - } - public void checkSecurityAccess(String arg0) { - } - public void checkSetFactory() { - } - public boolean checkTopLevelWindow(Object arg0) { - return true; - } - public void checkWrite(FileDescriptor arg0) { - } - public void checkWrite(String arg0) { - } - - } } diff --git a/testing/src/test/java/org/aspectj/testing/harness/bridge/Validator.java b/testing/src/test/java/org/aspectj/testing/harness/bridge/Validator.java index 37ddd005e..5bb1a15b2 100644 --- a/testing/src/test/java/org/aspectj/testing/harness/bridge/Validator.java +++ b/testing/src/test/java/org/aspectj/testing/harness/bridge/Validator.java @@ -1,13 +1,13 @@ /* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * 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: - * Xerox/PARC initial implementation + * 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: + * Xerox/PARC initial implementation * ******************************************************************/ package org.aspectj.testing.harness.bridge; @@ -27,7 +27,7 @@ import org.aspectj.bridge.MessageUtil; import org.aspectj.util.FileUtil; import org.aspectj.util.LangUtil; -/** +/** * Check input and implement defaults. * This handles failure messaging and collecting temp directories * for later cleanup. @@ -42,518 +42,518 @@ import org.aspectj.util.LangUtil; * not change the reporting scheme established by the caller, * so the caller may lock and unlock the error handling policy. * When the policy is locked, this silently ignores attempts - * to toggle exceptions, or delete temporary files. + * to toggle exceptions, or delete temporary files. * XXX callers cannot prevent others from pushing other error handlers. */ public class Validator { - - /** stack of handlers */ - private final Stack handlers; - - /** list of File registered for deletion on demand */ - private final ArrayList tempFiles; // deleteTempFiles requires ListIterator.remove() - - /** list of Sandboxes registered for cleanup on demand */ - private final ArrayList sandboxes; - - /** if true, throw AbortException on failure */ - boolean abortOnFailure; - - /** this object prevents any changes to error-handling policy */ - private Object locker; - - public Validator(IMessageHandler handler) { - tempFiles = new ArrayList(); - sandboxes = new ArrayList(); - handlers = new Stack(); - pushHandler(handler); - } - - /** - * Push IMessageHandler onto stack, - * so it will be used until the next push or pop - * @param handler not null - * - */ - public void pushHandler(IMessageHandler handler) { - LangUtil.throwIaxIfNull(handler, "handler"); + + /** stack of handlers */ + private final Stack<IMessageHandler> handlers; + + /** list of File registered for deletion on demand */ + private final ArrayList<File> tempFiles; // deleteTempFiles requires ListIterator.remove() + + /** list of Sandboxes registered for cleanup on demand */ + private final ArrayList<Sandbox> sandboxes; + + /** if true, throw AbortException on failure */ + boolean abortOnFailure; + + /** this object prevents any changes to error-handling policy */ + private Object locker; + + public Validator(IMessageHandler handler) { + tempFiles = new ArrayList<>(); + sandboxes = new ArrayList<>(); + handlers = new Stack<>(); + pushHandler(handler); + } + + /** + * Push IMessageHandler onto stack, + * so it will be used until the next push or pop + * @param handler not null + * + */ + public void pushHandler(IMessageHandler handler) { + LangUtil.throwIaxIfNull(handler, "handler"); handlers.push(handler); - } - - /** @throws IllegalStateException if handler is not on top */ - public void popHandler(IMessageHandler handler) { - LangUtil.throwIaxIfNull(handler, "handler"); + } + + /** @throws IllegalStateException if handler is not on top */ + public void popHandler(IMessageHandler handler) { + LangUtil.throwIaxIfNull(handler, "handler"); if (handler != handlers.peek()) { throw new IllegalStateException("not current handler"); } handlers.pop(); - } - - /** @return true if this requestor now has locked the error handling policy */ - public boolean lock(Object requestor) { - if (null == locker) { - locker = requestor; - } - return (locker == requestor); - } - - /** @return true if the error handling policy is now unlocked */ - public boolean unlock(Object requestor) { - if (requestor == locker) { - locker = null; - } - return (locker == null); - } - - public void setAbortOnFailure(boolean abortOnFailure) { - if (null == locker) { - if (this.abortOnFailure != abortOnFailure) { - this.abortOnFailure = abortOnFailure; - } - } - } - - /** - * May fail with any of the messages - * <li>{null check} array<li> - * <li>{null check} {message}[#}<li> - */ - public boolean nullcheck(Object[] ra, String message) { - return ((nullcheck((Object) ra, message + " array")) - && nullcheck(Arrays.asList(ra), message)); - } - - /** - * Like nullcheck(Collection, message), except adding lower and upper bound - * @param atLeast fail if list size is smaller than this - * @param atMost fail if list size is greater than this - */ - public boolean nullcheck(Collection list, int atLeast, int atMost, String message) { - if (nullcheck(list, message)) { - int size = list.size(); - if (size < atLeast) { - fail(message + ": " + size + "<" + atLeast); - } else if (size > atMost) { - fail(message + ": " + size + ">" + atMost); - } else { - return true; - } - } - return false; - } - - /** - * May fail with any of the messages - * <li>{null check} list<li> - * <li>{null check} {message}[#}<li> - */ - public boolean nullcheck(Collection list, String message) { - if (nullcheck((Object) list, message + " list")) { - int i = 0; - for (Iterator iter = list.iterator(); iter.hasNext();) { + } + + /** @return true if this requestor now has locked the error handling policy */ + public boolean lock(Object requestor) { + if (null == locker) { + locker = requestor; + } + return (locker == requestor); + } + + /** @return true if the error handling policy is now unlocked */ + public boolean unlock(Object requestor) { + if (requestor == locker) { + locker = null; + } + return (locker == null); + } + + public void setAbortOnFailure(boolean abortOnFailure) { + if (null == locker) { + if (this.abortOnFailure != abortOnFailure) { + this.abortOnFailure = abortOnFailure; + } + } + } + + /** + * May fail with any of the messages + * <li>{null check} array<li> + * <li>{null check} {message}[#}<li> + */ + public boolean nullcheck(Object[] ra, String message) { + return ((nullcheck((Object) ra, message + " array")) + && nullcheck(Arrays.asList(ra), message)); + } + + /** + * Like nullcheck(Collection, message), except adding lower and upper bound + * @param atLeast fail if list size is smaller than this + * @param atMost fail if list size is greater than this + */ + public boolean nullcheck(Collection list, int atLeast, int atMost, String message) { + if (nullcheck(list, message)) { + int size = list.size(); + if (size < atLeast) { + fail(message + ": " + size + "<" + atLeast); + } else if (size > atMost) { + fail(message + ": " + size + ">" + atMost); + } else { + return true; + } + } + return false; + } + + /** + * May fail with any of the messages + * <li>{null check} list<li> + * <li>{null check} {message}[#}<li> + */ + public boolean nullcheck(Collection list, String message) { + if (nullcheck((Object) list, message + " list")) { + int i = 0; + for (Iterator iter = list.iterator(); iter.hasNext();) { if (!nullcheck(iter.next(), message + "[" + i++ + "]")) { - return false; - } + return false; + } } - return true; - } - return false; - } - - /** - * May fail with the message "null {message}" - * if o and the def{ault} are null - * @return o if not null or default otherwise - */ - public Object nulldefault(Object o, String message, Object def) { - if (null == o) { - o = def; - } - nullcheck(o, message); - return o; - } - - /** may fail with the message "null {message}" */ - public boolean nullcheck(Object o, String message) { - if (null == o) { - if (null == message) message = "object"; - fail("null " + message); - return false; - } - return true; - } - - /** - * Verify that all paths are readable relative to baseDir. - * may fail with the message "cannot read {file}" - */ - public boolean canRead(File baseDir, String[] paths, String message) { - if (!canRead(baseDir, "baseDir - " + message) - || !nullcheck(paths, "paths - " + message)) { - return false; - } - final String dirPath = baseDir.getPath(); - File[] files = FileUtil.getBaseDirFiles(baseDir, paths); - for (int j = 0; j < files.length; j++) { - if (!canRead(files[j], "{" + dirPath + "} " + files[j])) { - return false; - } - } - return true; - } - - /** - * Verify that all paths are readable relative to baseDir. - * may fail with the message "cannot read {file}" - */ - public boolean canRead(File[] files, String message) { - if (!nullcheck(files, message)) { - return false; - } - for (int j = 0; j < files.length; j++) { - if (!canRead(files[j], files[j].getPath())) { - return false; - } - } - return true; - } - - /** may fail with the message "cannot read {file}" */ - public boolean canRead(File file, String message) { - if (nullcheck(file, message)) { - if (file.canRead()) { - return true; - } else { - fail("cannot read " + file); - } - } - return false; - } - - /** may fail with the message "cannot write {file}" */ - public boolean canWrite(File file, String message) { - if (nullcheck(file, message)) { - if (file.canRead()) { - return true; - } else { - fail("cannot write " + file); - } - } - return false; - } - - /** may fail with the message "not a directory {file}" */ - public boolean canReadDir(File file, String message) { - if (canRead(file, message)) { - if (file.isDirectory()) { - return true; - } else { - fail("not a directory " + file); - } - } - return false; - } - - /** may fail with the message "not a directory {file}" */ - public boolean canWriteDir(File file, String message) { - if (canWrite(file, message)) { - if (file.isDirectory()) { - return true; - } else { - fail("not a directory " + file); - } - } - return false; - } - - /** - * May fail with any of the messages - * <li>{null check} dir array<li> - * <li>"#: not a File {file}"<li> - * <li>{canRead} {message}[#}<li> - */ - public boolean canReadFiles(Object[] dirs, String message) { - return ((nullcheck((Object) dirs, message + " dir array")) - && canReadFiles(Arrays.asList(dirs), message)); - } - - /** - * May fail with any of the messages - * <li>{null check} files<li> - * <li>"#: not a File {file}"<li> - * <li>{canRead} {message}[#}<li> - */ - public boolean canReadFiles(Collection dirs, String message) { - if (nullcheck((Object) dirs, message + " files")) { - int i = 0; - for (Iterator iter = dirs.iterator(); iter.hasNext();) { - Object o = iter.next(); - if (! (o instanceof File)) { - fail(i + ": not a file " + o); - } - if (!canRead((File) o, message + "[" + i++ + "]")) { - return false; - } - } - return true; - } - return false; - } - /** - * May fail with any of the messages - * <li>{null check} dir array<li> - * <li>"#: not a File {file}"<li> - * <li>{canReadDir} {message}[#}<li> - */ - public boolean canReadDirs(Object[] dirs, String message) { - return ((nullcheck((Object) dirs, message + " dir array")) - && canReadDirs(Arrays.asList(dirs), message)); - } - - /** - * May fail with any of the messages - * <li>{null check} dirs<li> - * <li>"#: not a File {file}"<li> - * <li>{canReadDir} {message}[#}<li> - */ - public boolean canReadDirs(Collection dirs, String message) { - if (nullcheck((Object) dirs, message + " dirs")) { - int i = 0; - for (Iterator iter = dirs.iterator(); iter.hasNext();) { - Object o = iter.next(); - if (! (o instanceof File)) { - fail(i + ": not a file " + o); - } - if (!canReadDir((File) o, message + "[" + i++ + "]")) { - return false; - } - } - return true; - } - return false; - } - - /** - * May fail with any of the messages - * <li>{null check} dir array<li> - * <li>"#: not a File {file}"<li> - * <li>{canWrite} {message}[#}<li> - */ - public boolean canWriteFiles(Object[] dirs, String message) { - return ((nullcheck((Object) dirs, message + " dir array")) - && canWriteFiles(Arrays.asList(dirs), message)); - } - - /** - * May fail with any of the messages - * <li>{null check} files<li> - * <li>"#: not a File {file}"<li> - * <li>{canWrite} {message}[#}<li> - */ - public boolean canWriteFiles(Collection dirs, String message) { - if (nullcheck((Object) dirs, message + " files")) { - int i = 0; - for (Iterator iter = dirs.iterator(); iter.hasNext();) { - Object o = iter.next(); - if (! (o instanceof File)) { - fail(i + ": not a file " + o); - } - if (!canWrite((File) o, message + "[" + i++ + "]")) { - return false; - } - } - return true; - } - return false; - } - - /** - * May fail with any of the messages - * <li>{null check} dir array<li> - * <li>"#: not a File {file}"<li> - * <li>{canWriteDir} {message}[#}<li> - */ - public boolean canWriteDirs(Object[] dirs, String message) { - return ((nullcheck((Object) dirs, message + " dir array")) - && canWriteDirs(Arrays.asList(dirs), message)); - } - - /** - * May fail with any of the messages - * <li>{null check} dirs<li> - * <li>"#: not a File {file}"<li> - * <li>{canWriteDir} {message}[#}<li> - */ - public boolean canWriteDirs(Collection dirs, String message) { - if (nullcheck((Object) dirs, message + " dirs")) { - int i = 0; - for (Iterator iter = dirs.iterator(); iter.hasNext();) { - Object o = iter.next(); - if (! (o instanceof File)) { - fail(i + ": not a file " + o); - } - if (!canWriteDir((File) o, message + "[" + i++ + "]")) { - return false; - } - } - return true; - } - return false; - } - - /** - * Send an info message to any underlying handler - * @param message ignored if null - */ - public void info(String message) { - if (null != message) { - IMessageHandler handler = getHandler(); - MessageUtil.info(handler, message); - } - } - - /** Fail via message or AbortException */ - public void fail(String message) { - fail(message, (Throwable) null); - } - - /** - * Fail via message or AbortException. - * All failure messages go through here, - * so subclasses may override to control - * failure-handling. - */ - public void fail(String message, Throwable thrown) { - if ((null == message) && (null == thrown)) { - message = "<Validator:no message>"; - } - IMessage m = MessageUtil.fail(message, thrown); - if (abortOnFailure) { - throw new AbortException(m); - } else { - IMessageHandler handler = getHandler(); - handler.handleMessage(m); - } - } - - /** - * Register a file temporary, i.e., to be - * deleted on completion. The file need not - * exist (yet or ever) and may be a duplicate - * of existing files registered. - */ - public void registerTempFile(File file) { - if (null != file) { - tempFiles.add(file); - } - } - - /** - * Get a writable {possibly-empty} directory. - * If the input dir is null, then try to create a temporary - * directory using name. - * If the input dir is not null, this tries to - * create it if it does not exist. - * Then if name is not null, - * it tries to get a temporary directory - * under this using name. - * If name is null, "Validator" is used. - * If deleteContents is true, this will try to delete - * any existing contents. If this is unable to delete - * the contents of the input directory, this may return - * a new, empty temporary directory. - * If register is true, then any directory returned is - * saved for later deletion using <code>deleteTempDirs()</code>, - * including the input directory. - * When this is unable to create a result, if failMessage - * is not null then this will fail; otherwise it returns false; - */ - public File getWritableDir(File dir, String name, - boolean deleteContents, boolean register, String failMessage) { - // check dir - if (null == dir) { - if (null == name) { - name = "Validator"; - } - dir = FileUtil.getTempDir(name); - } else { - if (!dir.exists()) { - dir.mkdirs(); - } - } - // fail if necessary - if ((null == dir) || (!dir.exists())) { - if (null != failMessage) { - fail(failMessage + ": unable to get parent " + dir); - } - } else { - FileUtil.makeNewChildDir(dir, name); - if (deleteContents) { - FileUtil.deleteContents(dir); - } - if (register) { - tempFiles.add(dir); - } - } - return dir; - } - - /** - * Delete any temp sandboxes, files or directories saved, - * optionally reporting failures in the normal way. - * This will be ignored unless the failure policy - * is unlocked. - */ - public void deleteTempFiles(boolean reportFailures) { - if (null == locker) { - for (ListIterator iter = tempFiles.listIterator(); iter.hasNext();) { - if (deleteFile((File) iter.next(), reportFailures)) { - iter.remove(); - } - } - for (ListIterator iter = sandboxes.listIterator(); iter.hasNext();) { - Sandbox sandbox = (Sandbox) iter.next(); - // XXX assumes all dirs are in sandboxDir - if (deleteFile(sandbox.sandboxDir, reportFailures)) { - iter.remove(); - } - } - } - } + return true; + } + return false; + } + + /** + * May fail with the message "null {message}" + * if o and the def{ault} are null + * @return o if not null or default otherwise + */ + public Object nulldefault(Object o, String message, Object def) { + if (null == o) { + o = def; + } + nullcheck(o, message); + return o; + } + + /** may fail with the message "null {message}" */ + public boolean nullcheck(Object o, String message) { + if (null == o) { + if (null == message) message = "object"; + fail("null " + message); + return false; + } + return true; + } + + /** + * Verify that all paths are readable relative to baseDir. + * may fail with the message "cannot read {file}" + */ + public boolean canRead(File baseDir, String[] paths, String message) { + if (!canRead(baseDir, "baseDir - " + message) + || !nullcheck(paths, "paths - " + message)) { + return false; + } + final String dirPath = baseDir.getPath(); + File[] files = FileUtil.getBaseDirFiles(baseDir, paths); + for (File file : files) { + if (!canRead(file, "{" + dirPath + "} " + file)) { + return false; + } + } + return true; + } + + /** + * Verify that all paths are readable relative to baseDir. + * may fail with the message "cannot read {file}" + */ + public boolean canRead(File[] files, String message) { + if (!nullcheck(files, message)) { + return false; + } + for (File file : files) { + if (!canRead(file, file.getPath())) { + return false; + } + } + return true; + } + + /** may fail with the message "cannot read {file}" */ + public boolean canRead(File file, String message) { + if (nullcheck(file, message)) { + if (file.canRead()) { + return true; + } else { + fail("cannot read " + file); + } + } + return false; + } + + /** may fail with the message "cannot write {file}" */ + public boolean canWrite(File file, String message) { + if (nullcheck(file, message)) { + if (file.canRead()) { + return true; + } else { + fail("cannot write " + file); + } + } + return false; + } + + /** may fail with the message "not a directory {file}" */ + public boolean canReadDir(File file, String message) { + if (canRead(file, message)) { + if (file.isDirectory()) { + return true; + } else { + fail("not a directory " + file); + } + } + return false; + } + + /** may fail with the message "not a directory {file}" */ + public boolean canWriteDir(File file, String message) { + if (canWrite(file, message)) { + if (file.isDirectory()) { + return true; + } else { + fail("not a directory " + file); + } + } + return false; + } + + /** + * May fail with any of the messages + * <li>{null check} dir array<li> + * <li>"#: not a File {file}"<li> + * <li>{canRead} {message}[#}<li> + */ + public boolean canReadFiles(Object[] dirs, String message) { + return ((nullcheck((Object) dirs, message + " dir array")) + && canReadFiles(Arrays.asList(dirs), message)); + } + + /** + * May fail with any of the messages + * <li>{null check} files<li> + * <li>"#: not a File {file}"<li> + * <li>{canRead} {message}[#}<li> + */ + public boolean canReadFiles(Collection dirs, String message) { + if (nullcheck((Object) dirs, message + " files")) { + int i = 0; + for (Iterator iter = dirs.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (! (o instanceof File)) { + fail(i + ": not a file " + o); + } + if (!canRead((File) o, message + "[" + i++ + "]")) { + return false; + } + } + return true; + } + return false; + } + /** + * May fail with any of the messages + * <li>{null check} dir array<li> + * <li>"#: not a File {file}"<li> + * <li>{canReadDir} {message}[#}<li> + */ + public boolean canReadDirs(Object[] dirs, String message) { + return ((nullcheck((Object) dirs, message + " dir array")) + && canReadDirs(Arrays.asList(dirs), message)); + } + + /** + * May fail with any of the messages + * <li>{null check} dirs<li> + * <li>"#: not a File {file}"<li> + * <li>{canReadDir} {message}[#}<li> + */ + public boolean canReadDirs(Collection dirs, String message) { + if (nullcheck((Object) dirs, message + " dirs")) { + int i = 0; + for (Iterator iter = dirs.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (! (o instanceof File)) { + fail(i + ": not a file " + o); + } + if (!canReadDir((File) o, message + "[" + i++ + "]")) { + return false; + } + } + return true; + } + return false; + } + + /** + * May fail with any of the messages + * <li>{null check} dir array<li> + * <li>"#: not a File {file}"<li> + * <li>{canWrite} {message}[#}<li> + */ + public boolean canWriteFiles(Object[] dirs, String message) { + return ((nullcheck((Object) dirs, message + " dir array")) + && canWriteFiles(Arrays.asList(dirs), message)); + } + + /** + * May fail with any of the messages + * <li>{null check} files<li> + * <li>"#: not a File {file}"<li> + * <li>{canWrite} {message}[#}<li> + */ + public boolean canWriteFiles(Collection dirs, String message) { + if (nullcheck((Object) dirs, message + " files")) { + int i = 0; + for (Iterator iter = dirs.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (! (o instanceof File)) { + fail(i + ": not a file " + o); + } + if (!canWrite((File) o, message + "[" + i++ + "]")) { + return false; + } + } + return true; + } + return false; + } + + /** + * May fail with any of the messages + * <li>{null check} dir array<li> + * <li>"#: not a File {file}"<li> + * <li>{canWriteDir} {message}[#}<li> + */ + public boolean canWriteDirs(Object[] dirs, String message) { + return ((nullcheck((Object) dirs, message + " dir array")) + && canWriteDirs(Arrays.asList(dirs), message)); + } + + /** + * May fail with any of the messages + * <li>{null check} dirs<li> + * <li>"#: not a File {file}"<li> + * <li>{canWriteDir} {message}[#}<li> + */ + public boolean canWriteDirs(Collection dirs, String message) { + if (nullcheck((Object) dirs, message + " dirs")) { + int i = 0; + for (Iterator iter = dirs.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (! (o instanceof File)) { + fail(i + ": not a file " + o); + } + if (!canWriteDir((File) o, message + "[" + i++ + "]")) { + return false; + } + } + return true; + } + return false; + } + + /** + * Send an info message to any underlying handler + * @param message ignored if null + */ + public void info(String message) { + if (null != message) { + IMessageHandler handler = getHandler(); + MessageUtil.info(handler, message); + } + } + + /** Fail via message or AbortException */ + public void fail(String message) { + fail(message, (Throwable) null); + } + + /** + * Fail via message or AbortException. + * All failure messages go through here, + * so subclasses may override to control + * failure-handling. + */ + public void fail(String message, Throwable thrown) { + if ((null == message) && (null == thrown)) { + message = "<Validator:no message>"; + } + IMessage m = MessageUtil.fail(message, thrown); + if (abortOnFailure) { + throw new AbortException(m); + } else { + IMessageHandler handler = getHandler(); + handler.handleMessage(m); + } + } + + /** + * Register a file temporary, i.e., to be + * deleted on completion. The file need not + * exist (yet or ever) and may be a duplicate + * of existing files registered. + */ + public void registerTempFile(File file) { + if (null != file) { + tempFiles.add(file); + } + } + + /** + * Get a writable {possibly-empty} directory. + * If the input dir is null, then try to create a temporary + * directory using name. + * If the input dir is not null, this tries to + * create it if it does not exist. + * Then if name is not null, + * it tries to get a temporary directory + * under this using name. + * If name is null, "Validator" is used. + * If deleteContents is true, this will try to delete + * any existing contents. If this is unable to delete + * the contents of the input directory, this may return + * a new, empty temporary directory. + * If register is true, then any directory returned is + * saved for later deletion using <code>deleteTempDirs()</code>, + * including the input directory. + * When this is unable to create a result, if failMessage + * is not null then this will fail; otherwise it returns false; + */ + public File getWritableDir(File dir, String name, + boolean deleteContents, boolean register, String failMessage) { + // check dir + if (null == dir) { + if (null == name) { + name = "Validator"; + } + dir = FileUtil.getTempDir(name); + } else { + if (!dir.exists()) { + dir.mkdirs(); + } + } + // fail if necessary + if ((null == dir) || (!dir.exists())) { + if (null != failMessage) { + fail(failMessage + ": unable to get parent " + dir); + } + } else { + FileUtil.makeNewChildDir(dir, name); + if (deleteContents) { + FileUtil.deleteContents(dir); + } + if (register) { + tempFiles.add(dir); + } + } + return dir; + } + + /** + * Delete any temp sandboxes, files or directories saved, + * optionally reporting failures in the normal way. + * This will be ignored unless the failure policy + * is unlocked. + */ + public void deleteTempFiles(boolean reportFailures) { + if (null == locker) { + for (ListIterator iter = tempFiles.listIterator(); iter.hasNext();) { + if (deleteFile((File) iter.next(), reportFailures)) { + iter.remove(); + } + } + for (ListIterator iter = sandboxes.listIterator(); iter.hasNext();) { + Sandbox sandbox = (Sandbox) iter.next(); + // XXX assumes all dirs are in sandboxDir + if (deleteFile(sandbox.sandboxDir, reportFailures)) { + iter.remove(); + } + } + } + } /** * Manage temp files and directories of registered sandboxes. - * Note that a sandbox may register before it is initialized, - * so this must do nothing other than save the reference. + * Note that a sandbox may register before it is initialized, + * so this must do nothing other than save the reference. * @param sandbox the uninitialized Sandbox to track */ public void registerSandbox(Sandbox sandbox) { - sandboxes.add(sandbox); - } - - - private boolean deleteFile(File file, boolean reportFailures) { - if (null == file) { - if (reportFailures) { - fail("unable to delete null file"); - } - return true; // null file - skip - } - FileUtil.deleteContents(file); - if (file.exists()) { - file.delete(); - } - if (!file.exists()) { - return true; - } else if (reportFailures) { - fail("unable to delete " + file); - } - return false; - } - - /** @throws IllegalStateException if handler is null */ + sandboxes.add(sandbox); + } + + + private boolean deleteFile(File file, boolean reportFailures) { + if (null == file) { + if (reportFailures) { + fail("unable to delete null file"); + } + return true; // null file - skip + } + FileUtil.deleteContents(file); + if (file.exists()) { + file.delete(); + } + if (!file.exists()) { + return true; + } else if (reportFailures) { + fail("unable to delete " + file); + } + return false; + } + + /** @throws IllegalStateException if handler is null */ private IMessageHandler getHandler() { - IMessageHandler handler = (IMessageHandler) handlers.peek(); + IMessageHandler handler = handlers.peek(); if (null == handler) { throw new IllegalStateException("no handler"); } @@ -561,4 +561,4 @@ public class Validator { } } // class Validator - + |