@@ -181,9 +181,15 @@ abstract public class AbstractRunSpec implements IRunSpec { | |||
addKeyword(keyword); | |||
} | |||
/** @return ((null == s) || (0 == s.trim().length())); */ | |||
public static boolean isEmptyTrimmed(String s) { | |||
return ((null == s) || (0 == s.length()) | |||
|| (0 == s.trim().length())); | |||
} | |||
/** Add keyword if non-empty and not duplicate */ | |||
public void addKeyword(String keyword) { | |||
if (!LangUtil.isEmptyTrimmed(keyword)) { | |||
if (!isEmptyTrimmed(keyword)) { | |||
keyword = keyword.trim(); | |||
if (!keywords.contains(keyword)) { | |||
keywords.add(keyword); |
@@ -15,6 +15,7 @@ | |||
package org.aspectj.testing.harness.bridge; | |||
import java.io.*; | |||
import java.lang.reflect.Array; | |||
import java.util.*; | |||
import org.aspectj.bridge.*; | |||
@@ -98,6 +99,73 @@ public class CompilerRun implements IAjcRun { | |||
injars = new ArrayList(); | |||
inpaths = new ArrayList(); | |||
} | |||
/** | |||
* Select from input String[] if readable directories | |||
* @param inputs String[] of input - null ignored | |||
* @param baseDir the base directory of the input | |||
* @return String[] of input that end with any input | |||
*/ | |||
public static String[] selectDirectories(String[] inputs, File baseDir) { | |||
if (LangUtil.isEmpty(inputs)) { | |||
return new String[0]; | |||
} | |||
ArrayList result = new ArrayList(); | |||
for (int i = 0; i < inputs.length; i++) { | |||
String input = inputs[i]; | |||
if (null == input) { | |||
continue; | |||
} | |||
File inputFile = new File(baseDir, input); | |||
if (inputFile.canRead() && inputFile.isDirectory()) { | |||
result.add(input); | |||
} | |||
} | |||
return (String[]) result.toArray(new String[0]); | |||
} | |||
/** | |||
* Select from input String[] based on suffix-matching | |||
* @param inputs String[] of input - null ignored | |||
* @param suffixes String[] of suffix selectors - null ignored | |||
* @param ignoreCase if true, ignore case | |||
* @return String[] of input that end with any input | |||
*/ | |||
public static String[] endsWith(String[] inputs, String[] suffixes, boolean ignoreCase) { | |||
if (LangUtil.isEmpty(inputs) || LangUtil.isEmpty(suffixes)) { | |||
return new String[0]; | |||
} | |||
if (ignoreCase) { | |||
String[] temp = new String[suffixes.length]; | |||
for (int i = 0; i < temp.length; i++) { | |||
String suff = suffixes[i]; | |||
temp[i] = (null == suff ? null : suff.toLowerCase()); | |||
} | |||
suffixes = temp; | |||
} | |||
ArrayList result = new ArrayList(); | |||
for (int i = 0; i < inputs.length; i++) { | |||
String input = inputs[i]; | |||
if (null == input) { | |||
continue; | |||
} | |||
if (!ignoreCase) { | |||
input = input.toLowerCase(); | |||
} | |||
for (int j = 0; j < suffixes.length; j++) { | |||
String suffix = suffixes[j]; | |||
if (null == suffix) { | |||
continue; | |||
} | |||
if (input.endsWith(suffix)) { | |||
result.add(input); | |||
break; | |||
} | |||
} | |||
} | |||
return (String[]) result.toArray(new String[0]); | |||
} | |||
/** | |||
* This checks that the spec is reasonable and does setup: | |||
@@ -160,14 +228,14 @@ public class CompilerRun implements IAjcRun { | |||
{ | |||
final String[] paths = spec.getPathsArray(); | |||
srcPaths = | |||
LangUtil.endsWith( | |||
endsWith( | |||
paths, | |||
CompilerRun.SOURCE_SUFFIXES, | |||
true); | |||
injarPaths = | |||
LangUtil.endsWith(paths, CompilerRun.JAR_SUFFIXES, true); | |||
endsWith(paths, CompilerRun.JAR_SUFFIXES, true); | |||
inpathPaths = | |||
LangUtil.selectDirectories(paths, testBaseSrcDir); | |||
selectDirectories(paths, testBaseSrcDir); | |||
if (!spec.badInput) { | |||
int found = inpathPaths.length + injarPaths.length + srcPaths.length; | |||
if (paths.length != found) { | |||
@@ -175,6 +243,7 @@ public class CompilerRun implements IAjcRun { | |||
} | |||
} | |||
} | |||
// validate readable for sources | |||
if (!spec.badInput) { | |||
if (!validator.canRead(testBaseSrcDir, srcPaths, "sources") | |||
@@ -656,7 +725,7 @@ public class CompilerRun implements IAjcRun { | |||
int version = sourceVersion.charAt(2) - '0'; | |||
switch (version) { | |||
case (3) : | |||
if (LangUtil.supportsJava("1.4")) { | |||
if (Globals.supportsJava("1.4")) { | |||
if (!FileUtil.canReadFile(Globals.J2SE13_RTJAR)) { | |||
return "no 1.3 libraries to handle -source 1.3"; | |||
} | |||
@@ -665,7 +734,7 @@ public class CompilerRun implements IAjcRun { | |||
} | |||
break; | |||
case (4) : | |||
if (!LangUtil.supportsJava("1.4")) { | |||
if (!Globals.supportsJava("1.4")) { | |||
if (ReflectionFactory | |||
.ECLIPSE | |||
.equals(compilerName)) { | |||
@@ -870,7 +939,21 @@ public class CompilerRun implements IAjcRun { | |||
if (LangUtil.isEmpty(argfiles)) { | |||
return new String[0]; | |||
} | |||
return (String[]) LangUtil.copy(argfiles); | |||
return (String[]) copy(argfiles); | |||
} | |||
/** | |||
* Make a copy of the array. | |||
* @return an array with the same component type as source | |||
* containing same elements, even if null. | |||
* @throws IllegalArgumentException if source is null | |||
*/ | |||
public static final Object[] copy(Object[] source) { | |||
LangUtil.throwIaxIfNull(source, "source"); | |||
final Class c = source.getClass().getComponentType(); | |||
Object[] result = (Object[]) Array.newInstance(c, source.length); | |||
System.arraycopy(source, 0, result, 0, result.length); | |||
return result; | |||
} | |||
/** |
@@ -31,9 +31,9 @@ import org.aspectj.testing.util.BridgeUtil; | |||
import org.aspectj.testing.util.ObjectChecker; | |||
import org.aspectj.testing.util.SFileReader; | |||
import org.aspectj.testing.util.StandardObjectChecker; | |||
import org.aspectj.testing.util.UtilLineReader; | |||
import org.aspectj.util.FileUtil; | |||
import org.aspectj.util.LangUtil; | |||
import org.aspectj.util.LineReader; | |||
/** | |||
* SFileReader.Maker implementation to read tests | |||
@@ -74,9 +74,9 @@ public class FlatSuiteReader implements SFileReader.Maker { | |||
* test definition in reader and taking the parent directory of | |||
* the reader as the base directory for the test suite root. | |||
* @return the next AjcTest in reader, or null | |||
* @see org.aspectj.testing.harness.bridge.SFileReader.Maker#make(LineReader) | |||
* @see org.aspectj.testing.harness.bridge.SFileReader.Maker#make(UtilLineReader) | |||
*/ | |||
public Object make(final LineReader reader) | |||
public Object make(final UtilLineReader reader) | |||
throws AbortException, IOException { | |||
final AjcTest.Spec result = new AjcTest.Spec(); | |||
boolean usingEclipse = false; // XXX | |||
@@ -233,7 +233,7 @@ public class FlatSuiteReader implements SFileReader.Maker { | |||
* - convert test options to force-options | |||
* - detect illegal xml characters | |||
*/ | |||
private void cleanup(AjcTest.Spec result, LineReader lineReader) { | |||
private void cleanup(AjcTest.Spec result, UtilLineReader lineReader) { | |||
LangUtil.throwIaxIfNull(result, "result"); | |||
LangUtil.throwIaxIfNull(lineReader, "lineReader"); | |||
@@ -16,6 +16,9 @@ | |||
package org.aspectj.testing.harness.bridge; | |||
import java.io.File; | |||
import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.aspectj.util.FileUtil; | |||
import org.aspectj.util.LangUtil; | |||
@@ -23,6 +26,10 @@ import org.aspectj.util.LangUtil; | |||
/** | |||
*/ | |||
public class Globals { | |||
/** map from String version to String class implemented in that version or later */ | |||
private static final Map VM_CLASSES; | |||
public static final String FORK_NAME = "harness.fork"; | |||
// XXX in testing-drivers/../package.htm | |||
/** name/key of the System property to set to define library dir */ | |||
@@ -64,6 +71,13 @@ public class Globals { | |||
&& FileUtil.canReadFile(F_aspectjrt_jar) | |||
&& FileUtil.canReadFile(J2SE13_RTJAR) | |||
&& FileUtil.canReadFile(J2SE14_RTJAR)); | |||
HashMap map = new HashMap(); | |||
map.put("1.2", "java.lang.ref.Reference"); | |||
map.put("1.3", "java.lang.reflect.Proxy"); | |||
map.put("1.4", "java.nio.Buffer"); | |||
map.put("1.5", "java.lang.annotation.Annotation"); | |||
VM_CLASSES = Collections.unmodifiableMap(map); | |||
} | |||
private static File getRtJarFor( | |||
@@ -123,5 +137,26 @@ public class Globals { | |||
} | |||
return result; | |||
} | |||
/** | |||
* Detect whether Java version is supported. | |||
* @param version String "1.2" or "1.3" or "1.4" | |||
* @return true if the currently-running VM supports the version | |||
* @throws IllegalArgumentException if version is not known | |||
*/ | |||
public static final boolean supportsJava(String version) { | |||
LangUtil.throwIaxIfNull(version, "version"); | |||
String className = (String) VM_CLASSES.get(version); | |||
if (null == className) { | |||
throw new IllegalArgumentException("unknown version: " + version); | |||
} | |||
try { | |||
Class.forName(className); | |||
return true; | |||
} catch (Throwable t) { | |||
return false; | |||
} | |||
} | |||
} |
@@ -277,7 +277,7 @@ public class JavaRun implements IAjcRun { | |||
cmd.add(classpath); | |||
} else { | |||
// verify 1.4 or above, assuming same vm as running this | |||
if (!LangUtil.supportsJava("1.4")) { | |||
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"); | |||
@@ -660,7 +660,7 @@ public class JavaRun implements IAjcRun { | |||
* @throws IllegalArgumentException if version is not recognized | |||
*/ | |||
public void setJavaVersion(String version) { | |||
LangUtil.supportsJava(version); | |||
Globals.supportsJava(version); | |||
this.javaVersion = version; | |||
} | |||
@@ -779,7 +779,7 @@ public class JavaRun implements IAjcRun { | |||
if (!super.doAdoptParentValues(parentRuntime, handler)) { | |||
return false; | |||
} | |||
if ((null != javaVersion) && (!LangUtil.supportsJava(javaVersion))) { | |||
if ((null != javaVersion) && (!Globals.supportsJava(javaVersion))) { | |||
skipMessage(handler, "requires Java version " + javaVersion); | |||
return false; | |||
} |
@@ -24,7 +24,6 @@ import org.aspectj.bridge.SourceLocation; | |||
import org.aspectj.testing.run.IRunStatus; | |||
import org.aspectj.testing.run.RunValidator; | |||
import org.aspectj.util.FileUtil; | |||
import org.aspectj.util.LineReader; | |||
/** | |||
* | |||
@@ -43,7 +42,7 @@ public class BridgeUtil { | |||
private static final String MESSAGE_DELIM = "\" - "; | |||
public static ISourceLocation makeSourceLocation(LineReader reader) { | |||
public static ISourceLocation makeSourceLocation(UtilLineReader reader) { | |||
LangUtil.throwIaxIfNull(reader, "reader"); | |||
int line = reader.getLineNumber(); | |||
@@ -59,12 +58,12 @@ public class BridgeUtil { | |||
private static ISourceLocation readSourceLocation(String sourceLocStr) { | |||
return BridgeUtil.makeSourceLocation(sourceLocStr); | |||
} | |||
public static IMessage makeMessage(String message, IMessage.Kind kind, | |||
Throwable thrown, LineReader reader) { | |||
ISourceLocation sl = (null == reader ? null : MessageUtil.makeSourceLocation(reader)); | |||
if (null == kind) kind = IMessage.INFO; | |||
return new Message(message, kind, thrown, sl); | |||
} | |||
// public static IMessage makeMessage(String message, IMessage.Kind kind, | |||
// Throwable thrown, LineReader reader) { | |||
// ISourceLocation sl = (null == reader ? null : MessageUtil.makeSourceLocation(reader)); | |||
// if (null == kind) kind = IMessage.INFO; | |||
// return new Message(message, kind, thrown, sl); | |||
// } | |||
/** | |||
* Read a message from a string written by writeMessage(IMessage). |
@@ -21,7 +21,6 @@ import java.util.ArrayList; | |||
import org.aspectj.bridge.AbortException; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.util.LangUtil; | |||
import org.aspectj.util.LineReader; | |||
/** | |||
@@ -98,9 +97,9 @@ public class SFileReader { | |||
} else if (!file.isAbsolute()) { | |||
throw new IllegalArgumentException("file not absolute"); | |||
} | |||
LineReader reader = null; | |||
UtilLineReader reader = null; | |||
try { | |||
reader = LineReader.createTester(file); | |||
reader = UtilLineReader.createTester(file); | |||
if (null == reader) { | |||
throw new IOException("no reader for " + file); | |||
} | |||
@@ -167,7 +166,7 @@ public class SFileReader { | |||
* Make the result using the input from the LineReader, | |||
* starting with lastLine(). | |||
*/ | |||
Object make(LineReader reader) throws AbortException, IOException; | |||
Object make(UtilLineReader reader) throws AbortException, IOException; | |||
/** @return type of the Object made */ | |||
Class getType(); | |||
@@ -176,7 +175,7 @@ public class SFileReader { | |||
* @return file:line: {line} | |||
*/ | |||
static final Maker ECHO = new Maker() { | |||
public Object make(LineReader reader) { | |||
public Object make(UtilLineReader reader) { | |||
return reader + ": " + reader.lastLine(); | |||
} | |||
public Class getType() { return String.class; } |
@@ -0,0 +1,212 @@ | |||
/* ******************************************************************* | |||
* 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 | |||
* ******************************************************************/ | |||
package org.aspectj.testing.util; | |||
import java.io.*; | |||
import java.util.ArrayList; | |||
/** | |||
* LineNumberReader which absorbs comments and blank lines | |||
* and renders as file:line | |||
*/ | |||
public class UtilLineReader extends LineNumberReader { | |||
/** delimited multi-line output of readToBlankLine */ | |||
public static final String RETURN= "\n\r"; | |||
private static final String[] NONE = new String[0]; | |||
private static final String cSCRIPT = "#"; | |||
private static final String cJAVA = "//"; | |||
private static final String[] TESTER_LEAD = new String[] {cSCRIPT, cJAVA}; | |||
/** | |||
* Convenience factory for tester suite files | |||
* @return null if IOException or IllegalArgumentException thrown | |||
*/ | |||
public static final UtilLineReader createTester(File file) { | |||
return create(file, TESTER_LEAD, null); | |||
} | |||
/** | |||
* convenience factory | |||
* @return null if IOException or IllegalArgumentException thrown | |||
*/ | |||
public static final UtilLineReader create(File file, | |||
String[] leadComments, String[] eolComments) { | |||
try { | |||
FileReader reader = new FileReader(file); | |||
return new UtilLineReader(reader, file, leadComments, eolComments); | |||
} catch (IllegalArgumentException e) { | |||
} catch (IOException e) { | |||
} | |||
return null; | |||
} | |||
final private File file; | |||
final private String[] eolComments; | |||
final private String[] leadComments; | |||
transient String lastLine; | |||
/** | |||
* @param file the File used to open the FileReader | |||
* @param leadComments the String[] to be taken as the start of | |||
* comments when they are the first non-blank text on a line - | |||
* pass null to signal none. | |||
* @param leadComments the String[] to be taken as the start of | |||
* comment anywhere on a line - pass null to signal none. | |||
*@throws IllegalArgumentException if any String in | |||
* leadComments or eolComments is null. | |||
*/ | |||
public UtilLineReader(FileReader reader, File file, | |||
String[] leadComments, String[] eolComments) { | |||
super(reader); | |||
this.file = file; | |||
this.eolComments = normalize(eolComments); | |||
this.leadComments = normalize(leadComments); | |||
} | |||
public UtilLineReader(FileReader reader, File file) { | |||
this(reader, file, null, null); | |||
} | |||
/** @return file:line */ | |||
public String toString() { | |||
return file.getPath() + ":" + getLineNumber(); | |||
} | |||
/** @return underlying file */ | |||
public File getFile() { return file; } | |||
/** | |||
* Reader first..last (inclusive) and return in String[]. | |||
* This will return (1+(last-first)) elements only if this | |||
* reader has not read past the first line and there are last lines | |||
* and there are no IOExceptions during reads. | |||
* @param first the first line to read - if negative, use 0 | |||
* @param last the last line to read (inclusive) | |||
* - if less than first, use first | |||
* @return String[] of first..last (inclusive) lines read or | |||
*/ | |||
public String[] readLines(int first, int last) { | |||
if (0 > first) first = 0; | |||
if (first > last) last = first; | |||
ArrayList list = new ArrayList(); | |||
try { | |||
String line = null; | |||
while (getLineNumber() < first) { | |||
line = readLine(); | |||
if (null == line) { | |||
break; | |||
} | |||
} | |||
if (getLineNumber() > first) { | |||
// XXX warn? something else read past line | |||
} | |||
if ((null != line) && (first == getLineNumber())) { | |||
list.add(line); | |||
while (last >= getLineNumber()) { | |||
line = readLine(); | |||
if (null == line) { | |||
break; | |||
} | |||
list.add(line); | |||
} | |||
} | |||
} catch (IOException e) { | |||
return NONE; | |||
} | |||
return (String[]) list.toArray(NONE); | |||
} | |||
/** Skip to next blank line | |||
* @return the String containing all lines skipped (delimited with RETURN) | |||
*/ | |||
public String readToBlankLine() throws IOException { | |||
StringBuffer sb = new StringBuffer(); | |||
String input; | |||
while (null != (input = nextLine(false))) { // get next empty line to restart | |||
sb.append(input); | |||
sb.append(RETURN);// XXX verify/ignore/correct | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* lastLine is set only by readClippedLine, not readLine. | |||
* @return the last line read, after clipping | |||
*/ | |||
public String lastLine() { | |||
return lastLine; | |||
} | |||
/** | |||
* Get the next line from the input stream, stripping eol and | |||
* leading comments. | |||
* If emptyLinesOk is true, then this reads past lines which are | |||
* empty after omitting comments and trimming until the next non-empty line. | |||
* Otherwise, this returns null on reading an empty line. | |||
* (The input stream is not exhausted until this | |||
* returns null when emptyLines is true.) | |||
* @param skipEmpties if true, run to next non-empty line; if false, return next line | |||
* @return null if no more lines or got an empty line when they are not ok, | |||
* or next non-null, non-empty line in reader, | |||
* ignoring comments | |||
*/ | |||
public String nextLine(boolean skipEmpties) throws IOException { | |||
String result; | |||
do { | |||
result = readClippedLine(); | |||
if ((null != result) && skipEmpties && (0 == result.length())) { | |||
continue; | |||
} | |||
return result; | |||
} while (true); | |||
} | |||
/** @return null if no more lines or a clipped line otherwise */ | |||
protected String readClippedLine() throws IOException { | |||
String result = readLine(); | |||
if (result != null) { | |||
result = result.trim(); | |||
int len = result.length(); | |||
for (int i = 0; ((0 < len) && (i < leadComments.length)); i++) { | |||
if (result.startsWith(leadComments[i])) { | |||
result = ""; | |||
len = 0; | |||
} | |||
} | |||
for (int i = 0; ((0 < len) && (i < eolComments.length)); i++) { | |||
int loc = result.indexOf(eolComments[i]); | |||
if (-1 != loc) { | |||
result = result.substring(0, loc); | |||
len = result.length(); | |||
} | |||
} | |||
} | |||
lastLine = result; | |||
return result; | |||
} | |||
private String[] normalize(String[] input) { | |||
if ((null == input) || (0 == input.length)) return NONE; | |||
String[] result = new String[input.length]; | |||
System.arraycopy(input, 0, result, 0, result.length); | |||
for (int i = 0; i < result.length; i++) { | |||
if ((null == result[i]) || (0 == result[i].length())) { | |||
throw new IllegalArgumentException("empty input at [" + i + "]"); | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||