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 | |
parent | c3c07fdb4b93cc483317d8a314233f0b9dcf4d8b (diff) | |
download | aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.tar.gz aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.zip |
polish
10 files changed, 3813 insertions, 3734 deletions
diff --git a/ajde/src/main/java/org/aspectj/ajde/ui/internal/TreeStructureViewBuilder.java b/ajde/src/main/java/org/aspectj/ajde/ui/internal/TreeStructureViewBuilder.java index 9021cbfe7..728ed9069 100644 --- a/ajde/src/main/java/org/aspectj/ajde/ui/internal/TreeStructureViewBuilder.java +++ b/ajde/src/main/java/org/aspectj/ajde/ui/internal/TreeStructureViewBuilder.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 * ******************************************************************/ @@ -46,132 +46,132 @@ public class TreeStructureViewBuilder { * @todo get rid of instanceof tests */ public void buildView(StructureView view, IHierarchy model) { -// StructureViewProperties properties = view.getViewProperties(); + // StructureViewProperties properties = view.getViewProperties(); IProgramElement modelRoot = null; -// boolean noStructure = false; + // boolean noStructure = false; if (isFileView(view)) { FileStructureView fileView = (FileStructureView)view; - if (fileView.getSourceFile() == null) { + if (fileView.getSourceFile() == null) { modelRoot = IHierarchy.NO_STRUCTURE; -// noStructure = true; + // noStructure = true; } else { modelRoot = model.findElementForSourceFile(fileView.getSourceFile()); } } else { modelRoot = model.getRoot(); } - + IStructureViewNode viewRoot = null; if (!isFileView(view)) { - StructureViewProperties.Hierarchy hierarchy - = ((GlobalStructureView)view).getGlobalViewProperties().getHierarchy(); - if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING) - || hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { - viewRoot = buildCustomTree((GlobalStructureView)view, model); - } - } + StructureViewProperties.Hierarchy hierarchy + = ((GlobalStructureView)view).getGlobalViewProperties().getHierarchy(); + if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING) + || hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { + viewRoot = buildCustomTree((GlobalStructureView)view, model); + } + } if (viewRoot == null) { viewRoot = createViewNode(modelRoot, view.getViewProperties());//modelRoot; - } - + } + if (view.getViewProperties().getSorting() == StructureViewProperties.Sorting.ALPHABETICAL - || (!isFileView(view) && - ((GlobalStructureView)view).getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.DECLARATION))) { + || (!isFileView(view) && + ((GlobalStructureView)view).getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.DECLARATION))) { sortView(viewRoot, ALPHABETICAL_COMPARATOR); } else { sortView(viewRoot, DECLARATIONAL_COMPARATOR); - } - + } + addPackageNode(view, viewRoot); view.setRootNode(viewRoot); } private void addPackageNode(StructureView view, IStructureViewNode viewRoot) { if (isFileView(view)) { -// IProgramElement fileNode = viewRoot.getStructureNode(); -// IProgramElement parentNode = fileNode.getParent(); -// -// if (parentNode.getKind() == IProgramElement.Kind.PACKAGE) { -// String name = parentNode.getName(); -// IProgramElement packageNode = new ProgramElement(name, IProgramElement.Kind.PACKAGE, null); -// packageNode.setSourceLocation(fileNode.getSourceLocation()); -// StructureViewNode packageViewNode = createViewNode( -// packageNode, -// view.getViewProperties() -// ); -// viewRoot.getChildren().add(0, packageViewNode); -// }; + // IProgramElement fileNode = viewRoot.getStructureNode(); + // IProgramElement parentNode = fileNode.getParent(); + // + // if (parentNode.getKind() == IProgramElement.Kind.PACKAGE) { + // String name = parentNode.getName(); + // IProgramElement packageNode = new ProgramElement(name, IProgramElement.Kind.PACKAGE, null); + // packageNode.setSourceLocation(fileNode.getSourceLocation()); + // StructureViewNode packageViewNode = createViewNode( + // packageNode, + // view.getViewProperties() + // ); + // viewRoot.getChildren().add(0, packageViewNode); + // }; } } - + private IStructureViewNode createViewNode(IProgramElement node, StructureViewProperties properties) { if (node == null) return null; List children = new ArrayList(); -// IProgramElement pNode = node; -// if (node.getRelations() != null) { -// for (Iterator it = node.getRelations().iterator(); it.hasNext(); ) { -// IProgramElement IProgramElement = (IProgramElement)it.next(); -// if (acceptNode(IProgramElement, properties)) { -// children.add(createViewNode(IProgramElement, properties)); -// } -// } -// } + // IProgramElement pNode = node; + // if (node.getRelations() != null) { + // for (Iterator it = node.getRelations().iterator(); it.hasNext(); ) { + // IProgramElement IProgramElement = (IProgramElement)it.next(); + // if (acceptNode(IProgramElement, properties)) { + // children.add(createViewNode(IProgramElement, properties)); + // } + // } + // } if (node.isRunnable() && node.getParent() != null) { IProgramElement parent = node.getParent(); if (parent.getKind().equals(IProgramElement.Kind.CLASS) - || parent.getKind().equals(IProgramElement.Kind.ASPECT)) { - parent.setRunnable(true); + || parent.getKind().equals(IProgramElement.Kind.ASPECT)) { + parent.setRunnable(true); node.setRunnable(false); } } if (node.getChildren() != null) { - for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { - IProgramElement IProgramElement = (IProgramElement)it.next(); + for (Object element : node.getChildren()) { + IProgramElement IProgramElement = (IProgramElement)element; if (acceptNode(IProgramElement, properties)) { children.add(createViewNode(IProgramElement, properties)); } - } + } } IStructureViewNode viewNode = nodeFactory.createNode(node, children);//new TreeViewNode(root, null, children); - return viewNode; + return viewNode; } - + /** * @todo get rid of this test, fix polymorphism */ private boolean isFileView(StructureView view) { return view instanceof FileStructureView - && !(view instanceof GlobalStructureView); + && !(view instanceof GlobalStructureView); } - + private boolean acceptGranularity(IProgramElement.Kind kind, StructureViewProperties.Granularity granularity) { - + if (granularity == StructureViewProperties.Granularity.DECLARED_ELEMENTS) { return true; - } else if (granularity == StructureViewProperties.Granularity.MEMBER && - (kind != IProgramElement.Kind.CODE)) { + } else if (granularity == StructureViewProperties.Granularity.MEMBER && + (kind != IProgramElement.Kind.CODE)) { return true; } else if (granularity == StructureViewProperties.Granularity.TYPE - && (kind == IProgramElement.Kind.PROJECT + && (kind == IProgramElement.Kind.PROJECT || kind == IProgramElement.Kind.PACKAGE || kind.isSourceFile() || kind.isType())) { - return true; + return true; } else if (granularity == StructureViewProperties.Granularity.FILE - && (kind == IProgramElement.Kind.PROJECT + && (kind == IProgramElement.Kind.PROJECT || kind == IProgramElement.Kind.PACKAGE || kind.isSourceFile())) { - return true; + return true; } else if (granularity == StructureViewProperties.Granularity.PACKAGE - && (kind == IProgramElement.Kind.PROJECT + && (kind == IProgramElement.Kind.PROJECT || kind == IProgramElement.Kind.PACKAGE)) { - return true; + return true; } else { return false; } } - + private boolean acceptNode(IProgramElement node, StructureViewProperties properties) { if (node!=null) { IProgramElement pNode = node; @@ -179,250 +179,249 @@ public class TreeStructureViewBuilder { return false; } else if (pNode.getKind().isMember()) { if (properties.getFilteredMemberAccessibility().contains(pNode.getAccessibility())) { - return false; + return false; } if (properties.getFilteredMemberKinds().contains(pNode.getKind())) { - return false; + return false; } - for (Iterator it = pNode.getModifiers().iterator(); it.hasNext(); ) { - if (properties.getFilteredMemberModifiers().contains(it.next())) { - return false; - } + for (Object element : pNode.getModifiers()) { + if (properties.getFilteredMemberModifiers().contains(element)) { + return false; + } } } } return true; } - private void sortView(IStructureViewNode node, Comparator comparator) { + private void sortView(IStructureViewNode node, Comparator<IStructureViewNode> comparator) { if (node == null || node.getChildren() == null) return; Collections.sort(node.getChildren(), comparator); for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { IStructureViewNode nextNode = (IStructureViewNode)it.next(); - if (nextNode != null) sortView(nextNode, comparator); + if (nextNode != null) sortView(nextNode, comparator); } } - private IStructureViewNode buildCustomTree(GlobalStructureView view, IHierarchy model) { - IProgramElement rootNode = model.getRoot(); - IStructureViewNode treeNode = nodeFactory.createNode(rootNode); - - List rootNodes = new ArrayList(); - getRoots(rootNode, rootNodes, view.getGlobalViewProperties().getHierarchy()); - - for (Iterator it = rootNodes.iterator(); it.hasNext(); ) { - if (view.getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { - treeNode.add(getCrosscuttingChildren((IProgramElement)it.next())); - } else if (view.getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.INHERITANCE)) { - treeNode.add(getInheritanceChildren( - (IProgramElement)it.next(), - view.getViewProperties().getRelations()) - ); - } - } - return treeNode; - } - - private void getRoots(IProgramElement rootNode, List roots, StructureViewProperties.Hierarchy hierarchy) { -// if (rootNode != null && rootNode.getChildren() != null) { -// for (Iterator it = rootNode.getChildren().iterator(); it.hasNext(); ) { -// IProgramElement node = (IProgramElement)it.next(); -// if (node instanceof IProgramElement) { -// if (acceptNodeAsRoot((IProgramElement)node, hierarchy)) { -// IProgramElement pNode = (IProgramElement)node; -// List relations = pNode.getRelations(); -// String delimiter = ""; -// if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { -// delimiter = "uses pointcut"; -// } else if (hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { -// delimiter = "inherits"; -// } -// if (relations != null && relations.toString().indexOf(delimiter) == -1) { -// boolean found = false; -// for (Iterator it2 = roots.iterator(); it2.hasNext(); ) { -// if (((IProgramElement)it2.next()).equals(pNode)) found = true; -// } -// if (!found) roots.add(pNode); -// } -// } -// } -// getRoots(node, roots, hierarchy); -// } -// } - } - - public boolean acceptNodeAsRoot(IProgramElement node, StructureViewProperties.Hierarchy hierarchy) { - if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { - return node.getKind().equals(IProgramElement.Kind.ADVICE) - || node.getKind().equals(IProgramElement.Kind.POINTCUT); - } else if (hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { - return node.getKind().equals(IProgramElement.Kind.CLASS); - } else { - return false; - } - } - - private IStructureViewNode getInheritanceChildren(IProgramElement node, List associations) { -// IStructureViewNode treeNode = nodeFactory.createNode(node); -// //StructureViewNode treeNode = new StructureViewNodeAdapter(node); -// List relations = ((IProgramElement)node).getRelations(); - throw new RuntimeException("unimplemented"); -// if (relations != null) { -// for (Iterator it = relations.iterator(); it.hasNext(); ) { -// IRelationship relation = (IRelationship)it.next(); -// if (relation.getName().equals("is inherited by")) { -// for (Iterator it2 = relation.getTargets().iterator(); it2.hasNext(); ) { -//// IProgramElement pNode = ((LinkNode)it2.next()).getProgramElementNode(); -//// StructureViewNode newNode = getInheritanceChildren(pNode, associations); -// StructureViewNode typeChildren = buildTree(newNode.getStructureNode(), associations); -// for (int i = 0; i < typeChildren.getChildren().size(); i++) { -// newNode.add((StructureViewNode)typeChildren.getChildren().get(i)); -// } -// treeNode.add(newNode); -// } -// } -// } -// } -// return treeNode; - } - - private IStructureViewNode getCrosscuttingChildren(IProgramElement node) { - //StructureViewNodeAdapter treeNode = new StructureViewNodeAdapter(node); -// IStructureViewNode treeNode = nodeFactory.createNode(node); -// List relations = ((IProgramElement)node).getRelations(); - throw new RuntimeException("unimplemented"); -// if (relations != null) { -// for (Iterator it = relations.iterator(); it.hasNext(); ) { -// IRelationship relation = (IRelationship)it.next(); -// if (relation.getName().equals("pointcut used by")) { -// for (Iterator it2 = relation.getTargets().iterator(); it2.hasNext(); ) { -// IProgramElement pNode = ((LinkNode)it2.next()).getProgramElementNode(); -// StructureViewNode newNode = getCrosscuttingChildren(pNode); -// for (Iterator it3 = pNode.getRelations().iterator(); it3.hasNext(); ) { -// IRelationship relationNode = (IRelation)it3.next(); -// if (relationNode.getName().indexOf("pointcut") == -1) { -// newNode.add(getRelations(relationNode)); -// } -// } -// treeNode.add(newNode); -// } -// } else if (relations.toString().indexOf("uses pointcut") == -1) { -// for (Iterator it4 = relations.iterator(); it4.hasNext(); ) { -// IRelation relationNode = (IRelationship)it4.next(); -// if (relationNode.getName().indexOf("pointcut") == -1) { -// treeNode.add(getRelations(relationNode)); -// } -// } -// } -// } -// } -// return treeNode; - } - -// private IStructureViewNode buildTree(IProgramElement node, List associations) { -// //StructureViewNode treeNode = new StructureViewNodeAdapter(node); -// IStructureViewNode treeNode = nodeFactory.createNode(node); -//// if (node instanceof IProgramElement) { -// List relations = ((IProgramElement)node).getRelations(); -// if (relations != null) { -// for (Iterator it = relations.iterator(); it.hasNext(); ) { -// IRelationship relationNode = (IRelationship)it.next(); -// if (associations.contains(relationNode.toString())) { -// treeNode.add(buildTree(relationNode, associations)); -// } -// } -// } -// } -// if (node != null) { -// List children = null; -// children = node.getChildren(); -// if (children != null) { -// List childList = new ArrayList(); -// for (Iterator itt = children.iterator(); itt.hasNext(); ) { -// IProgramElement child = (IProgramElement)itt.next(); -// if (child instanceof IProgramElement) { -// IProgramElement progNode = (IProgramElement)child; -//// if (progNode.getKind() != IProgramElement.Kind.CODE) { -// childList.add(buildTree(child, associations)); -//// } -// } else { -// childList.add(buildTree(child, associations)); -// } -// } -// //sortNodes(childList); -// for (Iterator it = childList.iterator(); it.hasNext(); ) { -// treeNode.add((IStructureViewNode)it.next()); -// } -// } -// -// } -// return treeNode; -// } + private IStructureViewNode buildCustomTree(GlobalStructureView view, IHierarchy model) { + IProgramElement rootNode = model.getRoot(); + IStructureViewNode treeNode = nodeFactory.createNode(rootNode); -// private IStructureViewNode getRelations(IRelationship node) { -// return null; -// //StructureViewNode treeNode = new StructureViewNode(node); -//// IStructureViewNode treeNode = nodeFactory.c(node); -//// for (Iterator it = node.getTargets().iterator(); it.hasNext(); ) { -//// treeNode.add( -//// nodeFactory.createNode((IProgramElement)it.next()) -//// ); -//// } -//// return treeNode; -// } -// -// /** -// * For debugging only. -// */ -// private void dumpView(IStructureViewNode root, int level) { -// System.out.println(root.getStructureNode()); -// for (Iterator it = root.getChildren().iterator(); it.hasNext(); ) { -// dumpView((IStructureViewNode)it.next(), level++); -// } -// for (int i = 0; i < level; i++) { -// System.out.print(' '); -// } -// } + List rootNodes = new ArrayList(); + getRoots(rootNode, rootNodes, view.getGlobalViewProperties().getHierarchy()); + + for (Iterator it = rootNodes.iterator(); it.hasNext(); ) { + if (view.getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { + treeNode.add(getCrosscuttingChildren((IProgramElement)it.next())); + } else if (view.getGlobalViewProperties().getHierarchy().equals(StructureViewProperties.Hierarchy.INHERITANCE)) { + treeNode.add(getInheritanceChildren( + (IProgramElement)it.next(), + view.getViewProperties().getRelations()) + ); + } + } + return treeNode; + } + + private void getRoots(IProgramElement rootNode, List roots, StructureViewProperties.Hierarchy hierarchy) { + // if (rootNode != null && rootNode.getChildren() != null) { + // for (Iterator it = rootNode.getChildren().iterator(); it.hasNext(); ) { + // IProgramElement node = (IProgramElement)it.next(); + // if (node instanceof IProgramElement) { + // if (acceptNodeAsRoot((IProgramElement)node, hierarchy)) { + // IProgramElement pNode = (IProgramElement)node; + // List relations = pNode.getRelations(); + // String delimiter = ""; + // if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { + // delimiter = "uses pointcut"; + // } else if (hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { + // delimiter = "inherits"; + // } + // if (relations != null && relations.toString().indexOf(delimiter) == -1) { + // boolean found = false; + // for (Iterator it2 = roots.iterator(); it2.hasNext(); ) { + // if (((IProgramElement)it2.next()).equals(pNode)) found = true; + // } + // if (!found) roots.add(pNode); + // } + // } + // } + // getRoots(node, roots, hierarchy); + // } + // } + } + + public boolean acceptNodeAsRoot(IProgramElement node, StructureViewProperties.Hierarchy hierarchy) { + if (hierarchy.equals(StructureViewProperties.Hierarchy.CROSSCUTTING)) { + return node.getKind().equals(IProgramElement.Kind.ADVICE) + || node.getKind().equals(IProgramElement.Kind.POINTCUT); + } else if (hierarchy.equals(StructureViewProperties.Hierarchy.INHERITANCE)) { + return node.getKind().equals(IProgramElement.Kind.CLASS); + } else { + return false; + } + } + + private IStructureViewNode getInheritanceChildren(IProgramElement node, List associations) { + // IStructureViewNode treeNode = nodeFactory.createNode(node); + // //StructureViewNode treeNode = new StructureViewNodeAdapter(node); + // List relations = ((IProgramElement)node).getRelations(); + throw new RuntimeException("unimplemented"); + // if (relations != null) { + // for (Iterator it = relations.iterator(); it.hasNext(); ) { + // IRelationship relation = (IRelationship)it.next(); + // if (relation.getName().equals("is inherited by")) { + // for (Iterator it2 = relation.getTargets().iterator(); it2.hasNext(); ) { + //// IProgramElement pNode = ((LinkNode)it2.next()).getProgramElementNode(); + //// StructureViewNode newNode = getInheritanceChildren(pNode, associations); + // StructureViewNode typeChildren = buildTree(newNode.getStructureNode(), associations); + // for (int i = 0; i < typeChildren.getChildren().size(); i++) { + // newNode.add((StructureViewNode)typeChildren.getChildren().get(i)); + // } + // treeNode.add(newNode); + // } + // } + // } + // } + // return treeNode; + } + + private IStructureViewNode getCrosscuttingChildren(IProgramElement node) { + //StructureViewNodeAdapter treeNode = new StructureViewNodeAdapter(node); + // IStructureViewNode treeNode = nodeFactory.createNode(node); + // List relations = ((IProgramElement)node).getRelations(); + throw new RuntimeException("unimplemented"); + // if (relations != null) { + // for (Iterator it = relations.iterator(); it.hasNext(); ) { + // IRelationship relation = (IRelationship)it.next(); + // if (relation.getName().equals("pointcut used by")) { + // for (Iterator it2 = relation.getTargets().iterator(); it2.hasNext(); ) { + // IProgramElement pNode = ((LinkNode)it2.next()).getProgramElementNode(); + // StructureViewNode newNode = getCrosscuttingChildren(pNode); + // for (Iterator it3 = pNode.getRelations().iterator(); it3.hasNext(); ) { + // IRelationship relationNode = (IRelation)it3.next(); + // if (relationNode.getName().indexOf("pointcut") == -1) { + // newNode.add(getRelations(relationNode)); + // } + // } + // treeNode.add(newNode); + // } + // } else if (relations.toString().indexOf("uses pointcut") == -1) { + // for (Iterator it4 = relations.iterator(); it4.hasNext(); ) { + // IRelation relationNode = (IRelationship)it4.next(); + // if (relationNode.getName().indexOf("pointcut") == -1) { + // treeNode.add(getRelations(relationNode)); + // } + // } + // } + // } + // } + // return treeNode; + } + + // private IStructureViewNode buildTree(IProgramElement node, List associations) { + // //StructureViewNode treeNode = new StructureViewNodeAdapter(node); + // IStructureViewNode treeNode = nodeFactory.createNode(node); + //// if (node instanceof IProgramElement) { + // List relations = ((IProgramElement)node).getRelations(); + // if (relations != null) { + // for (Iterator it = relations.iterator(); it.hasNext(); ) { + // IRelationship relationNode = (IRelationship)it.next(); + // if (associations.contains(relationNode.toString())) { + // treeNode.add(buildTree(relationNode, associations)); + // } + // } + // } + // } + // if (node != null) { + // List children = null; + // children = node.getChildren(); + // if (children != null) { + // List childList = new ArrayList(); + // for (Iterator itt = children.iterator(); itt.hasNext(); ) { + // IProgramElement child = (IProgramElement)itt.next(); + // if (child instanceof IProgramElement) { + // IProgramElement progNode = (IProgramElement)child; + //// if (progNode.getKind() != IProgramElement.Kind.CODE) { + // childList.add(buildTree(child, associations)); + //// } + // } else { + // childList.add(buildTree(child, associations)); + // } + // } + // //sortNodes(childList); + // for (Iterator it = childList.iterator(); it.hasNext(); ) { + // treeNode.add((IStructureViewNode)it.next()); + // } + // } + // + // } + // return treeNode; + // } + + // private IStructureViewNode getRelations(IRelationship node) { + // return null; + // //StructureViewNode treeNode = new StructureViewNode(node); + //// IStructureViewNode treeNode = nodeFactory.c(node); + //// for (Iterator it = node.getTargets().iterator(); it.hasNext(); ) { + //// treeNode.add( + //// nodeFactory.createNode((IProgramElement)it.next()) + //// ); + //// } + //// return treeNode; + // } + // + // /** + // * For debugging only. + // */ + // private void dumpView(IStructureViewNode root, int level) { + // System.out.println(root.getStructureNode()); + // for (Iterator it = root.getChildren().iterator(); it.hasNext(); ) { + // dumpView((IStructureViewNode)it.next(), level++); + // } + // for (int i = 0; i < level; i++) { + // System.out.print(' '); + // } + // } /** * Does not sort imports alphabetically. */ - private static final Comparator ALPHABETICAL_COMPARATOR = new Comparator() { - public int compare(Object o1, Object o2) { - IProgramElement sv1 = ((IStructureViewNode)o1).getStructureNode(); - IProgramElement sv2 = ((IStructureViewNode)o2).getStructureNode(); - - if (sv1!=null && sv2!=null) { - + private static final Comparator<IStructureViewNode> ALPHABETICAL_COMPARATOR = new Comparator<IStructureViewNode>() { + @Override + public int compare(IStructureViewNode o1, IStructureViewNode o2) { + IProgramElement sv1 = o1.getStructureNode(); + IProgramElement sv2 = o2.getStructureNode(); + if (sv1!=null && sv2!=null) { if (sv2.getKind() == IProgramElement.Kind.IMPORT_REFERENCE) return 1; if (sv1.getKind() == IProgramElement.Kind.IMPORT_REFERENCE) return -1; - return sv1.getName().compareTo(sv2.getName()); - } else { - return 0; - } - } - }; - - private static final Comparator DECLARATIONAL_COMPARATOR = new Comparator() { - public int compare(Object o1, Object o2) { - IProgramElement sv1 = ((IStructureViewNode)o1).getStructureNode(); - IProgramElement sv2 = ((IStructureViewNode)o2).getStructureNode(); - if (sv1!=null && sv2!=null) { - if (sv2.getKind() == IProgramElement.Kind.IMPORT_REFERENCE) return 1; + } else { + return 0; + } + } + }; + + private static final Comparator<IStructureViewNode> DECLARATIONAL_COMPARATOR = new Comparator<IStructureViewNode>() { + @Override + public int compare(IStructureViewNode o1, IStructureViewNode o2) { + IProgramElement sv1 = o1.getStructureNode(); + IProgramElement sv2 = o2.getStructureNode(); + if (sv1!=null && sv2!=null) { + if (sv2.getKind() == IProgramElement.Kind.IMPORT_REFERENCE) return 1; if (sv1.getKind() == IProgramElement.Kind.IMPORT_REFERENCE) return -1; - if (sv1.getSourceLocation() == null || sv2.getSourceLocation() == null) { - return 0; - } else if (sv1.getSourceLocation().getLine() < sv2.getSourceLocation().getLine()) { - return -1; - } else { - return 1; - } - } else { - return 0; - } - } - }; + if (sv1.getSourceLocation() == null || sv2.getSourceLocation() == null) { + return 0; + } else if (sv1.getSourceLocation().getLine() < sv2.getSourceLocation().getLine()) { + return -1; + } else { + return 1; + } + } else { + return 0; + } + } + }; } // private boolean acceptNode(ProgramElementNode node) { diff --git a/ajde/src/main/java/org/aspectj/ajde/ui/internal/UserPreferencesStore.java b/ajde/src/main/java/org/aspectj/ajde/ui/internal/UserPreferencesStore.java index b1120f0fb..572506aed 100644 --- a/ajde/src/main/java/org/aspectj/ajde/ui/internal/UserPreferencesStore.java +++ b/ajde/src/main/java/org/aspectj/ajde/ui/internal/UserPreferencesStore.java @@ -1,19 +1,19 @@ /* ******************************************************************* - * 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: + * 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 - * Helen Hawkins Converted to new interface (bug 148190) + * Helen Hawkins Converted to new interface (bug 148190) * ******************************************************************/ - - + + package org.aspectj.ajde.ui.internal; import java.io.File; @@ -33,121 +33,129 @@ import org.aspectj.bridge.Message; import org.aspectj.util.LangUtil; public class UserPreferencesStore implements UserPreferencesAdapter { - public static final String FILE_NAME = "/.ajbrowser"; - private static final String VALUE_SEP = ";"; - private Properties properties = new Properties(); - private boolean persist = true; - + public static final String FILE_NAME = "/.ajbrowser"; + private static final String VALUE_SEP = ";"; + private Properties properties = new Properties(); + private boolean persist = true; + public UserPreferencesStore() { - this(true); + this(true); + } + + public UserPreferencesStore(boolean loadDefault) { + persist = loadDefault; + if (persist) { + loadProperties(getPropertiesFilePath()); + } + } + + @Override + public String getProjectPreference(String name) { + return properties.getProperty(name); + } + + @Override + public List<String> getProjectMultivalPreference(String name) { + List<String> values = new ArrayList<>(); + String valuesString = properties.getProperty(name); + if (valuesString != null && !valuesString.trim().equals("")) { + StringTokenizer st = new StringTokenizer(valuesString, VALUE_SEP); + while (st.hasMoreTokens()) { + values.add(st.nextToken()); + } + } + return values; + } + + @Override + public void setProjectPreference(String name, String value) { + properties.setProperty(name, value); + saveProperties(); + } + + @Override + public void setProjectMultivalPreference(String name, List values) { + String valuesString = ""; + for (Iterator it = values.iterator(); it.hasNext(); ) { + valuesString += (String)it.next() + ';'; + } + properties.setProperty(name, valuesString); + saveProperties(); + } + + public static String getPropertiesFilePath() { + String path = System.getProperty("user.home"); + if (path == null) { + path = "."; + } + return path + FILE_NAME; } - public UserPreferencesStore(boolean loadDefault) { - persist = loadDefault; - if (persist) { - loadProperties(getPropertiesFilePath()); - } - } - - public String getProjectPreference(String name) { - return properties.getProperty(name); - } - - public List getProjectMultivalPreference(String name) { - List values = new ArrayList(); - String valuesString = properties.getProperty(name); - if (valuesString != null && !valuesString.trim().equals("")) { - StringTokenizer st = new StringTokenizer(valuesString, VALUE_SEP); - while (st.hasMoreTokens()) { - values.add(st.nextToken()); - } - } - return values; - } - - public void setProjectPreference(String name, String value) { - properties.setProperty(name, value); - saveProperties(); - } - - public void setProjectMultivalPreference(String name, List values) { - String valuesString = ""; - for (Iterator it = values.iterator(); it.hasNext(); ) { - valuesString += (String)it.next() + ';'; - } - properties.setProperty(name, valuesString); - saveProperties(); - } - - public static String getPropertiesFilePath() { - String path = System.getProperty("user.home"); - if (path == null) { - path = "."; - } - return path + FILE_NAME; - } - + @Override public String getGlobalPreference(String name) { return getProjectPreference(name); } - + + @Override public List getGlobalMultivalPreference(String name) { return getProjectMultivalPreference(name); } - + + @Override public void setGlobalPreference(String name, String value) { setProjectPreference(name, value); } - + + @Override public void setGlobalMultivalPreference(String name, List values) { setProjectMultivalPreference(name, values); } private void loadProperties(String path) { - if (LangUtil.isEmpty(path)) { - return; - } - File file = new File(path); - if (!file.canRead()) { - return; - } - FileInputStream in = null; - try { - path = getPropertiesFilePath(); - in = new FileInputStream(file); - properties.load(in); - } catch (IOException ioe) { - Message msg = new Message("Error reading properties from " + path,IMessage.ERROR,ioe,null); - Ajde.getDefault().getMessageHandler().handleMessage(msg); - } finally { - if (null != in) { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - } + if (LangUtil.isEmpty(path)) { + return; + } + File file = new File(path); + if (!file.canRead()) { + return; + } + FileInputStream in = null; + try { + path = getPropertiesFilePath(); + in = new FileInputStream(file); + properties.load(in); + } catch (IOException ioe) { + Message msg = new Message("Error reading properties from " + path,IMessage.ERROR,ioe,null); + Ajde.getDefault().getMessageHandler().handleMessage(msg); + } finally { + if (null != in) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + public void saveProperties() { + if (!persist) return; + + FileOutputStream out = null; + String path = null; + try { + path = getPropertiesFilePath(); + out = new FileOutputStream(path); + properties.store(out, "AJDE Settings"); + } catch (IOException ioe) { + Message msg = new Message("Error writing properties to " + path,IMessage.ERROR,ioe,null); + Ajde.getDefault().getMessageHandler().handleMessage(msg); + } finally { + if (null != out) { + try { + out.close(); + } catch (IOException e) { + // ignore + } + } + } } - public void saveProperties() { - if (!persist) return; - - FileOutputStream out = null; - String path = null; - try { - path = getPropertiesFilePath(); - out = new FileOutputStream(path); - properties.store(out, "AJDE Settings"); - } catch (IOException ioe) { - Message msg = new Message("Error writing properties to " + path,IMessage.ERROR,ioe,null); - Ajde.getDefault().getMessageHandler().handleMessage(msg); - } finally { - if (null != out) { - try { - out.close(); - } catch (IOException e) { - // ignore - } - } - } - } } diff --git a/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaComplianceOptionsPanel.java b/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaComplianceOptionsPanel.java index 1d8dba958..667e673ae 100644 --- a/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaComplianceOptionsPanel.java +++ b/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaComplianceOptionsPanel.java @@ -1,11 +1,11 @@ /******************************************************************** - * Copyright (c) 2007 Contributors. 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://eclipse.org/legal/epl-v10.html - * - * Contributors: IBM Corporation - initial API and implementation + * Copyright (c) 2007 Contributors. 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://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation * Helen Hawkins - initial version (bug 148190) *******************************************************************/ package org.aspectj.ajde.ui.javaoptions; @@ -14,9 +14,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.io.IOException; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import javax.swing.BorderFactory; @@ -37,9 +35,9 @@ import org.aspectj.ajde.ui.swing.OptionsPanel; public class JavaComplianceOptionsPanel extends OptionsPanel { private final String[] complianceLevels = new String[] {JavaOptions.VERSION_13, JavaOptions.VERSION_14, JavaOptions.VERSION_15, JavaOptions.VERSION_16}; - + private static final long serialVersionUID = 4491319302490183151L; - + private JPanel parentPanel; private Border complianceEtchedBorder; @@ -47,11 +45,11 @@ public class JavaComplianceOptionsPanel extends OptionsPanel { private Border complianceCompoundBorder; private JPanel compliancePanel; private Box complianceBox = Box.createVerticalBox(); - + private JavaBuildOptions javaBuildOptions; - private Map/*String --> JComboBox*/ complianceComboBoxes = new HashMap(); - + private Map<String,JComboBox<String>> complianceComboBoxes = new HashMap<>(); + public JavaComplianceOptionsPanel(JavaBuildOptions javaBuildOptions) { this.javaBuildOptions = javaBuildOptions; try { @@ -62,20 +60,21 @@ public class JavaComplianceOptionsPanel extends OptionsPanel { } } + @Override public void loadOptions() throws IOException { createComplianceContents(); } - - public void saveOptions() throws IOException { - Set s = complianceComboBoxes.entrySet(); - for (Iterator iterator = s.iterator(); iterator.hasNext();) { - Map.Entry entry = (Entry) iterator.next(); - String javaOption = (String) entry.getKey(); - JComboBox combo = (JComboBox)entry.getValue(); + + @Override + public void saveOptions() throws IOException { + Set<Map.Entry<String,JComboBox<String>>> s = complianceComboBoxes.entrySet(); + for (Map.Entry<String,JComboBox<String>> entry : s) { + String javaOption = entry.getKey(); + JComboBox<String> combo = entry.getValue(); String value = (String) combo.getSelectedItem(); javaBuildOptions.setOption(javaOption, value); } - } + } private void jbInit() throws Exception { this.setLayout(new BorderLayout()); @@ -95,32 +94,32 @@ public class JavaComplianceOptionsPanel extends OptionsPanel { private void createComplianceEntry(String labelText, String javaOptionToSet) { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - + JLabel label = new JLabel(); label.setFont(new java.awt.Font("Dialog", 0, 11)); label.setText(labelText); panel.add(label,BorderLayout.WEST); - - JComboBox levels = new JComboBox(complianceLevels); - String value = (String) javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); + + JComboBox<String> levels = new JComboBox<>(complianceLevels); + String value = javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); if (value == null) { // default to 1.5 levels.setSelectedIndex(2); } else if (value.equals(JavaOptions.VERSION_13)) { levels.setSelectedIndex(0); } else if (value.equals(JavaOptions.VERSION_14)){ - levels.setSelectedIndex(1); + levels.setSelectedIndex(1); } else if (value.equals(JavaOptions.VERSION_15)){ - levels.setSelectedIndex(2); + levels.setSelectedIndex(2); } else if (value.equals(JavaOptions.VERSION_16)){ - levels.setSelectedIndex(3); - } + levels.setSelectedIndex(3); + } panel.add(levels,BorderLayout.EAST); complianceBox.add(panel,null); complianceComboBoxes.put(javaOptionToSet,levels); } - + private void createBorders() { complianceEtchedBorder = BorderFactory.createEtchedBorder(Color.white, new Color(156, 156, 158)); complianceTitleBorder = new TitledBorder(complianceEtchedBorder, "Compliance Options"); @@ -128,11 +127,11 @@ public class JavaComplianceOptionsPanel extends OptionsPanel { BorderFactory.createEmptyBorder(5, 5, 5, 5)); complianceTitleBorder.setTitleFont(new java.awt.Font("Dialog", 0, 11)); } - + private void addBordersToPanel() { parentPanel = new JPanel(); parentPanel.setLayout(new BorderLayout()); - + compliancePanel = new JPanel(); compliancePanel.setBorder(complianceCompoundBorder); diff --git a/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaDebugOptionsPanel.java b/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaDebugOptionsPanel.java index 9678e3a0d..86f7a5025 100644 --- a/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaDebugOptionsPanel.java +++ b/ajde/src/main/java/org/aspectj/ajde/ui/javaoptions/JavaDebugOptionsPanel.java @@ -1,11 +1,11 @@ /******************************************************************** - * Copyright (c) 2007 Contributors. 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://eclipse.org/legal/epl-v10.html - * - * Contributors: IBM Corporation - initial API and implementation + * Copyright (c) 2007 Contributors. 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://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation * Helen Hawkins - initial version (bug 148190) *******************************************************************/ package org.aspectj.ajde.ui.javaoptions; @@ -14,9 +14,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.io.IOException; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import javax.swing.BorderFactory; @@ -38,9 +36,9 @@ public class JavaDebugOptionsPanel extends OptionsPanel { private final String[] debugOptions = new String[] {JavaOptions.GENERATE,JavaOptions.DO_NOT_GENERATE}; private final String[] preserveOptions = new String[] {JavaOptions.PRESERVE,JavaOptions.OPTIMIZE}; - + private static final long serialVersionUID = 4491319302490183151L; - + private JPanel parentPanel; private Border debugEtchedBorder; @@ -48,11 +46,11 @@ public class JavaDebugOptionsPanel extends OptionsPanel { private Border debugCompoundBorder; private JPanel debugPanel; private Box debugBox = Box.createVerticalBox(); - + private JavaBuildOptions javaBuildOptions; - private Map/*String --> JComboBox*/ debugComboBoxes = new HashMap(); - + private Map<String,JComboBox<String>> debugComboBoxes = new HashMap(); + public JavaDebugOptionsPanel(JavaBuildOptions javaBuildOptions) { this.javaBuildOptions = javaBuildOptions; try { @@ -63,20 +61,21 @@ public class JavaDebugOptionsPanel extends OptionsPanel { } } + @Override public void loadOptions() throws IOException { createDebugContents(); } - - public void saveOptions() throws IOException { - Set s = debugComboBoxes.entrySet(); - for (Iterator iterator = s.iterator(); iterator.hasNext();) { - Map.Entry entry = (Entry) iterator.next(); - String javaOption = (String) entry.getKey(); - JComboBox combo = (JComboBox)entry.getValue(); + + @Override + public void saveOptions() throws IOException { + Set<Map.Entry<String,JComboBox<String>>> s = debugComboBoxes.entrySet(); + for (Map.Entry<String,JComboBox<String>> entry : s) { + String javaOption = entry.getKey(); + JComboBox<String> combo = entry.getValue(); String value = (String) combo.getSelectedItem(); javaBuildOptions.setOption(javaOption, value); } - } + } private void jbInit() throws Exception { this.setLayout(new BorderLayout()); @@ -88,7 +87,7 @@ public class JavaDebugOptionsPanel extends OptionsPanel { private void createDebugContents() { createDebugEntry("Add line number attributes to generated class files",JavaOptions.DEBUG_LINES); createDebugEntry("Add source file name to generated class file",JavaOptions.DEBUG_SOURCE); - createDebugEntry("Add variable attributes to generated class files",JavaOptions.DEBUG_VARS); + createDebugEntry("Add variable attributes to generated class files",JavaOptions.DEBUG_VARS); createDebugEntry("Preserve unused (never read) local variables",JavaOptions.PRESERVE_ALL_LOCALS); debugPanel.add(debugBox); } @@ -96,48 +95,48 @@ public class JavaDebugOptionsPanel extends OptionsPanel { private void createDebugEntry(String labelText, String javaOptionToSet) { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - + JLabel label = new JLabel(); label.setFont(new java.awt.Font("Dialog", 0, 11)); label.setText(labelText); panel.add(label,BorderLayout.WEST); - - JComboBox debug = null; + + JComboBox<String> debug = null; if (javaOptionToSet.equals(JavaOptions.PRESERVE_ALL_LOCALS)) { - debug = new JComboBox(preserveOptions); - String value = (String) javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); + debug = new JComboBox<String>(preserveOptions); + String value = javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); if (value.equals(JavaOptions.PRESERVE)) { debug.setSelectedIndex(0); } else { - debug.setSelectedIndex(1); - } + debug.setSelectedIndex(1); + } } else { - debug = new JComboBox(debugOptions); - String value = (String) javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); + debug = new JComboBox<String>(debugOptions); + String value = javaBuildOptions.getJavaBuildOptionsMap().get(javaOptionToSet); if (value.equals(JavaOptions.GENERATE)) { debug.setSelectedIndex(0); } else { - debug.setSelectedIndex(1); - } - } + debug.setSelectedIndex(1); + } + } panel.add(debug,BorderLayout.EAST); debugBox.add(panel,null); - debugComboBoxes.put(javaOptionToSet,debug); + debugComboBoxes.put(javaOptionToSet,debug); } - - private void createBorders() { + + private void createBorders() { debugEtchedBorder = BorderFactory.createEtchedBorder(Color.white, new Color(156, 156, 158)); debugTitleBorder = new TitledBorder(debugEtchedBorder, "Debug Options"); debugCompoundBorder = BorderFactory.createCompoundBorder(debugTitleBorder, BorderFactory.createEmptyBorder(5, 5, 5, 5)); debugTitleBorder.setTitleFont(new java.awt.Font("Dialog", 0, 11)); } - + private void addBordersToPanel() { parentPanel = new JPanel(); parentPanel.setLayout(new BorderLayout()); - + debugPanel = new JPanel(); debugPanel.setBorder(debugCompoundBorder); diff --git a/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java b/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java index 05efb60e6..fea887cb6 100644 --- a/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java +++ b/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java @@ -1,12 +1,12 @@ /* ******************************************************************* * Copyright (c) 2003 Contributors - * 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: + * 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: * Wes Isberg initial implementation * ******************************************************************/ @@ -18,17 +18,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestResult; -import junit.framework.TestSuite; - import org.aspectj.ajdt.internal.core.builder.AjState; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHolder; import org.aspectj.bridge.MessageHandler; import org.aspectj.bridge.MessageUtil; import org.aspectj.testing.harness.bridge.AjcTest; +import org.aspectj.testing.harness.bridge.AjcTest.Spec; import org.aspectj.testing.harness.bridge.RunSpecIterator; import org.aspectj.testing.harness.bridge.Sandbox; import org.aspectj.testing.harness.bridge.Validator; @@ -36,6 +32,11 @@ import org.aspectj.testing.run.IRunIterator; import org.aspectj.testing.run.RunStatus; import org.aspectj.testing.run.Runner; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestResult; +import junit.framework.TestSuite; + /* * Adapt Harness tests to JUnit driver. This renders suite files as TestSuite * and AjcTest as TestCase. When run, aborts are reported as error and fails as @@ -47,336 +48,344 @@ import org.aspectj.testing.run.Runner; * the test. */ public class AjctestsAdapter extends TestSuite { - public static final String VERBOSE_NAME = AjctestsAdapter.class.getName() - + ".VERBOSE"; - - private static final boolean VERBOSE = HarnessJUnitUtil - .readBooleanSystemProperty(VERBOSE_NAME); - - /** - * Factory to make and populate suite without options. - * - * @param suitePath - * the String path to a harness suite file - * @return AjctestJUnitSuite populated with tests - */ - public static AjctestsAdapter make(String suitePath) { - return make(suitePath, null); - } - - /** - * Factory to make and populate suite - * - * @param suitePath - * the String path to a harness suite file - * @param options - * the String[] options to use when creating tests - * @return AjctestJUnitSuite populated with tests - */ - public static AjctestsAdapter make(String suitePath, String[] options) { - AjctestsAdapter result = new AjctestsAdapter(suitePath, options); - AjcTest.Spec[] tests = AjcTest.Suite.getTests(result.getSpec()); - if (VERBOSE) { - log("loading " + tests.length + " tests in " + suitePath); - } - for (int i = 0; i < tests.length; i++) { - AjcTest.Spec ajcTest = tests[i]; - result.addTest(new AjcTestSpecAsTest(ajcTest, result)); - } - return result; - } - - private static void log(String message) { - System.err.println(message); - System.err.flush(); - } - - private final String suitePath; - - private final String[] options; - - private AjcTest.Suite.Spec spec; - - private Runner runner; - - private Validator validator; - - private IMessageHolder holder; - - private Sandbox sandbox; - - private File suiteDir; - - private String name; - - private AjctestsAdapter(String suitePath, String[] options) { - this.suitePath = suitePath; - String[] opts = new String[0]; - if (!HarnessJUnitUtil.isEmpty(options)) { - opts = new String[options.length]; - System.arraycopy(options, 0, opts, 0, opts.length); - } - this.options = opts; - } - - public void addTest(Test test) { - if (!(test instanceof AjcTestSpecAsTest)) { - String m = "expecting AjcTestSpecAsTest, got " - + (null == test ? "null test" : test.getClass().getName() - + ": " + test); - throw new IllegalArgumentException(m); - } - super.addTest(test); - } - - public void addTestSuite(Class testClass) { - throw new Error("unimplemented"); - } - - public String getName() { - if (null == name) { - name = HarnessJUnitUtil.cleanTestName(suitePath - + Arrays.asList(options)); - } - return name; - } - - /** - * Callback from test to run it using suite-wide holder, etc. The caller is - * responsible for calling result.startTest(test) and result.endTest(test); - * - * @param test - * the AjcTestSpecAsTest to run - * @param result - * the TestResult for any result messages (may be null) - */ - protected void runTest(AjcTestSpecAsTest test, TestResult result) { - final Runner runner = getRunner(); - final Sandbox sandbox = getSandbox(); - final Validator validator = getValidator(); - int numIncomplete = 0; - final RunStatus status = new RunStatus(new MessageHandler(), runner); - status.setIdentifier(test.toString()); - try { - IMessageHolder holder = getHolder(); - holder.clearMessages(); - IRunIterator steps = test.spec.makeRunIterator(sandbox, validator); - if (0 < holder.numMessages(IMessage.ERROR, true)) { - MessageUtil.handleAll(status, holder, IMessage.INFO, true, - false); - } else { - runner.runIterator(steps, status, null); - } - if (steps instanceof RunSpecIterator) { - numIncomplete = ((RunSpecIterator) steps).getNumIncomplete(); - } - } finally { - try { - // reportResult handles null TestResult - HarnessJUnitUtil - .reportResult(null, status, test, numIncomplete); - } finally { - validator.deleteTempFiles(true); - } - } - } - - private File getSuiteDir() { - if (null == suiteDir) { - File file = new File(suitePath); - file = file.getParentFile(); - if (null == file) { - file = new File("."); - } - suiteDir = file; - } - return suiteDir; - } - - private Validator getValidator() { - if (null == validator) { - validator = new Validator(getHolder()); - // XXX lock if keepTemp? - } - return validator; - } - - private Runner getRunner() { - if (null == runner) { - runner = new Runner(); - } - return runner; - } - - private IMessageHolder getHolder() { - if (null == holder) { - holder = new MessageHandler(); - } - return holder; - } - - private AjcTest.Suite.Spec getSpec() { - if (null == spec) { - IMessageHolder holder = getHolder(); - spec = HarnessJUnitUtil.getSuiteSpec(suitePath, options, - getHolder()); - if (VERBOSE && holder.hasAnyMessage(null, true)) { - MessageUtil.print(System.err, holder, "skip ", - MessageUtil.MESSAGE_MOST); - } - holder.clearMessages(); - } - return spec; - } - - private Sandbox getSandbox() { - if (null == sandbox) { - sandbox = new Sandbox(spec.getSuiteDirFile(), getValidator()); - } - return sandbox; - } - - /** - * Wrap AjcTest.Spec for lookup by description - * - * @author wes - */ - public static class SpecTests { - private static final HashMap TESTS = new HashMap(); - -// private static void putSpecTestsFor(String id, SpecTests tests) { -// TESTS.put(id, tests); -// } - - private static SpecTests getSpecTestsFor(String id) { - SpecTests result = (SpecTests) TESTS.get(id); - if (null == result) { - throw new Error("no tests found for " + id); - } - return result; - } - - // ------------------------------------ - final AjctestsAdapter mAjctestsAdapter; - - private final Map mDescriptionToAjcTestSpec; - - // ------------------------------------ - private SpecTests(AjctestsAdapter ajctestsAdapter, AjcTest.Spec[] tests) { - mAjctestsAdapter = ajctestsAdapter; - Map map = new HashMap(); - for (int i = 0; i < tests.length; i++) { - map.put(tests[i].getDescription(), tests[i]); - } - - mDescriptionToAjcTestSpec = Collections.unmodifiableMap(map); - } - - /** - * @param description - * the String description of the test - * @throws IllegalArgumentException - * if testName is not found - */ - protected void runTest(String description) { - AjcTest.Spec spec = getSpec(description); - AjctestsAdapter.AjcTestSpecAsTest ajcTestAsSpec = new AjctestsAdapter.AjcTestSpecAsTest( - spec, mAjctestsAdapter); - // runTest handles null TestResult - mAjctestsAdapter.runTest(ajcTestAsSpec, null); - } - - /** - * @param description - * the String description of the test - * @throws IllegalArgumentException - * if testName is not found - */ - private AjcTest.Spec getSpec(String description) { - AjcTest.Spec spec = (AjcTest.Spec) mDescriptionToAjcTestSpec - .get(description); - if (null == spec) { - throw new IllegalArgumentException("no test for " + description); - } - return spec; - } - - /** - * makeUsingTestClass(..) extends this to create TestCase with - * test_{name} for each test case. - */ - public static class TestClass extends TestCase { - public TestClass() { - } - private SpecTests mTests; - - /** - * Called by code generated in makeUsingTestClass(..) - * - * @param description - * the String identifier of the test stored in SpecTests - * mTests. - * @throws Error - * on first and later uses if getTestsFor() returns - * null. - */ - public final void runTest(String description) { - if (null == mTests) { - String classname = getClass().getName(); - mTests = getSpecTestsFor(classname); - } - mTests.runTest(description); - } - } - } - - /** Wrap AjcTest.Spec as a TestCase. Run by delegation to suite */ - private static class AjcTestSpecAsTest extends TestCase implements - HarnessJUnitUtil.IHasAjcSpec { - // this could implement Test, but Ant batchtest fails to pull name - final String name; - - final AjcTest.Spec spec; - - AjctestsAdapter suite; - - AjcTestSpecAsTest(AjcTest.Spec spec, AjctestsAdapter suite) { - super(HarnessJUnitUtil.cleanTestName(spec.getDescription())); - this.name = HarnessJUnitUtil.cleanTestName(spec.getDescription()); - this.suite = suite; - this.spec = spec; - spec.setSuiteDir(suite.getSuiteDir()); - } - - public int countTestCases() { - return 1; - } - - public AjcTest.Spec getAjcTestSpec() { - return spec; - } - - public void run(TestResult result) { - if (null == suite) { - throw new Error("need to re-init"); - } - try { - AjState.FORCE_INCREMENTAL_DURING_TESTING = true; - result.startTest(this); - suite.runTest(this, result); - } finally { - result.endTest(this); - suite = null; - AjState.FORCE_INCREMENTAL_DURING_TESTING = false; - } - } - - public String getName() { - return name; - } - - public String toString() { - return name; - } - } + public static final String VERBOSE_NAME = AjctestsAdapter.class.getName() + + ".VERBOSE"; + + private static final boolean VERBOSE = HarnessJUnitUtil + .readBooleanSystemProperty(VERBOSE_NAME); + + /** + * Factory to make and populate suite without options. + * + * @param suitePath + * the String path to a harness suite file + * @return AjctestJUnitSuite populated with tests + */ + public static AjctestsAdapter make(String suitePath) { + return make(suitePath, null); + } + + /** + * Factory to make and populate suite + * + * @param suitePath + * the String path to a harness suite file + * @param options + * the String[] options to use when creating tests + * @return AjctestJUnitSuite populated with tests + */ + public static AjctestsAdapter make(String suitePath, String[] options) { + AjctestsAdapter result = new AjctestsAdapter(suitePath, options); + AjcTest.Spec[] tests = AjcTest.Suite.getTests(result.getSpec()); + if (VERBOSE) { + log("loading " + tests.length + " tests in " + suitePath); + } + for (Spec ajcTest : tests) { + result.addTest(new AjcTestSpecAsTest(ajcTest, result)); + } + return result; + } + + private static void log(String message) { + System.err.println(message); + System.err.flush(); + } + + private final String suitePath; + + private final String[] options; + + private AjcTest.Suite.Spec spec; + + private Runner runner; + + private Validator validator; + + private IMessageHolder holder; + + private Sandbox sandbox; + + private File suiteDir; + + private String name; + + private AjctestsAdapter(String suitePath, String[] options) { + this.suitePath = suitePath; + String[] opts = new String[0]; + if (!HarnessJUnitUtil.isEmpty(options)) { + opts = new String[options.length]; + System.arraycopy(options, 0, opts, 0, opts.length); + } + this.options = opts; + } + + @Override + public void addTest(Test test) { + if (!(test instanceof AjcTestSpecAsTest)) { + String m = "expecting AjcTestSpecAsTest, got " + + (null == test ? "null test" : test.getClass().getName() + + ": " + test); + throw new IllegalArgumentException(m); + } + super.addTest(test); + } + + @SuppressWarnings("rawtypes") + @Override + public void addTestSuite(Class testClass) { + throw new Error("unimplemented"); + } + + @Override + public String getName() { + if (null == name) { + name = HarnessJUnitUtil.cleanTestName(suitePath + + Arrays.asList(options)); + } + return name; + } + + /** + * Callback from test to run it using suite-wide holder, etc. The caller is + * responsible for calling result.startTest(test) and result.endTest(test); + * + * @param test + * the AjcTestSpecAsTest to run + * @param result + * the TestResult for any result messages (may be null) + */ + protected void runTest(AjcTestSpecAsTest test, TestResult result) { + final Runner runner = getRunner(); + final Sandbox sandbox = getSandbox(); + final Validator validator = getValidator(); + int numIncomplete = 0; + final RunStatus status = new RunStatus(new MessageHandler(), runner); + status.setIdentifier(test.toString()); + try { + IMessageHolder holder = getHolder(); + holder.clearMessages(); + IRunIterator steps = test.spec.makeRunIterator(sandbox, validator); + if (0 < holder.numMessages(IMessage.ERROR, true)) { + MessageUtil.handleAll(status, holder, IMessage.INFO, true, + false); + } else { + runner.runIterator(steps, status, null); + } + if (steps instanceof RunSpecIterator) { + numIncomplete = ((RunSpecIterator) steps).getNumIncomplete(); + } + } finally { + try { + // reportResult handles null TestResult + HarnessJUnitUtil + .reportResult(null, status, test, numIncomplete); + } finally { + validator.deleteTempFiles(true); + } + } + } + + private File getSuiteDir() { + if (null == suiteDir) { + File file = new File(suitePath); + file = file.getParentFile(); + if (null == file) { + file = new File("."); + } + suiteDir = file; + } + return suiteDir; + } + + private Validator getValidator() { + if (null == validator) { + validator = new Validator(getHolder()); + // XXX lock if keepTemp? + } + return validator; + } + + private Runner getRunner() { + if (null == runner) { + runner = new Runner(); + } + return runner; + } + + private IMessageHolder getHolder() { + if (null == holder) { + holder = new MessageHandler(); + } + return holder; + } + + private AjcTest.Suite.Spec getSpec() { + if (null == spec) { + IMessageHolder holder = getHolder(); + spec = HarnessJUnitUtil.getSuiteSpec(suitePath, options, + getHolder()); + if (VERBOSE && holder.hasAnyMessage(null, true)) { + MessageUtil.print(System.err, holder, "skip ", + MessageUtil.MESSAGE_MOST); + } + holder.clearMessages(); + } + return spec; + } + + private Sandbox getSandbox() { + if (null == sandbox) { + sandbox = new Sandbox(spec.getSuiteDirFile(), getValidator()); + } + return sandbox; + } + + /** + * Wrap AjcTest.Spec for lookup by description + * + * @author wes + */ + public static class SpecTests { + private static final HashMap<String,SpecTests> TESTS = new HashMap<>(); + + // private static void putSpecTestsFor(String id, SpecTests tests) { + // TESTS.put(id, tests); + // } + + private static SpecTests getSpecTestsFor(String id) { + SpecTests result = TESTS.get(id); + if (null == result) { + throw new Error("no tests found for " + id); + } + return result; + } + + // ------------------------------------ + final AjctestsAdapter mAjctestsAdapter; + + private final Map<String,AjcTest.Spec> mDescriptionToAjcTestSpec; + + // ------------------------------------ + private SpecTests(AjctestsAdapter ajctestsAdapter, AjcTest.Spec[] tests) { + mAjctestsAdapter = ajctestsAdapter; + Map<String,AjcTest.Spec> map = new HashMap<>(); + for (Spec test : tests) { + map.put(test.getDescription(), test); + } + + mDescriptionToAjcTestSpec = Collections.unmodifiableMap(map); + } + + /** + * @param description + * the String description of the test + * @throws IllegalArgumentException + * if testName is not found + */ + protected void runTest(String description) { + AjcTest.Spec spec = getSpec(description); + AjctestsAdapter.AjcTestSpecAsTest ajcTestAsSpec = new AjctestsAdapter.AjcTestSpecAsTest( + spec, mAjctestsAdapter); + // runTest handles null TestResult + mAjctestsAdapter.runTest(ajcTestAsSpec, null); + } + + /** + * @param description + * the String description of the test + * @throws IllegalArgumentException + * if testName is not found + */ + private AjcTest.Spec getSpec(String description) { + AjcTest.Spec spec = mDescriptionToAjcTestSpec + .get(description); + if (null == spec) { + throw new IllegalArgumentException("no test for " + description); + } + return spec; + } + + /** + * makeUsingTestClass(..) extends this to create TestCase with + * test_{name} for each test case. + */ + public static class TestClass extends TestCase { + public TestClass() { + } + private SpecTests mTests; + + /** + * Called by code generated in makeUsingTestClass(..) + * + * @param description + * the String identifier of the test stored in SpecTests + * mTests. + * @throws Error + * on first and later uses if getTestsFor() returns + * null. + */ + public final void runTest(String description) { + if (null == mTests) { + String classname = getClass().getName(); + mTests = getSpecTestsFor(classname); + } + mTests.runTest(description); + } + } + } + + /** Wrap AjcTest.Spec as a TestCase. Run by delegation to suite */ + private static class AjcTestSpecAsTest extends TestCase implements + HarnessJUnitUtil.IHasAjcSpec { + // this could implement Test, but Ant batchtest fails to pull name + final String name; + + final AjcTest.Spec spec; + + AjctestsAdapter suite; + + AjcTestSpecAsTest(AjcTest.Spec spec, AjctestsAdapter suite) { + super(HarnessJUnitUtil.cleanTestName(spec.getDescription())); + this.name = HarnessJUnitUtil.cleanTestName(spec.getDescription()); + this.suite = suite; + this.spec = spec; + spec.setSuiteDir(suite.getSuiteDir()); + } + + @Override + public int countTestCases() { + return 1; + } + + @Override + public AjcTest.Spec getAjcTestSpec() { + return spec; + } + + @Override + public void run(TestResult result) { + if (null == suite) { + throw new Error("need to re-init"); + } + try { + AjState.FORCE_INCREMENTAL_DURING_TESTING = true; + result.startTest(this); + suite.runTest(this, result); + } finally { + result.endTest(this); + suite = null; + AjState.FORCE_INCREMENTAL_DURING_TESTING = false; + } + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + } }
\ No newline at end of file diff --git a/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java b/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java index 767444ce3..f1c8b3635 100644 --- a/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java +++ b/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java @@ -32,6 +32,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -44,6 +45,7 @@ import org.aspectj.testing.harness.bridge.AbstractRunSpec; import org.aspectj.testing.harness.bridge.AjcTest; import org.aspectj.testing.harness.bridge.CompilerRun; import org.aspectj.testing.harness.bridge.FlatSuiteReader; +import org.aspectj.testing.harness.bridge.IRunSpec; import org.aspectj.testing.harness.bridge.IncCompilerRun; import org.aspectj.testing.harness.bridge.JavaRun; import org.aspectj.testing.harness.bridge.RunSpecIterator; @@ -82,236 +84,236 @@ import org.aspectj.util.LangUtil; * categories. */ public class Harness { - /** - * Spaces up to the width that an option should take in the syntax, - * including the two-space leader - */ - protected static final String SYNTAX_PAD = " "; - protected static final String OPTION_DELIM = ";"; - private static final String JAVA_VERSION; - private static final String ASPECTJ_VERSION; - static { - String version = "UNKNOWN"; - try { version = System.getProperty("java.version", "UNKNOWN"); } - catch (Throwable t) {} - JAVA_VERSION = version; - - version = "UNKNOWN"; - try { - Class c = Class.forName("org.aspectj.bridge.Version"); - version = (String) c.getField("text").get(null); - } catch (Throwable t) { - // ignore - } - ASPECTJ_VERSION = version; - } - - /** factory for the subclass currently anointed as default */ - public static Harness makeHarness() { - return new FeatureHarness(); - } - - /** @param args String[] like runMain(String[]) args */ - public static void main(String[] args) throws Exception { - if (LangUtil.isEmpty(args)) { - File argFile = new File("HarnessArgs.txt"); - if (argFile.canRead()) { - args = readArgs(argFile); - } else { - args = new String[] { "-help" }; - } - } - makeHarness().runMain(args, null); - } - - /** - * Get known option aliases. - * Subclasses may add new aliases, where the key is the alias option, - * and the value is a comma-delimited String of target options. - * @return Properties with feature aliases or null - */ - protected static Properties getOptionAliases() { - if (null == optionAliases) { - optionAliases = new Properties(); - // XXX load from **OptionAliases.properties - } - return optionAliases; - } - - /** - * Read argFile contents into String[], - * delimiting at any whitespace - */ - private static String[] readArgs(File argFile) { - ArrayList<String> args = new ArrayList<>(); -// int lineNum = 0; - - try { - BufferedReader stream = - new BufferedReader(new FileReader(argFile)); - String line; - while (null != (line = stream.readLine())) { - StringTokenizer st = new StringTokenizer(line); - while (st.hasMoreTokens()) { - args.add(st.nextToken()); - } - } - } catch (IOException e) { - e.printStackTrace(System.err); - } - return args.toArray(new String[0]); - } - - /** aliases key="option" value="option{,option}" */ - private static Properties optionAliases; - - /** be extra noisy if true */ - private boolean verboseHarness; - - /** be extra quiet if true */ - private boolean quietHarness; - - /** just don't say anything! */ - protected boolean silentHarness; - - private HashMap<String,Feature> features; + /** + * Spaces up to the width that an option should take in the syntax, + * including the two-space leader + */ + protected static final String SYNTAX_PAD = " "; + protected static final String OPTION_DELIM = ";"; + private static final String JAVA_VERSION; + private static final String ASPECTJ_VERSION; + static { + String version = "UNKNOWN"; + try { version = System.getProperty("java.version", "UNKNOWN"); } + catch (Throwable t) {} + JAVA_VERSION = version; + + version = "UNKNOWN"; + try { + Class c = Class.forName("org.aspectj.bridge.Version"); + version = (String) c.getField("text").get(null); + } catch (Throwable t) { + // ignore + } + ASPECTJ_VERSION = version; + } + + /** factory for the subclass currently anointed as default */ + public static Harness makeHarness() { + return new FeatureHarness(); + } + + /** @param args String[] like runMain(String[]) args */ + public static void main(String[] args) throws Exception { + if (LangUtil.isEmpty(args)) { + File argFile = new File("HarnessArgs.txt"); + if (argFile.canRead()) { + args = readArgs(argFile); + } else { + args = new String[] { "-help" }; + } + } + makeHarness().runMain(args, null); + } + + /** + * Get known option aliases. + * Subclasses may add new aliases, where the key is the alias option, + * and the value is a comma-delimited String of target options. + * @return Properties with feature aliases or null + */ + protected static Properties getOptionAliases() { + if (null == optionAliases) { + optionAliases = new Properties(); + // XXX load from **OptionAliases.properties + } + return optionAliases; + } + + /** + * Read argFile contents into String[], + * delimiting at any whitespace + */ + private static String[] readArgs(File argFile) { + ArrayList<String> args = new ArrayList<>(); + // int lineNum = 0; + + try { + BufferedReader stream = + new BufferedReader(new FileReader(argFile)); + String line; + while (null != (line = stream.readLine())) { + StringTokenizer st = new StringTokenizer(line); + while (st.hasMoreTokens()) { + args.add(st.nextToken()); + } + } + } catch (IOException e) { + e.printStackTrace(System.err); + } + return args.toArray(new String[0]); + } + + /** aliases key="option" value="option{,option}" */ + private static Properties optionAliases; + + /** be extra noisy if true */ + private boolean verboseHarness; + + /** be extra quiet if true */ + private boolean quietHarness; + + /** just don't say anything! */ + protected boolean silentHarness; + + private HashMap<String,Feature> features; /** if true, do not delete temporary files. */ private boolean keepTemp; - /** if true, delete temporary files as each test completes. */ - private boolean killTemp; + /** if true, delete temporary files as each test completes. */ + private boolean killTemp; /** if true, then log results in report(..) when done */ private boolean logResults; - /** if true and there were failures, do System.exit({numFailures})*/ - private boolean exitOnFailure; - - protected Harness() { - features = new HashMap<>(); - } - - - /** - * Entry point for a test. - * This reads in the arguments, - * creates the test suite(s) from the input file(s), - * and for each suite does setup, run, report, and cleanup. - * When arguments are read, any option ending with "-" causes - * option variants, a set of args with and another without the - * option. See {@link LangUtil.optionVariants(String[])} for - * more details. - * @param args the String[] for the test suite - use -help to get options, - * and use "-" suffixes for variants. - * @param resultList List for IRunStatus results - ignored if null - */ - public void runMain(String[] args, List resultList) { - LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(args), "empty args"); - // read arguments - final ArrayList<String> globals = new ArrayList<>(); - final ArrayList<String> files = new ArrayList<>(); - final LinkedList<String> argList = new LinkedList<>(); - argList.addAll(Arrays.asList(args)); - for (int i = 0; i < argList.size(); i++) { - String arg = argList.get(i); - List<String> aliases = aliasOptions(arg); - if (!LangUtil.isEmpty(aliases)) { - argList.remove(i); - argList.addAll(i, aliases); - i--; - continue; - } - if ("-help".equals(arg)) { - logln("java " + Harness.class.getName() + " {option|suiteFile}.."); - printSyntax(getLogStream()); - return; - } else if (isSuiteFile(arg)) { - files.add(arg); - } else if (!acceptOption(arg)) { - globals.add(arg); - } // else our options absorbed - } - if (0 == files.size()) { - logln("## Error reading arguments: at least 1 suite file required"); - logln("java " + Harness.class.getName() + " {option|suiteFile}.."); - printSyntax(getLogStream()); - return; - } - String[] globalOptions = globals.toArray(new String[0]); - String[][] globalOptionVariants = optionVariants(globalOptions); - AbstractRunSpec.RT runtime = new AbstractRunSpec.RT(); - if (verboseHarness) { - runtime.setVerbose(true); - } - - // run suites read from each file - AjcTest.Suite.Spec spec; - for (Iterator iter = files.iterator(); iter.hasNext();) { - File suiteFile = new File((String) iter.next()); - if (!suiteFile.canRead()) { - logln("runMain(..) cannot read file: " + suiteFile); - continue; - } - if (null == (spec = readSuite(suiteFile))) { - logln("runMain(..) cannot read suite from file: " + suiteFile); - continue; - } - - MessageHandler holder = new MessageHandler(); - for (int i = 0; i < globalOptionVariants.length; i++) { - runtime.setOptions(globalOptionVariants[i]); - holder.init(); - boolean skip = !spec.adoptParentValues(runtime, holder); - // awful/brittle assumption about number of skips == number of skip messages - final List skipList = MessageUtil.getMessages(holder, IMessage.INFO, false, "skip"); - if ((verboseHarness || skip || (0 < skipList.size()))) { - final List curArgs = Arrays.asList(globalOptionVariants[i]); + /** if true and there were failures, do System.exit({numFailures})*/ + private boolean exitOnFailure; + + protected Harness() { + features = new HashMap<>(); + } + + + /** + * Entry point for a test. + * This reads in the arguments, + * creates the test suite(s) from the input file(s), + * and for each suite does setup, run, report, and cleanup. + * When arguments are read, any option ending with "-" causes + * option variants, a set of args with and another without the + * option. See {@link LangUtil.optionVariants(String[])} for + * more details. + * @param args the String[] for the test suite - use -help to get options, + * and use "-" suffixes for variants. + * @param resultList List for IRunStatus results - ignored if null + */ + public void runMain(String[] args, List resultList) { + LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(args), "empty args"); + // read arguments + final ArrayList<String> globals = new ArrayList<>(); + final ArrayList<String> files = new ArrayList<>(); + final LinkedList<String> argList = new LinkedList<>(); + argList.addAll(Arrays.asList(args)); + for (int i = 0; i < argList.size(); i++) { + String arg = argList.get(i); + List<String> aliases = aliasOptions(arg); + if (!LangUtil.isEmpty(aliases)) { + argList.remove(i); + argList.addAll(i, aliases); + i--; + continue; + } + if ("-help".equals(arg)) { + logln("java " + Harness.class.getName() + " {option|suiteFile}.."); + printSyntax(getLogStream()); + return; + } else if (isSuiteFile(arg)) { + files.add(arg); + } else if (!acceptOption(arg)) { + globals.add(arg); + } // else our options absorbed + } + if (0 == files.size()) { + logln("## Error reading arguments: at least 1 suite file required"); + logln("java " + Harness.class.getName() + " {option|suiteFile}.."); + printSyntax(getLogStream()); + return; + } + String[] globalOptions = globals.toArray(new String[0]); + String[][] globalOptionVariants = optionVariants(globalOptions); + AbstractRunSpec.RT runtime = new AbstractRunSpec.RT(); + if (verboseHarness) { + runtime.setVerbose(true); + } + + // run suites read from each file + AjcTest.Suite.Spec spec; + for (String string : files) { + File suiteFile = new File(string); + if (!suiteFile.canRead()) { + logln("runMain(..) cannot read file: " + suiteFile); + continue; + } + if (null == (spec = readSuite(suiteFile))) { + logln("runMain(..) cannot read suite from file: " + suiteFile); + continue; + } + + MessageHandler holder = new MessageHandler(); + for (String[] globalOptionVariant : globalOptionVariants) { + runtime.setOptions(globalOptionVariant); + holder.init(); + boolean skip = !spec.adoptParentValues(runtime, holder); + // awful/brittle assumption about number of skips == number of skip messages + final List<IMessage> skipList = MessageUtil.getMessages(holder, IMessage.INFO, false, "skip"); + if ((verboseHarness || skip || (0 < skipList.size()))) { + final List<String> curArgs = Arrays.asList(globalOptionVariant); logln("runMain(" + suiteFile + ", " + curArgs + ")"); - if (verboseHarness) { - String format = "yyyy.MM.dd G 'at' hh:mm:ss a zzz"; - SimpleDateFormat formatter = new SimpleDateFormat (format); - String date = formatter.format(new Date()); - logln("test date: " + date); - logln("harness features: " + listFeatureNames()); - logln("Java version: " + JAVA_VERSION); - logln("AspectJ version: " + ASPECTJ_VERSION); - } - if (!(quietHarness || silentHarness) && holder.hasAnyMessage(null, true)) { - MessageUtil.print(getLogStream(), holder, "skip - "); - MessageUtil.printMessageCounts(getLogStream(), holder, "skip - "); - } - } - if (!skip) { - doStartSuite(suiteFile); - long elapsed = 0; - RunResult result = null; - try { - final long startTime = System.currentTimeMillis(); - result = run(spec); - if (null != resultList) { - resultList.add(result); - } - elapsed = System.currentTimeMillis() - startTime; - report(result.status, skipList.size(), result.numIncomplete, elapsed); - } finally { - doEndSuite(suiteFile,elapsed); - } - if (exitOnFailure) { - int numFailures = RunUtils.numFailures(result.status, true); - if (0 < numFailures) { - System.exit(numFailures); - } - Object value = result.status.getResult(); - if ((value instanceof Boolean) - && !((Boolean) value).booleanValue()) { - System.exit(-1); - } - } - } - } - } - } + if (verboseHarness) { + String format = "yyyy.MM.dd G 'at' hh:mm:ss a zzz"; + SimpleDateFormat formatter = new SimpleDateFormat (format); + String date = formatter.format(new Date()); + logln("test date: " + date); + logln("harness features: " + listFeatureNames()); + logln("Java version: " + JAVA_VERSION); + logln("AspectJ version: " + ASPECTJ_VERSION); + } + if (!(quietHarness || silentHarness) && holder.hasAnyMessage(null, true)) { + MessageUtil.print(getLogStream(), holder, "skip - "); + MessageUtil.printMessageCounts(getLogStream(), holder, "skip - "); + } + } + if (!skip) { + doStartSuite(suiteFile); + long elapsed = 0; + RunResult result = null; + try { + final long startTime = System.currentTimeMillis(); + result = run(spec); + if (null != resultList) { + resultList.add(result); + } + elapsed = System.currentTimeMillis() - startTime; + report(result.status, skipList.size(), result.numIncomplete, elapsed); + } finally { + doEndSuite(suiteFile,elapsed); + } + if (exitOnFailure) { + int numFailures = RunUtils.numFailures(result.status, true); + if (0 < numFailures) { + System.exit(numFailures); + } + Object value = result.status.getResult(); + if ((value instanceof Boolean) + && !((Boolean) value).booleanValue()) { + System.exit(-1); + } + } + } + } + } + } /** @@ -328,72 +330,71 @@ public class Harness { } } } - /** - * Generate variants of String[] options by creating an extra set for - * each option that ends with "-". If none end with "-", then an - * array equal to <code>new String[][] { options }</code> is returned; - * if one ends with "-", then two sets are returned, - * three causes eight sets, etc. - * @return String[][] with each option set. - * @throws IllegalArgumentException if any option is null or empty. - */ - public static String[][] optionVariants(String[] options) { - if ((null == options) || (0 == options.length)) { - return new String[][] { new String[0]}; - } - // be nice, don't stomp input - String[] temp = new String[options.length]; - System.arraycopy(options, 0, temp, 0, temp.length); - options = temp; - boolean[] dup = new boolean[options.length]; - int numDups = 0; - - for (int i = 0; i < options.length; i++) { - String option = options[i]; - if (LangUtil.isEmpty(option)) { - throw new IllegalArgumentException("empty option at " + i); - } - if (option.endsWith("-")) { - options[i] = option.substring(0, option.length()-1); - dup[i] = true; - numDups++; - } - } - final String[] NONE = new String[0]; - final int variants = exp(2, numDups); - final String[][] result = new String[variants][]; - // variant is a bitmap wrt doing extra value when dup[k]=true - for (int variant = 0; variant < variants; variant++) { - ArrayList<String> next = new ArrayList<>(); - int nextOption = 0; - for (int k = 0; k < options.length; k++) { - if (!dup[k] || (0 != (variant & (1 << (nextOption++))))) { - next.add(options[k]); - } - } - result[variant] = next.toArray(NONE); - } - return result; - } - - private static int exp(int base, int power) { // not in Math? - if (0 > power) { - throw new IllegalArgumentException("negative power: " + power); - } - int result = 1; - while (0 < power--) { - result *= base; - } - return result; - } + /** + * Generate variants of String[] options by creating an extra set for + * each option that ends with "-". If none end with "-", then an + * array equal to <code>new String[][] { options }</code> is returned; + * if one ends with "-", then two sets are returned, + * three causes eight sets, etc. + * @return String[][] with each option set. + * @throws IllegalArgumentException if any option is null or empty. + */ + public static String[][] optionVariants(String[] options) { + if ((null == options) || (0 == options.length)) { + return new String[][] { new String[0]}; + } + // be nice, don't stomp input + String[] temp = new String[options.length]; + System.arraycopy(options, 0, temp, 0, temp.length); + options = temp; + boolean[] dup = new boolean[options.length]; + int numDups = 0; + + for (int i = 0; i < options.length; i++) { + String option = options[i]; + if (LangUtil.isEmpty(option)) { + throw new IllegalArgumentException("empty option at " + i); + } + if (option.endsWith("-")) { + options[i] = option.substring(0, option.length()-1); + dup[i] = true; + numDups++; + } + } + final String[] NONE = new String[0]; + final int variants = exp(2, numDups); + final String[][] result = new String[variants][]; + // variant is a bitmap wrt doing extra value when dup[k]=true + for (int variant = 0; variant < variants; variant++) { + ArrayList<String> next = new ArrayList<>(); + int nextOption = 0; + for (int k = 0; k < options.length; k++) { + if (!dup[k] || (0 != (variant & (1 << (nextOption++))))) { + next.add(options[k]); + } + } + result[variant] = next.toArray(NONE); + } + return result; + } + + private static int exp(int base, int power) { // not in Math? + if (0 > power) { + throw new IllegalArgumentException("negative power: " + power); + } + int result = 1; + while (0 < power--) { + result *= base; + } + return result; + } /** * @param suiteFile */ private void doStartSuite(File suiteFile) { - Collection c = features.values(); - for (Iterator iter = c.iterator(); iter.hasNext();) { - Feature element = (Feature) iter.next(); + Collection<Feature> c = features.values(); + for (Feature element : c) { if (element.listener instanceof TestCompleteListener) { ((TestCompleteListener)element.listener).doStartSuite(suiteFile); } @@ -401,271 +402,271 @@ public class Harness { } /** Run the test suite specified by the spec */ - protected RunResult run(AjcTest.Suite.Spec spec) { - LangUtil.throwIaxIfNull(spec, "spec"); - /* - * For each run, initialize the runner and validator, - * create a new set of IRun{Iterator} tests, - * and run them. - * Delete all temp files when done. - */ - Runner runner = new Runner(); - if (0 != features.size()) { - for (Iterator<Map.Entry<String,Feature>> iter = features.entrySet().iterator(); iter.hasNext();) { - Feature feature = iter.next().getValue(); - runner.registerListener(feature.clazz, feature.listener); - } - } - IMessageHolder holder = new MessageHandler(); - int numIncomplete = 0; - RunStatus status = new RunStatus(holder, runner); - status.setIdentifier(spec); - // validator is used for all setup in entire tree... - Validator validator = new Validator(status); - if (!killTemp) { - validator.lock(this); - } - Sandbox sandbox = null; - try { - sandbox = new Sandbox(spec.getSuiteDirFile(), validator); - IRunIterator tests = spec.makeRunIterator(sandbox, validator); - runner.runIterator(tests, status, null); - if (tests instanceof RunSpecIterator) { - numIncomplete = ((RunSpecIterator) tests).getNumIncomplete(); - } - } finally { - if (!keepTemp) { - if (!killTemp) { - validator.unlock(this); - } - validator.deleteTempFiles(verboseHarness); - } - } - return new RunResult(status, numIncomplete); - } - - /** - * Report the results of a test run after it is completed. - * Clients should be able to identify the number of: - * <ul> - * <li>tests run and passed</li> - * <li>tests failed, i.e., run and not passed (fail, error, etc.)</li> - * <li>tests incomplete, i.e., test definition read but test run setup failed</li> - * <li>tests skipped, i.e., test definition read and found incompatible with - * the current configuration.</li> - * <ul> - * - * @param status returned from the run - * @param numSkipped int tests that were skipped because of - * configuration incompatibilities - * @param numIncomplete int tests that failed during setup, - * usually indicating a test definition or configuration error. - * @param msElapsed elapsed time in milliseconds - * */ - protected void report(IRunStatus status, int numSkipped, int numIncomplete, - long msElapsed ) { - if (logResults) { - RunUtils.AJCSUITE_PRINTER.printRunStatus(getLogStream(), status); - } else if (!(quietHarness || silentHarness) && (0 < status.numMessages(null, true))) { - if (!silentHarness) { - MessageUtil.print(getLogStream(), status, ""); - } - } - - logln(BridgeUtil.childString(status, numSkipped, numIncomplete) - + " " + (msElapsed/1000) + " seconds"); - - } - - // --------------- delegate methods - protected void logln(String s) { - if (!silentHarness) { - getLogStream().println(s); - } - } - - protected PrintStream getLogStream() { - return System.out; - } - - protected boolean isSuiteFile(String arg) { - return ((null != arg) - && (arg.endsWith(".txt") || arg.endsWith(".xml")) - && new File(arg).canRead()); - } - - /** - * Get the options that the input option is an alias for. - * Subclasses may add options directly to the getFeatureAliases result - * or override this. - * @return null if the input is not an alias for other options, - * or a non-empty List (String) of options that this option is an alias for - */ - protected List<String> aliasOptions(String option) { - Properties aliases = Harness.getOptionAliases(); - if (null != aliases) { - String args = aliases.getProperty(option); - if (!LangUtil.isEmpty(args)) { - return LangUtil.anySplit(args, OPTION_DELIM); - } - } - return null; - } - - /** - * Read and implement any of our options. - * Options other than this and suite files will be - * passed down as parent options through the test spec hierarchy. - * Subclasses override this to implement new options. - */ - protected boolean acceptOption(String option) { -// boolean result = false; - if (LangUtil.isEmpty(option)) { - return true; // skip bad input - } else if ("-verboseHarness".equals(option)) { - verboseHarness = true; + protected RunResult run(AjcTest.Suite.Spec spec) { + LangUtil.throwIaxIfNull(spec, "spec"); + /* + * For each run, initialize the runner and validator, + * create a new set of IRun{Iterator} tests, + * and run them. + * Delete all temp files when done. + */ + Runner runner = new Runner(); + if (0 != features.size()) { + for (Entry<String, Feature> entry : features.entrySet()) { + Feature feature = entry.getValue(); + runner.registerListener(feature.clazz, feature.listener); + } + } + IMessageHolder holder = new MessageHandler(); + int numIncomplete = 0; + RunStatus status = new RunStatus(holder, runner); + status.setIdentifier(spec); + // validator is used for all setup in entire tree... + Validator validator = new Validator(status); + if (!killTemp) { + validator.lock(this); + } + Sandbox sandbox = null; + try { + sandbox = new Sandbox(spec.getSuiteDirFile(), validator); + IRunIterator tests = spec.makeRunIterator(sandbox, validator); + runner.runIterator(tests, status, null); + if (tests instanceof RunSpecIterator) { + numIncomplete = ((RunSpecIterator) tests).getNumIncomplete(); + } + } finally { + if (!keepTemp) { + if (!killTemp) { + validator.unlock(this); + } + validator.deleteTempFiles(verboseHarness); + } + } + return new RunResult(status, numIncomplete); + } + + /** + * Report the results of a test run after it is completed. + * Clients should be able to identify the number of: + * <ul> + * <li>tests run and passed</li> + * <li>tests failed, i.e., run and not passed (fail, error, etc.)</li> + * <li>tests incomplete, i.e., test definition read but test run setup failed</li> + * <li>tests skipped, i.e., test definition read and found incompatible with + * the current configuration.</li> + * <ul> + * + * @param status returned from the run + * @param numSkipped int tests that were skipped because of + * configuration incompatibilities + * @param numIncomplete int tests that failed during setup, + * usually indicating a test definition or configuration error. + * @param msElapsed elapsed time in milliseconds + * */ + protected void report(IRunStatus status, int numSkipped, int numIncomplete, + long msElapsed ) { + if (logResults) { + RunUtils.AJCSUITE_PRINTER.printRunStatus(getLogStream(), status); + } else if (!(quietHarness || silentHarness) && (0 < status.numMessages(null, true))) { + if (!silentHarness) { + MessageUtil.print(getLogStream(), status, ""); + } + } + + logln(BridgeUtil.childString(status, numSkipped, numIncomplete) + + " " + (msElapsed/1000) + " seconds"); + + } + + // --------------- delegate methods + protected void logln(String s) { + if (!silentHarness) { + getLogStream().println(s); + } + } + + protected PrintStream getLogStream() { + return System.out; + } + + protected boolean isSuiteFile(String arg) { + return ((null != arg) + && (arg.endsWith(".txt") || arg.endsWith(".xml")) + && new File(arg).canRead()); + } + + /** + * Get the options that the input option is an alias for. + * Subclasses may add options directly to the getFeatureAliases result + * or override this. + * @return null if the input is not an alias for other options, + * or a non-empty List (String) of options that this option is an alias for + */ + protected List<String> aliasOptions(String option) { + Properties aliases = Harness.getOptionAliases(); + if (null != aliases) { + String args = aliases.getProperty(option); + if (!LangUtil.isEmpty(args)) { + return LangUtil.anySplit(args, OPTION_DELIM); + } + } + return null; + } + + /** + * Read and implement any of our options. + * Options other than this and suite files will be + * passed down as parent options through the test spec hierarchy. + * Subclasses override this to implement new options. + */ + protected boolean acceptOption(String option) { + // boolean result = false; + if (LangUtil.isEmpty(option)) { + return true; // skip bad input + } else if ("-verboseHarness".equals(option)) { + verboseHarness = true; } else if ("-quietHarness".equals(option)) { quietHarness = true; } else if ("-silentHarness".equals(option)) { silentHarness = true; - } else if ("-keepTemp".equals(option)) { - keepTemp = true; - } else if ("-killTemp".equals(option)) { - killTemp = true; - } else if ("-logResults".equals(option)) { - logResults = true; - } else if ("-exitOnFailure".equals(option)) { - exitOnFailure = true; - } else { - return false; - } - return true; - } - - /** - * Read a test suite file. - * This implementation knows how to read .txt and .xml files - * and logs any errors. - * Subclasses override this to read new kinds of suites. - * @return null if unable to read (logging errors) or AjcTest.Suite.Spec otherwise - */ - protected AjcTest.Suite.Spec readSuite(File suiteFile) { - if (null != suiteFile) { - String path = suiteFile.getPath(); - try { - if (path.endsWith(".xml")) { - return AjcSpecXmlReader.getReader().readAjcSuite(suiteFile); - } else if (path.endsWith(".txt")) { - return FlatSuiteReader.ME.readSuite(suiteFile); - } else { - logln("unrecognized extension? " + path); - } - } catch (IOException e) { - e.printStackTrace(getLogStream()); - } - } - return null; - } - - /** Add feature to take effect during the next runMain(..) invocation. - * @param feature the Feature to add, using feature.name as key. - */ - protected void addFeature(Feature feature) { - if (null != feature) { - features.put(feature.name, feature); - } - } - - /** remove feature by name (same as feature.name) */ - protected void removeFeature(String name) { - if (!LangUtil.isEmpty(name)) { - features.remove(name); - } - } - - /** @return unmodifiable Set of feature names */ - protected Set listFeatureNames() { - return Collections.unmodifiableSet(features.keySet()); - } - - /** print detail message for syntax of main(String[]) command-line */ - protected void printSyntax(PrintStream out) { - out.println(" {??} unrecognized options are used as test spec globals"); - out.println(" -help print this help message"); - out.println(" -verboseHarness harness components log verbosely"); - out.println(" -quietHarness harness components suppress logging"); - out.println(" -keepTemp do not delete temporary files"); - out.println(" -logResults log results at end, verbosely if fail"); - out.println(" -exitOnFailure do System.exit({num-failures}) if suite fails"); - out.println(" {suiteFile}.xml.. specify test suite XML file"); - out.println(" {suiteFile}.txt.. specify test suite .txt file (deprecated)"); - } - - /** print known aliases at the end of the syntax message */ - protected void printAliases(PrintStream out) { - LangUtil.throwIaxIfNull(out, "out"); - Properties props = getOptionAliases(); - if (null == props) { - return; - } - int pdLength = SYNTAX_PAD.length(); - Set entries = props.entrySet(); - for (Iterator iter = entries.iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); + } else if ("-keepTemp".equals(option)) { + keepTemp = true; + } else if ("-killTemp".equals(option)) { + killTemp = true; + } else if ("-logResults".equals(option)) { + logResults = true; + } else if ("-exitOnFailure".equals(option)) { + exitOnFailure = true; + } else { + return false; + } + return true; + } + + /** + * Read a test suite file. + * This implementation knows how to read .txt and .xml files + * and logs any errors. + * Subclasses override this to read new kinds of suites. + * @return null if unable to read (logging errors) or AjcTest.Suite.Spec otherwise + */ + protected AjcTest.Suite.Spec readSuite(File suiteFile) { + if (null != suiteFile) { + String path = suiteFile.getPath(); + try { + if (path.endsWith(".xml")) { + return AjcSpecXmlReader.getReader().readAjcSuite(suiteFile); + } else if (path.endsWith(".txt")) { + return FlatSuiteReader.ME.readSuite(suiteFile); + } else { + logln("unrecognized extension? " + path); + } + } catch (IOException e) { + e.printStackTrace(getLogStream()); + } + } + return null; + } + + /** Add feature to take effect during the next runMain(..) invocation. + * @param feature the Feature to add, using feature.name as key. + */ + protected void addFeature(Feature feature) { + if (null != feature) { + features.put(feature.name, feature); + } + } + + /** remove feature by name (same as feature.name) */ + protected void removeFeature(String name) { + if (!LangUtil.isEmpty(name)) { + features.remove(name); + } + } + + /** @return unmodifiable Set of feature names */ + protected Set listFeatureNames() { + return Collections.unmodifiableSet(features.keySet()); + } + + /** print detail message for syntax of main(String[]) command-line */ + protected void printSyntax(PrintStream out) { + out.println(" {??} unrecognized options are used as test spec globals"); + out.println(" -help print this help message"); + out.println(" -verboseHarness harness components log verbosely"); + out.println(" -quietHarness harness components suppress logging"); + out.println(" -keepTemp do not delete temporary files"); + out.println(" -logResults log results at end, verbosely if fail"); + out.println(" -exitOnFailure do System.exit({num-failures}) if suite fails"); + out.println(" {suiteFile}.xml.. specify test suite XML file"); + out.println(" {suiteFile}.txt.. specify test suite .txt file (deprecated)"); + } + + /** print known aliases at the end of the syntax message */ + protected void printAliases(PrintStream out) { + LangUtil.throwIaxIfNull(out, "out"); + Properties props = getOptionAliases(); + if (null == props) { + return; + } + int pdLength = SYNTAX_PAD.length(); + Set<Map.Entry<Object,Object>> entries = props.entrySet(); + for (Map.Entry<Object,Object> entry : entries) { String alias = " " + (String) entry.getKey(); - int buf = pdLength - alias.length(); - if (0 < buf) { - alias += SYNTAX_PAD.substring(0, buf); - } else { - alias += " "; - } - out.println(alias + entry.getValue()); - } - } - - /** result struct for run(AjcTest.Spec) */ - public static class RunResult { - public final IRunStatus status; - public final int numIncomplete; - public RunResult(IRunStatus status, int numIncomplete) { - this.status = status; - this.numIncomplete = numIncomplete; - } - } - /** feature implemented as named IRunIterator/IRun association */ - public static class Feature { - /** never null, always assignable to IRun */ - public final Class clazz; - - /** never null */ - public final IRunListener listener; - - /** never null or empty */ - public final String name; - - /** @throws IllegalArgumentException if any is null/empty or clazz is - * not assignable to IRun - */ - public Feature(String name, Class clazz, IRunListener listener) { - LangUtil.throwIaxIfNull(clazz, "class"); - if (!IRun.class.isAssignableFrom(clazz) - && !IRunIterator.class.isAssignableFrom(clazz)) { - String s = clazz.getName() + "is not assignable to IRun or IRunIterator"; - LangUtil.throwIaxIfFalse(false, s); - } - LangUtil.throwIaxIfNull(listener, "listener"); - LangUtil.throwIaxIfNull(name, "name"); - LangUtil.throwIaxIfFalse(0 < name.length(), "empty name"); - this.clazz = clazz; - this.listener = listener; - this.name = name; - } - - /** @return feature name */ - public String toString() { - return name; - } - } + int buf = pdLength - alias.length(); + if (0 < buf) { + alias += SYNTAX_PAD.substring(0, buf); + } else { + alias += " "; + } + out.println(alias + entry.getValue()); + } + } + + /** result struct for run(AjcTest.Spec) */ + public static class RunResult { + public final IRunStatus status; + public final int numIncomplete; + public RunResult(IRunStatus status, int numIncomplete) { + this.status = status; + this.numIncomplete = numIncomplete; + } + } + /** feature implemented as named IRunIterator/IRun association */ + public static class Feature { + /** never null, always assignable to IRun */ + public final Class clazz; + + /** never null */ + public final IRunListener listener; + + /** never null or empty */ + public final String name; + + /** @throws IllegalArgumentException if any is null/empty or clazz is + * not assignable to IRun + */ + public Feature(String name, Class clazz, IRunListener listener) { + LangUtil.throwIaxIfNull(clazz, "class"); + if (!IRun.class.isAssignableFrom(clazz) + && !IRunIterator.class.isAssignableFrom(clazz)) { + String s = clazz.getName() + "is not assignable to IRun or IRunIterator"; + LangUtil.throwIaxIfFalse(false, s); + } + LangUtil.throwIaxIfNull(listener, "listener"); + LangUtil.throwIaxIfNull(name, "name"); + LangUtil.throwIaxIfFalse(0 < name.length(), "empty name"); + this.clazz = clazz; + this.listener = listener; + this.name = name; + } + + /** @return feature name */ + @Override + public String toString() { + return name; + } + } } @@ -676,323 +677,333 @@ public class Harness { */ class FeatureHarness extends Harness { - private static final String[] ALIASES = new String[] - { "-hideStreams", - "-hideCompilerStreams" - + OPTION_DELIM + "-hideRunStreams", - "-jim", - "-logMinFail" - + OPTION_DELIM + "-hideStreams", - "-loud", - "-verboseHarness", - "-baseline", - "-verboseHarness" - + OPTION_DELIM + "-traceTestsMin" - + OPTION_DELIM + "-hideStreams", - "-release", - "-baseline" - + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava", - "-junit", - "-silentHarness" + OPTION_DELIM + "-logJUnit" + OPTION_DELIM + - "-hideStreams", - "-cruisecontrol", - "-junit" + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava" - }; - static { - Properties optionAliases = Harness.getOptionAliases(); - if (null != optionAliases) { - for (int i = 1; i < ALIASES.length; i += 2) { - optionAliases.put(ALIASES[i-1], ALIASES[i]); + private static final String[] ALIASES = new String[] + { "-hideStreams", + "-hideCompilerStreams" + + OPTION_DELIM + "-hideRunStreams", + "-jim", + "-logMinFail" + + OPTION_DELIM + "-hideStreams", + "-loud", + "-verboseHarness", + "-baseline", + "-verboseHarness" + + OPTION_DELIM + "-traceTestsMin" + + OPTION_DELIM + "-hideStreams", + "-release", + "-baseline" + + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava", + "-junit", + "-silentHarness" + OPTION_DELIM + "-logJUnit" + OPTION_DELIM + + "-hideStreams", + "-cruisecontrol", + "-junit" + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava" + }; + static { + Properties optionAliases = Harness.getOptionAliases(); + if (null != optionAliases) { + for (int i = 1; i < ALIASES.length; i += 2) { + optionAliases.put(ALIASES[i-1], ALIASES[i]); } - } - } - - /** controller for suppressing and sniffing error and output streams. */ - StreamsHandler streamsHandler; - - /** facility of hiding-streams may be applied in many features */ - IRunListener streamHider; - - /** facility of capture/log may be applied in many features */ - IRunListener captureLogger; - - /** when making tests, do not run them */ - TestMaker testMaker; - - public FeatureHarness() { - super(); - streamsHandler = new StreamsHandler(false, true); - } - /** override to make tests or run as usual */ - protected RunResult run(AjcTest.Suite.Spec spec) { - if (null != testMaker) { - System.out.println("generating rather than running tests..."); - return testMaker.run(spec); - } else { - return super.run(spec); - } - } - - /** - * Log via StreamsHandler-designated log stream. - * @see org.aspectj.testing.drivers.Harness#log(String) + } + } + + /** controller for suppressing and sniffing error and output streams. */ + StreamsHandler streamsHandler; + + /** facility of hiding-streams may be applied in many features */ + IRunListener streamHider; + + /** facility of capture/log may be applied in many features */ + IRunListener captureLogger; + + /** when making tests, do not run them */ + TestMaker testMaker; + + public FeatureHarness() { + super(); + streamsHandler = new StreamsHandler(false, true); + } + /** override to make tests or run as usual */ + @Override + protected RunResult run(AjcTest.Suite.Spec spec) { + if (null != testMaker) { + System.out.println("generating rather than running tests..."); + return testMaker.run(spec); + } else { + return super.run(spec); + } + } + + /** + * Log via StreamsHandler-designated log stream. + * @see org.aspectj.testing.drivers.Harness#log(String) */ + @Override protected void logln(String s) { if (!silentHarness) - streamsHandler.lnlog(s); + streamsHandler.lnlog(s); } - /** + /** * @see org.aspectj.testing.drivers.Harness#getLogStream() - * @return StreamsHandler-designated log stream. + * @return StreamsHandler-designated log stream. */ + @Override protected PrintStream getLogStream() { return streamsHandler.out; } - /** print detail message for syntax of main(String[]) command-line */ - protected void printSyntax(PrintStream out) { - super.printSyntax(out); - out.println(" -progressDots log . or ! for each AjcTest pass or fail"); - out.println(" -logFail log each failed AjcTest"); - out.println(" -logPass log each passed AjcTest"); - out.println(" -logAll log each AjcTest"); - out.println(" -logMinFail log each AjcTest failure with minimal excess data"); - out.println(" -logMinPass log each AjcTest success with minimal excess data"); - out.println(" -logMinAll log all AjcTest with minimal excess data"); - out.println(" -logXMLFail log XML definition for each failed AjcTest"); - out.println(" -logXMLPass log XML definition for each passed AjcTest"); - out.println(" -logXMLAll log XML definition for each AjcTest"); - out.println(" -logJUnit log all tests in JUnit XML report style"); - out.println(" -hideRunStreams hide err/out streams during java runs"); - out.println(" -hideCompilerStreams hide err/out streams during compiler runs"); - out.println(" -traceTests log pass|fail, /time/memory taken after each test"); - out.println(" -traceTestsMin log pass|fail after each test"); - out.println(" -XmakeTests create source files/dirs for initial compile run of each test"); - out.println(" -XlogPublicType log test XML if \"public type\" in an error message"); - out.println(" -XlogSourceIn=Y,Z log test XML if Y or Z is in path of any sources"); - super.printAliases(out); - } - - /** Accept a number of logging and output options */ + /** print detail message for syntax of main(String[]) command-line */ + @Override + protected void printSyntax(PrintStream out) { + super.printSyntax(out); + out.println(" -progressDots log . or ! for each AjcTest pass or fail"); + out.println(" -logFail log each failed AjcTest"); + out.println(" -logPass log each passed AjcTest"); + out.println(" -logAll log each AjcTest"); + out.println(" -logMinFail log each AjcTest failure with minimal excess data"); + out.println(" -logMinPass log each AjcTest success with minimal excess data"); + out.println(" -logMinAll log all AjcTest with minimal excess data"); + out.println(" -logXMLFail log XML definition for each failed AjcTest"); + out.println(" -logXMLPass log XML definition for each passed AjcTest"); + out.println(" -logXMLAll log XML definition for each AjcTest"); + out.println(" -logJUnit log all tests in JUnit XML report style"); + out.println(" -hideRunStreams hide err/out streams during java runs"); + out.println(" -hideCompilerStreams hide err/out streams during compiler runs"); + out.println(" -traceTests log pass|fail, /time/memory taken after each test"); + out.println(" -traceTestsMin log pass|fail after each test"); + out.println(" -XmakeTests create source files/dirs for initial compile run of each test"); + out.println(" -XlogPublicType log test XML if \"public type\" in an error message"); + out.println(" -XlogSourceIn=Y,Z log test XML if Y or Z is in path of any sources"); + super.printAliases(out); + } + + /** Accept a number of logging and output options */ + @Override protected boolean acceptOption(String option) { - if (null == option) { - return false; - } - - final StreamsHandler streams = streamsHandler; - final IRunValidator validator = RunValidator.NORMAL; - final RunUtils.IRunStatusPrinter verbose - = RunUtils.VERBOSE_PRINTER; - final RunUtils.IRunStatusPrinter terse - = RunUtils.TERSE_PRINTER; -// final boolean LOGPASS = true; -// final boolean LOGFAIL = true; -// final boolean SKIPPASS = false; -// final boolean SKIPFAIL = false; -// final boolean LOGSTREAMS = true; - final boolean SKIPSTREAMS = false; + if (null == option) { + return false; + } + + final StreamsHandler streams = streamsHandler; + final IRunValidator validator = RunValidator.NORMAL; + final RunUtils.IRunStatusPrinter verbose + = RunUtils.VERBOSE_PRINTER; + final RunUtils.IRunStatusPrinter terse + = RunUtils.TERSE_PRINTER; + // final boolean LOGPASS = true; + // final boolean LOGFAIL = true; + // final boolean SKIPPASS = false; + // final boolean SKIPFAIL = false; + // final boolean LOGSTREAMS = true; + final boolean SKIPSTREAMS = false; Feature feature = null; - if (super.acceptOption(option)) { - // ok, result returned below - - } else if ("-XmakeTests".equals(option)) { - testMaker = TestMaker.ME; - } else if (option.startsWith("-traceTestsMin")) { - feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, false)); - } else if (option.startsWith("-traceTests")) { - feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, true)); - } else if (option.startsWith("-logMin")) { - feature = new Feature(option, AjcTest.class, - new RunLogger(option, SKIPSTREAMS, streams, validator, terse)); - } else if (option.startsWith("-logXML")) { - feature = new Feature(option, AjcTest.class, - new XmlLogger(option, streams, validator)); - } else if (option.startsWith("-logJUnit")) { - feature = new Feature(option, AjcTest.class, - new JUnitXMLLogger(option,streams,validator)); - } else if (option.startsWith("-log")) { - feature = new Feature(option, AjcTest.class, - new RunLogger(option, SKIPSTREAMS, streams, validator, verbose)); - } else if ("-hideRunStreams".equals(option)) { - feature = new Feature(option, JavaRun.class, getStreamHider()); - } else if ("-hideCompilerStreams".equals(option)) { - addFeature(new Feature(option, IncCompilerRun.class, getStreamHider())); // hmmm - feature = new Feature(option, CompilerRun.class, getStreamHider()); - } else if ("-progressDots".equals(option)) { - IRunListener listener = new RunListener() { + if (super.acceptOption(option)) { + // ok, result returned below + + } else if ("-XmakeTests".equals(option)) { + testMaker = TestMaker.ME; + } else if (option.startsWith("-traceTestsMin")) { + feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, false)); + } else if (option.startsWith("-traceTests")) { + feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, true)); + } else if (option.startsWith("-logMin")) { + feature = new Feature(option, AjcTest.class, + new RunLogger(option, SKIPSTREAMS, streams, validator, terse)); + } else if (option.startsWith("-logXML")) { + feature = new Feature(option, AjcTest.class, + new XmlLogger(option, streams, validator)); + } else if (option.startsWith("-logJUnit")) { + feature = new Feature(option, AjcTest.class, + new JUnitXMLLogger(option,streams,validator)); + } else if (option.startsWith("-log")) { + feature = new Feature(option, AjcTest.class, + new RunLogger(option, SKIPSTREAMS, streams, validator, verbose)); + } else if ("-hideRunStreams".equals(option)) { + feature = new Feature(option, JavaRun.class, getStreamHider()); + } else if ("-hideCompilerStreams".equals(option)) { + addFeature(new Feature(option, IncCompilerRun.class, getStreamHider())); // hmmm + feature = new Feature(option, CompilerRun.class, getStreamHider()); + } else if ("-progressDots".equals(option)) { + IRunListener listener = new RunListener() { + @Override public void runCompleted(IRunStatus run) { - streamsHandler.log((validator.runPassed(run) ? "." : "!")); + streamsHandler.log((validator.runPassed(run) ? "." : "!")); } - }; - feature = new Feature(option, AjcTest.class, listener); - } else if (option.startsWith("-XlogPublicType")) { - String label = option + TestCompleteListener.PASS; // print when validator true - feature = new Feature(option, AjcTest.class, - new XmlLogger(label, streams, MessageRunValidator.PUBLIC_TYPE_ERROR)); - } else if (option.startsWith("-XlogSourceIn")) { - String input = option.substring("-XlogSourceIn=".length()); - LangUtil.throwIaxIfFalse(0 < input.length(), option); - String label = "-XlogSourceIn=" + TestCompleteListener.PASS; // print when validator true - StringRunner sr = new SubstringRunner(input, false); - feature = new Feature(option, AjcTest.class, - new XmlLogger(label, streams, new SourcePathValidator(sr))); - } else { - return false; - } - addFeature(feature); - return true; - } - - /** lazy construction for shared hider */ - protected IRunListener getStreamHider() { - if (null == streamHider) { - streamHider = new RunListener() { - public void runStarting(IRunStatus run) { - streamsHandler.hide(); - } - public void runCompleted(IRunStatus run) { - streamsHandler.show(); - } - public String toString() { return "Harness StreamHider"; } - }; - } - return streamHider; - } + }; + feature = new Feature(option, AjcTest.class, listener); + } else if (option.startsWith("-XlogPublicType")) { + String label = option + TestCompleteListener.PASS; // print when validator true + feature = new Feature(option, AjcTest.class, + new XmlLogger(label, streams, MessageRunValidator.PUBLIC_TYPE_ERROR)); + } else if (option.startsWith("-XlogSourceIn")) { + String input = option.substring("-XlogSourceIn=".length()); + LangUtil.throwIaxIfFalse(0 < input.length(), option); + String label = "-XlogSourceIn=" + TestCompleteListener.PASS; // print when validator true + StringRunner sr = new SubstringRunner(input, false); + feature = new Feature(option, AjcTest.class, + new XmlLogger(label, streams, new SourcePathValidator(sr))); + } else { + return false; + } + addFeature(feature); + return true; + } + + /** lazy construction for shared hider */ + protected IRunListener getStreamHider() { + if (null == streamHider) { + streamHider = new RunListener() { + @Override + public void runStarting(IRunStatus run) { + streamsHandler.hide(); + } + @Override + public void runCompleted(IRunStatus run) { + streamsHandler.show(); + } + @Override + public String toString() { return "Harness StreamHider"; } + }; + } + return streamHider; + } } /** Generate any needed test case files for any test. */ class TestMaker { - static TestMaker ME = new TestMaker(); - - /** @throws Error if unable to make dir */ - static void mkdirs(File dir) { - if (null != dir && !dir.exists()) { - if (!dir.mkdirs()) { - throw new Error("unable to make dir: " + dir); - } - } - } - static String getFileContents(File baseDir, File file, String label) { - String fileName = file.getName(); - if (fileName.endsWith(".java")) { - fileName = fileName.substring(0, fileName.length() - 5); - } - StringBuffer sb = new StringBuffer(); - String filePath = file.getParentFile().getAbsolutePath(); - String dirPath = baseDir.getAbsolutePath(); - String pack = null; - if (filePath.startsWith(dirPath)) { - pack = filePath.substring(dirPath.length()).replace('/', '.'); - } - if (!LangUtil.isEmpty(pack)) { - sb.append("package " + pack + ";"); - } - final String EOL = "\n"; // XXX find discovered EOL - sb.append( EOL - + EOL + "import org.aspectj.testing.Tester;" - + EOL + "" - + EOL + "/** @testcase " + label + " */" - + EOL + "public class " + fileName + " {" - + EOL + "\tpublic static void main(String[] args) { " - + EOL + "\t\tTester.check(null != args, \"null args\"); " - + EOL + "\t}" - + EOL + "}" - + EOL - ); - - return sb.toString(); - } - - /** create a minimal source file for a test */ - static void createSrcFile(File baseDir, File file, String testName) { - if (file.exists()) { - return; - } - String contents = getFileContents(baseDir, file, testName); - String error = FileUtil.writeAsString(file, contents); - if (null != error) { - throw new Error(error); - } - } - - /** create an empty arg file for a test */ - static void createArgFile(File baseDir, File file, String testName) { - if (file.exists()) { - return; - } - String contents = "// argfile " + file; - String error = FileUtil.writeAsString(file, contents); - if (null != error) { - throw new Error(error); - } - } - - public Harness.RunResult run(AjcTest.Suite.Spec spec) { - ArrayList kids = spec.getChildren(); - for (Iterator iter = kids.iterator(); iter.hasNext();) { - makeTest( (AjcTest.Spec) iter.next()); - } - IRunStatus status = new RunStatus(new MessageHandler(), new Runner()); - status.start(); - status.finish(IRunStatus.PASS); - return new Harness.RunResult(status, 0); - } - - private void makeTest(AjcTest.Spec spec) { - CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(spec); - if (null == spec) { - throw new Error("null spec"); - } - System.out.println(" generating test files for test: " + spec.getDescription()); - File dir = spec.getSuiteDir(); - if (null != dir) { - TestMaker.mkdirs(dir); - } - String offset = spec.getTestDirOffset(); - if (!LangUtil.isEmpty(offset)) { - if (null == dir) { - dir = new File(offset); - } else { - dir = new File(dir.getAbsolutePath() + "/" + offset); - } - } else if (null == dir) { - dir = new File("."); - } - StringBuffer testName = new StringBuffer(); - int pr = spec.getBugId(); - if (0 < pr) { - testName.append("PR#" + pr + " "); - } - - testName.append(spec.getDescription()); - final String label = testName.toString(); - final File[] srcFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getPathsArray()); - if (!LangUtil.isEmpty(srcFiles)) { - for (int i = 0; i < srcFiles.length; i++) { - TestMaker.createSrcFile(dir, srcFiles[i], label); - } - } - final File[] argFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getArgfilesArray()); - if (!LangUtil.isEmpty(argFiles)) { - for (int i = 0; i < argFiles.length; i++) { - TestMaker.createArgFile(dir, argFiles[i], label); - } - } - - } - - /** @return "Testmaker()" */ - public String toString() { - return "TestMaker()"; - } + static TestMaker ME = new TestMaker(); + + /** @throws Error if unable to make dir */ + static void mkdirs(File dir) { + if (null != dir && !dir.exists()) { + if (!dir.mkdirs()) { + throw new Error("unable to make dir: " + dir); + } + } + } + static String getFileContents(File baseDir, File file, String label) { + String fileName = file.getName(); + if (fileName.endsWith(".java")) { + fileName = fileName.substring(0, fileName.length() - 5); + } + StringBuffer sb = new StringBuffer(); + String filePath = file.getParentFile().getAbsolutePath(); + String dirPath = baseDir.getAbsolutePath(); + String pack = null; + if (filePath.startsWith(dirPath)) { + pack = filePath.substring(dirPath.length()).replace('/', '.'); + } + if (!LangUtil.isEmpty(pack)) { + sb.append("package " + pack + ";"); + } + final String EOL = "\n"; // XXX find discovered EOL + sb.append( EOL + + EOL + "import org.aspectj.testing.Tester;" + + EOL + "" + + EOL + "/** @testcase " + label + " */" + + EOL + "public class " + fileName + " {" + + EOL + "\tpublic static void main(String[] args) { " + + EOL + "\t\tTester.check(null != args, \"null args\"); " + + EOL + "\t}" + + EOL + "}" + + EOL + ); + + return sb.toString(); + } + + /** create a minimal source file for a test */ + static void createSrcFile(File baseDir, File file, String testName) { + if (file.exists()) { + return; + } + String contents = getFileContents(baseDir, file, testName); + String error = FileUtil.writeAsString(file, contents); + if (null != error) { + throw new Error(error); + } + } + + /** create an empty arg file for a test */ + static void createArgFile(File baseDir, File file, String testName) { + if (file.exists()) { + return; + } + String contents = "// argfile " + file; + String error = FileUtil.writeAsString(file, contents); + if (null != error) { + throw new Error(error); + } + } + + public Harness.RunResult run(AjcTest.Suite.Spec spec) { + ArrayList<IRunSpec> kids = spec.getChildren(); + for (IRunSpec iRunSpec : kids) { + makeTest( (AjcTest.Spec) iRunSpec); + } + IRunStatus status = new RunStatus(new MessageHandler(), new Runner()); + status.start(); + status.finish(IRunStatus.PASS); + return new Harness.RunResult(status, 0); + } + + private void makeTest(AjcTest.Spec spec) { + CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(spec); + if (null == spec) { + throw new Error("null spec"); + } + System.out.println(" generating test files for test: " + spec.getDescription()); + File dir = spec.getSuiteDir(); + if (null != dir) { + TestMaker.mkdirs(dir); + } + String offset = spec.getTestDirOffset(); + if (!LangUtil.isEmpty(offset)) { + if (null == dir) { + dir = new File(offset); + } else { + dir = new File(dir.getAbsolutePath() + "/" + offset); + } + } else if (null == dir) { + dir = new File("."); + } + StringBuffer testName = new StringBuffer(); + int pr = spec.getBugId(); + if (0 < pr) { + testName.append("PR#" + pr + " "); + } + + testName.append(spec.getDescription()); + final String label = testName.toString(); + final File[] srcFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getPathsArray()); + if (!LangUtil.isEmpty(srcFiles)) { + for (File srcFile : srcFiles) { + TestMaker.createSrcFile(dir, srcFile, label); + } + } + final File[] argFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getArgfilesArray()); + if (!LangUtil.isEmpty(argFiles)) { + for (File argFile : argFiles) { + TestMaker.createArgFile(dir, argFile, label); + } + } + + } + + /** @return "Testmaker()" */ + @Override + public String toString() { + return "TestMaker()"; + } } interface StringRunner { - boolean accept(String s); + boolean accept(String s); } /** @@ -1000,56 +1011,57 @@ interface StringRunner { * optionally case-insensitive. */ class SubstringRunner implements StringRunner { - private static String[] extractSubstrings( - String substrings, - boolean caseSensitive) { - if (null == substrings) { - return null; - } - StringTokenizer st = new StringTokenizer(substrings, ","); - String[] result = new String[st.countTokens()]; - for (int i = 0; i < result.length; i++) { + private static String[] extractSubstrings( + String substrings, + boolean caseSensitive) { + if (null == substrings) { + return null; + } + StringTokenizer st = new StringTokenizer(substrings, ","); + String[] result = new String[st.countTokens()]; + for (int i = 0; i < result.length; i++) { result[i] = st.nextToken().trim(); - LangUtil.throwIaxIfFalse(0 < result[i].length(), "empty entry"); - if (!caseSensitive) { - result[i] = result[i].toLowerCase(); - } - } - return result; - } - - private final String[] substrings; - private final boolean caseSensitive; - - /** - * @param substrings the String containing comma-separated substrings - * to find in input - if null, any input accepted - * @param caseSensitive if true, do case-sensitive comparison - * @throws IllegalArgumentException if any substrings contains empty entry ", ," - */ - SubstringRunner(String substrings, boolean caseSensitive) { - this.caseSensitive = caseSensitive; - this.substrings = extractSubstrings(substrings, caseSensitive); - } - - public boolean accept(String input) { - if (null == substrings) { - return true; - } - if (null == input) { - return false; - } - - if (!caseSensitive) { - input = input.toLowerCase(); - } - for (int i = 0; i < substrings.length; i++) { - if (-1 != input.indexOf(substrings[i])) { - return true; - } - } - return false; - } + LangUtil.throwIaxIfFalse(0 < result[i].length(), "empty entry"); + if (!caseSensitive) { + result[i] = result[i].toLowerCase(); + } + } + return result; + } + + private final String[] substrings; + private final boolean caseSensitive; + + /** + * @param substrings the String containing comma-separated substrings + * to find in input - if null, any input accepted + * @param caseSensitive if true, do case-sensitive comparison + * @throws IllegalArgumentException if any substrings contains empty entry ", ," + */ + SubstringRunner(String substrings, boolean caseSensitive) { + this.caseSensitive = caseSensitive; + this.substrings = extractSubstrings(substrings, caseSensitive); + } + + @Override + public boolean accept(String input) { + if (null == substrings) { + return true; + } + if (null == input) { + return false; + } + + if (!caseSensitive) { + input = input.toLowerCase(); + } + for (String substring : substrings) { + if (-1 != input.indexOf(substring)) { + return true; + } + } + return false; + } } /** @@ -1057,30 +1069,31 @@ class SubstringRunner implements StringRunner { * (Static evaluation - no run necessary) */ class SourcePathValidator implements IRunValidator { // static - no run needed - private final StringRunner validator; - // XXX hoist common - SourcePathValidator(StringRunner validator) { - LangUtil.throwIaxIfNull(validator, "validator"); - this.validator = validator; - } - /** - * @return true if any source files in compile spec are - * accepted by the validator. + private final StringRunner validator; + // XXX hoist common + SourcePathValidator(StringRunner validator) { + LangUtil.throwIaxIfNull(validator, "validator"); + this.validator = validator; + } + /** + * @return true if any source files in compile spec are + * accepted by the validator. * @see org.aspectj.testing.run.IRunValidator#runPassed(IRunStatus) */ + @Override public boolean runPassed(IRunStatus run) { - AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); - if (null != testSpec) { - CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); - File basedir = new File(testSpec.getSuiteDir(), testSpec.getTestDirOffset()); - String[] paths = compileSpec.getPathsArray(); - File[] files = FileUtil.getBaseDirFiles(basedir, paths); - for (int i = 0; i < files.length; i++) { - if (validator.accept(files[i].getAbsolutePath())) { - return true; - } + AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); + if (null != testSpec) { + CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); + File basedir = new File(testSpec.getSuiteDir(), testSpec.getTestDirOffset()); + String[] paths = compileSpec.getPathsArray(); + File[] files = FileUtil.getBaseDirFiles(basedir, paths); + for (File file : files) { + if (validator.accept(file.getAbsolutePath())) { + return true; + } } - } + } return false; } @@ -1089,65 +1102,65 @@ class SourcePathValidator implements IRunValidator { // static - no run needed /** Signal whether run "passed" based on message kind and content */ class MessageRunValidator implements IRunValidator { - /** signals "passed" if any error contains "public type" */ - static final IRunValidator PUBLIC_TYPE_ERROR - = new MessageRunValidator("public type", IMessage.ERROR, false); - - private final IMessage.Kind kind; - private final String sought; - private final boolean orGreater; - - /** - * @param sought the String to seek anywhere in any message of the right kind - * if null, accept any message of the right kind. - * @param kind the IMessage.Kind of messages to search - all if null - */ - MessageRunValidator(String sought, IMessage.Kind kind, boolean orGreater) { - this.sought = sought; - this.kind = kind; - this.orGreater = orGreater; - } - - /** @return true if this run has messages of the right kind and text */ + /** signals "passed" if any error contains "public type" */ + static final IRunValidator PUBLIC_TYPE_ERROR + = new MessageRunValidator("public type", IMessage.ERROR, false); + + private final IMessage.Kind kind; + private final String sought; + private final boolean orGreater; + + /** + * @param sought the String to seek anywhere in any message of the right kind + * if null, accept any message of the right kind. + * @param kind the IMessage.Kind of messages to search - all if null + */ + MessageRunValidator(String sought, IMessage.Kind kind, boolean orGreater) { + this.sought = sought; + this.kind = kind; + this.orGreater = orGreater; + } + + /** @return true if this run has messages of the right kind and text */ + @Override public boolean runPassed(IRunStatus run) { - return gotMessage(new IRunStatus[] {run}); - } - - /** - * Search these children and their children recursively - * for messages of the right kind and content. - * @return true at first match of message of the right kind and content - */ - private boolean gotMessage(IRunStatus[] children) { - if (LangUtil.isEmpty(children)) { - return false; - } - for (int i = 0; i < children.length; i++) { - IRunStatus run = children[i]; - if (null == run) { - continue; // hmm - } - IMessage[] messages = run.getMessages(kind, orGreater); - if (!LangUtil.isEmpty(messages)) { - if (LangUtil.isEmpty(sought)) { - return true; - } else { - for (int j = 0; j < messages.length; j++) { - if (null == messages[j]) { - continue; // hmm - } - String text = messages[j].getMessage(); - if ((null != text) && (-1 != text.indexOf(sought))) { - return true; - } - } - } - } - if (gotMessage(run.getChildren())) { - return true; - } - } - return false; + return gotMessage(new IRunStatus[] {run}); + } + + /** + * Search these children and their children recursively + * for messages of the right kind and content. + * @return true at first match of message of the right kind and content + */ + private boolean gotMessage(IRunStatus[] children) { + if (LangUtil.isEmpty(children)) { + return false; + } + for (IRunStatus run : children) { + if (null == run) { + continue; // hmm + } + IMessage[] messages = run.getMessages(kind, orGreater); + if (!LangUtil.isEmpty(messages)) { + if (LangUtil.isEmpty(sought)) { + return true; + } else { + for (IMessage message : messages) { + if (null == message) { + continue; // hmm + } + String text = message.getMessage(); + if ((null != text) && (-1 != text.indexOf(sought))) { + return true; + } + } + } + } + if (gotMessage(run.getChildren())) { + return true; + } + } + return false; } } @@ -1157,105 +1170,107 @@ class MessageRunValidator implements IRunValidator { * Subclasses implement doRunCompleted(..). */ abstract class TestCompleteListener extends RunListener { - /** label suffix indicating both pass and fail */ - public static final String ALL = "All"; - - /** label suffix indicating fail */ - public static final String FAIL = "Fail"; - - /** label suffix indicating pass */ - public static final String PASS = "Pass"; - - - /** runValidator determines if a given run passed */ - protected final IRunValidator runValidator; - - /** label for this listener */ - final String label; - - /** if trun and run passed, then run doRunCompleted(..) */ - final boolean logOnPass; - - /** if true and run did not pass, then run doRunCompleted(..) */ - final boolean logOnNotPass; - - /** may be null */ - protected final StreamsHandler streamsHandler; - - /** true if the last run evaluation was ok */ - boolean lastRunOk; - - /** last run evaluated */ - IRunStatus lastRun; // XXX small memory leak - cache hashcode instead? - - /** @param label endsWith PASS || FAIL || ALL */ - protected TestCompleteListener( - String label, - IRunValidator runValidator, - StreamsHandler streamsHandler) { - if (null == runValidator) { - runValidator = RunValidator.NORMAL; - } - this.label = (null == label? "" : label); - this.logOnPass = label.endsWith(PASS) || label.endsWith(ALL); - this.logOnNotPass = label.endsWith(FAIL) || label.endsWith(ALL); - this.runValidator = runValidator; - this.streamsHandler = streamsHandler; - } - - public void runStarted(IRunStatus run) { - if (null != streamsHandler) { - streamsHandler.startListening(); - } - } - - /** subclasses implement this to do some per-test initialization */ - protected void doRunStarted(IRunStatus run) { - } - - - /** subclasses implement this to do some per-suite initialization */ - protected void doStartSuite(File suite) { - } - - /** subclasses implement this to do end-of-suite processing */ - protected void doEndSuite(File suite, long duration) { - } - - public final void runCompleted(IRunStatus run) { - boolean doit = lastRunOk(run); - StreamsHandler.Result result = null; - if (null != streamsHandler) { - streamsHandler.endListening(doit); - } - if (doit) { - doRunCompleted(run, result); - } - } - - /** - * @return true if run is ok per constructor specifications - */ - protected boolean lastRunOk(IRunStatus run) { - if (lastRun != run) { - boolean passed = runValidator.runPassed(run); - lastRunOk = (passed ? logOnPass : logOnNotPass); - } - return lastRunOk; - } - - /** @return "{classname}({pass}{,fail})" indicating when this runs */ - public String toString() { // XXX add label? - return LangUtil.unqualifiedClassName(this) - + "(" + (logOnPass ? (logOnNotPass ? "pass, fail)" : "pass)") - : (logOnNotPass ? "fail)" : ")")); - } - /** - * Subclasses implement this to do some completion action - * @param run the IRunStatus for this completed run - * @param result the StreamsHandler.Result (if any - may be null) - */ - public abstract void doRunCompleted(IRunStatus run, StreamsHandler.Result result); + /** label suffix indicating both pass and fail */ + public static final String ALL = "All"; + + /** label suffix indicating fail */ + public static final String FAIL = "Fail"; + + /** label suffix indicating pass */ + public static final String PASS = "Pass"; + + + /** runValidator determines if a given run passed */ + protected final IRunValidator runValidator; + + /** label for this listener */ + final String label; + + /** if trun and run passed, then run doRunCompleted(..) */ + final boolean logOnPass; + + /** if true and run did not pass, then run doRunCompleted(..) */ + final boolean logOnNotPass; + + /** may be null */ + protected final StreamsHandler streamsHandler; + + /** true if the last run evaluation was ok */ + boolean lastRunOk; + + /** last run evaluated */ + IRunStatus lastRun; // XXX small memory leak - cache hashcode instead? + + /** @param label endsWith PASS || FAIL || ALL */ + protected TestCompleteListener( + String label, + IRunValidator runValidator, + StreamsHandler streamsHandler) { + if (null == runValidator) { + runValidator = RunValidator.NORMAL; + } + this.label = (null == label? "" : label); + this.logOnPass = label.endsWith(PASS) || label.endsWith(ALL); + this.logOnNotPass = label.endsWith(FAIL) || label.endsWith(ALL); + this.runValidator = runValidator; + this.streamsHandler = streamsHandler; + } + + public void runStarted(IRunStatus run) { + if (null != streamsHandler) { + streamsHandler.startListening(); + } + } + + /** subclasses implement this to do some per-test initialization */ + protected void doRunStarted(IRunStatus run) { + } + + + /** subclasses implement this to do some per-suite initialization */ + protected void doStartSuite(File suite) { + } + + /** subclasses implement this to do end-of-suite processing */ + protected void doEndSuite(File suite, long duration) { + } + + @Override + public final void runCompleted(IRunStatus run) { + boolean doit = lastRunOk(run); + StreamsHandler.Result result = null; + if (null != streamsHandler) { + streamsHandler.endListening(doit); + } + if (doit) { + doRunCompleted(run, result); + } + } + + /** + * @return true if run is ok per constructor specifications + */ + protected boolean lastRunOk(IRunStatus run) { + if (lastRun != run) { + boolean passed = runValidator.runPassed(run); + lastRunOk = (passed ? logOnPass : logOnNotPass); + } + return lastRunOk; + } + + /** @return "{classname}({pass}{,fail})" indicating when this runs */ + @Override + public String toString() { // XXX add label? + return LangUtil.unqualifiedClassName(this) + + "(" + (logOnPass ? (logOnNotPass ? "pass, fail)" : "pass)") + : (logOnNotPass ? "fail)" : ")")); + } + /** + * Subclasses implement this to do some completion action + * @param run the IRunStatus for this completed run + * @param result the StreamsHandler.Result (if any - may be null) + */ + public abstract void doRunCompleted(IRunStatus run, StreamsHandler.Result result); } /** @@ -1264,36 +1279,37 @@ abstract class TestCompleteListener extends RunListener { * most sensibly AjcTest.class. */ class XmlLogger extends TestCompleteListener { - /** - * @param printer the component that prints any status - not null - * @param runValidator if null, use RunValidator.NORMAL - */ - public XmlLogger( - String label, - StreamsHandler streamsHandler, - IRunValidator runValidator) { - super(label, runValidator, streamsHandler); - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - PrintStream out = streamsHandler.getLogStream(); - out.println(""); - XMLWriter writer = new XMLWriter(new PrintWriter(out, true)); - Object id = run.getIdentifier(); - if (!(id instanceof Runner.IteratorWrapper)) { - out.println(this + " not IteratorWrapper: " - + id.getClass().getName() + ": " + id); - return; - } - IRunIterator iter = ((Runner.IteratorWrapper) id).iterator; - if (!(iter instanceof RunSpecIterator)) { - out.println(this + " not RunSpecIterator: " + iter.getClass().getName() - + ": " + iter); - return; - } - ((RunSpecIterator) iter).spec.writeXml(writer); - out.flush(); - } + /** + * @param printer the component that prints any status - not null + * @param runValidator if null, use RunValidator.NORMAL + */ + public XmlLogger( + String label, + StreamsHandler streamsHandler, + IRunValidator runValidator) { + super(label, runValidator, streamsHandler); + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + PrintStream out = streamsHandler.getLogStream(); + out.println(""); + XMLWriter writer = new XMLWriter(new PrintWriter(out, true)); + Object id = run.getIdentifier(); + if (!(id instanceof Runner.IteratorWrapper)) { + out.println(this + " not IteratorWrapper: " + + id.getClass().getName() + ": " + id); + return; + } + IRunIterator iter = ((Runner.IteratorWrapper) id).iterator; + if (!(iter instanceof RunSpecIterator)) { + out.println(this + " not RunSpecIterator: " + iter.getClass().getName() + + ": " + iter); + return; + } + ((RunSpecIterator) iter).spec.writeXml(writer); + out.flush(); + } } @@ -1312,24 +1328,25 @@ class XmlLogger extends TestCompleteListener { */ class JUnitXMLLogger extends TestCompleteListener { -// private File suite; - private StringBuffer junitOutput; - private long startTimeMillis; - private int numTests = 0; - private int numFails = 0; - private DecimalFormat timeFormatter = new DecimalFormat("#.##"); - - public JUnitXMLLogger( - String label, - StreamsHandler streamsHandler, - IRunValidator runValidator) { - super(label + ALL, runValidator, streamsHandler); - junitOutput = new StringBuffer(); - } + // private File suite; + private StringBuffer junitOutput; + private long startTimeMillis; + private int numTests = 0; + private int numFails = 0; + private DecimalFormat timeFormatter = new DecimalFormat("#.##"); + + public JUnitXMLLogger( + String label, + StreamsHandler streamsHandler, + IRunValidator runValidator) { + super(label + ALL, runValidator, streamsHandler); + junitOutput = new StringBuffer(); + } /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doRunCompleted(org.aspectj.testing.run.IRunStatus, org.aspectj.testing.util.StreamsHandler.Result) */ + @Override public void doRunCompleted(IRunStatus run, Result result) { long duration = System.currentTimeMillis() - startTimeMillis; numTests++; @@ -1340,8 +1357,8 @@ class JUnitXMLLogger extends TestCompleteListener { numFails++; junitOutput.append("\n"); junitOutput.append("<failure message=\"test failed\" type=\"unknown\">\n"); -// junitOutput.println(result.junitOutput); -// junitOutput.println(result.err); + // junitOutput.println(result.junitOutput); + // junitOutput.println(result.err); junitOutput.append("</failure>\n"); } junitOutput.append("</testcase>\n"); @@ -1350,14 +1367,16 @@ class JUnitXMLLogger extends TestCompleteListener { /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#runStarted(org.aspectj.testing.run.IRunStatus) */ + @Override public void runStarting(IRunStatus run) { - super.runStarting(run); - startTimeMillis = System.currentTimeMillis(); + super.runStarting(run); + startTimeMillis = System.currentTimeMillis(); } /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doEndSuite(java.io.File, long) */ + @Override protected void doEndSuite(File suite, long duration) { super.doEndSuite(suite, duration); String suiteName = suite.getName(); @@ -1376,9 +1395,10 @@ class JUnitXMLLogger extends TestCompleteListener { /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doStartSuite(java.io.File) */ + @Override protected void doStartSuite(File suite) { super.doStartSuite(suite); -// this.suite = suite; + // this.suite = suite; numTests = 0; numFails = 0; junitOutput = new StringBuffer(); @@ -1388,98 +1408,101 @@ class JUnitXMLLogger extends TestCompleteListener { /** log pass and/or failed runs */ class RunLogger extends TestCompleteListener { - final boolean logStreams; - final RunUtils.IRunStatusPrinter printer; - - /** - * @param printer the component that prints any status - not null - * @param runValidator if null, use RunValidator.NORMAL - */ - public RunLogger( - String label, - boolean logStreams, - StreamsHandler streamsHandler, - IRunValidator runValidator, - RunUtils.IRunStatusPrinter printer) { - super(label, runValidator, streamsHandler); - LangUtil.throwIaxIfNull(streamsHandler, "streamsHandler"); - LangUtil.throwIaxIfNull(printer, "printer"); - this.logStreams = logStreams; - this.printer = printer; - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - PrintStream out = streamsHandler.getLogStream(); - printer.printRunStatus(out, run); - if (logStreams) { - if (!LangUtil.isEmpty(result.err)) { - out.println("--- error"); - out.println(result.err); - } - if (!LangUtil.isEmpty(result.out)) { - out.println("--- ouput"); - out.println(result.out); - } - } - out.println(""); - } + final boolean logStreams; + final RunUtils.IRunStatusPrinter printer; + + /** + * @param printer the component that prints any status - not null + * @param runValidator if null, use RunValidator.NORMAL + */ + public RunLogger( + String label, + boolean logStreams, + StreamsHandler streamsHandler, + IRunValidator runValidator, + RunUtils.IRunStatusPrinter printer) { + super(label, runValidator, streamsHandler); + LangUtil.throwIaxIfNull(streamsHandler, "streamsHandler"); + LangUtil.throwIaxIfNull(printer, "printer"); + this.logStreams = logStreams; + this.printer = printer; + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + PrintStream out = streamsHandler.getLogStream(); + printer.printRunStatus(out, run); + if (logStreams) { + if (!LangUtil.isEmpty(result.err)) { + out.println("--- error"); + out.println(result.err); + } + if (!LangUtil.isEmpty(result.out)) { + out.println("--- ouput"); + out.println(result.out); + } + } + out.println(""); + } } /** trace time and memory between runStaring and runCompleted */ class TestTraceLogger extends TestCompleteListener { - private static final Runtime runtime = Runtime.getRuntime(); - private long startTime; - private long startMemoryFree; - private final boolean verbose; - - public TestTraceLogger(StreamsHandler handler) { - this(handler, true); - } - public TestTraceLogger(StreamsHandler handler, boolean verbose) { - super("-traceTestsAll", null, handler); - this.verbose = verbose; - } - public void runStarting(IRunStatus run) { - super.runStarting(run); - startTime = System.currentTimeMillis(); - startMemoryFree = runtime.freeMemory(); - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - long elapsed = System.currentTimeMillis() - startTime; - long free = runtime.freeMemory(); - long used = startMemoryFree - free; - String label = run.runResult() ? "PASS " : "FAIL "; - PrintStream out = streamsHandler.getLogStream(); - if (verbose) { - label = label - + "elapsed: " + LangUtil.toSizedString(elapsed, 7) - + " free: " + LangUtil.toSizedString(free, 10) - + " used: " + LangUtil.toSizedString(used, 10) - + " id: "; - } - out.println(label + renderId(run)); - } - - /** @return true - always trace tests */ - protected boolean isFailLabel(String label) { - return true; - } - - /** @return true - always trace tests */ - protected boolean isPassLabel(String label) { - return true; - } - - /** - * This implementation returns run identifier toString(). - * Subclasses override this to render id as message suffix. - */ - protected String renderId(IRunStatus run) { - return "" + run.getIdentifier(); - } + private static final Runtime runtime = Runtime.getRuntime(); + private long startTime; + private long startMemoryFree; + private final boolean verbose; + + public TestTraceLogger(StreamsHandler handler) { + this(handler, true); + } + public TestTraceLogger(StreamsHandler handler, boolean verbose) { + super("-traceTestsAll", null, handler); + this.verbose = verbose; + } + @Override + public void runStarting(IRunStatus run) { + super.runStarting(run); + startTime = System.currentTimeMillis(); + startMemoryFree = runtime.freeMemory(); + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + long elapsed = System.currentTimeMillis() - startTime; + long free = runtime.freeMemory(); + long used = startMemoryFree - free; + String label = run.runResult() ? "PASS " : "FAIL "; + PrintStream out = streamsHandler.getLogStream(); + if (verbose) { + label = label + + "elapsed: " + LangUtil.toSizedString(elapsed, 7) + + " free: " + LangUtil.toSizedString(free, 10) + + " used: " + LangUtil.toSizedString(used, 10) + + " id: "; + } + out.println(label + renderId(run)); + } + + /** @return true - always trace tests */ + protected boolean isFailLabel(String label) { + return true; + } + + /** @return true - always trace tests */ + protected boolean isPassLabel(String label) { + return true; + } + + /** + * This implementation returns run identifier toString(). + * Subclasses override this to render id as message suffix. + */ + protected String renderId(IRunStatus run) { + return "" + run.getIdentifier(); + } } - // printing files +// printing files // AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); // if (null != testSpec) { // CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); 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 - + |