--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectj-parent</artifactId>
+ <packaging>pom</packaging>
+ <version>${revision}</version>
+ <name>AspectJ Parent Project</name>
+
+ <properties>
+ <revision>1.9.3.BUILD-SNAPSHOT</revision>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <modules>
+ <module>util</module>
+ <module>bcel</module>
+ </modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <testFailureIgnore>true</testFailureIgnore>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="testsrc"/>
- <classpathentry kind="lib" path="/lib/junit/junit.jar" sourcepath="/lib/junit/junit-src.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="output" path="bin"/>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ <attribute name="test" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="target/generated-sources/annotations">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ <attribute name="ignore_optional_problems" value="true"/>
+ <attribute name="m2e-apt" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ <attribute name="ignore_optional_problems" value="true"/>
+ <attribute name="m2e-apt" value="true"/>
+ <attribute name="test" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
</classpath>
+++ /dev/null
-bin
-
-bintest
+++ /dev/null
-
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>util</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=false
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.processAnnotations=disabled
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
+++ /dev/null
-<?xml version="1.0"?>
-<!-- see ../build/*.html for explanation -->
-<project name="util" default="test" basedir=".">
- <import file="${basedir}/../build/build.xml"/>
-</project>
-
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>util</artifactId>
+ <packaging>jar</packaging>
+ <name>util</name>
+
+ <parent>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectj-parent</artifactId>
+ <version>${revision}</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+</project>
+++ /dev/null
-Index: src/org/aspectj/util/ConfigParser.java
-===================================================================
-RCS file: /home/technology/org.aspectj/modules/util/src/org/aspectj/util/ConfigParser.java,v
-retrieving revision 1.6
-diff -u -r1.6 ConfigParser.java
---- src/org/aspectj/util/ConfigParser.java 5 Aug 2004 17:31:56 -0000 1.6
-+++ src/org/aspectj/util/ConfigParser.java 2 Sep 2005 07:40:04 -0000
-@@ -21,11 +21,14 @@
- public class ConfigParser {
- Location location;
- protected File relativeDirectory = null;
-- protected List files = new LinkedList();
-+ protected List files = new ArrayList();
-+ protected Map userFileMap = new HashMap(); // from File -> File, keys are canonical files, values are the 'user' path
- private boolean fileParsed = false;
- protected static String CONFIG_MSG = "build config error: ";
-
- public List getFiles() { return files; }
-+
-+ public Map getUserFileNameMap() { return userFileMap; }
-
- public void parseCommandLine(String[] argsArray) throws ParseException {
- location = new CommandLineLocation();
-@@ -221,7 +224,9 @@
- ret = new File(dir, name);
- }
- try {
-- ret = ret.getCanonicalFile();
-+ File canonicalFile = ret.getCanonicalFile();
-+ userFileMap.put(canonicalFile,new File(name));
-+ ret = canonicalFile;
- } catch (IOException ioEx) {
- // proceed without canonicalization
- // so nothing to do here
--- /dev/null
+/* *******************************************************************
+ * 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.util;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * @author Andy Clement
+ * @author Kris De Volder
+ */
+public class FileUtil {
+ /** default parent directory File when a file has a null parent */
+ public static final File DEFAULT_PARENT = new File("."); // XXX user.dir?
+
+ /** unmodifiable List of String source file suffixes (including leading ".") */
+ public static final List<String> SOURCE_SUFFIXES = Collections.unmodifiableList(Arrays.asList(new String[] { ".java", ".aj" }));
+
+ public static final FileFilter ZIP_FILTER = new FileFilter() {
+ public boolean accept(File file) {
+ return isZipFile(file);
+ }
+
+ public String toString() {
+ return "ZIP_FILTER";
+ }
+ };
+
+ // public static final FileFilter SOURCE_FILTER = new FileFilter() {
+ // public boolean accept(File file) {
+ // return hasSourceSuffix(file);
+ // }
+ //
+ // public String toString() {
+ // return "SOURCE_FILTER";
+ // }
+ // };
+
+ final static int[] INT_RA = new int[0];
+
+ /** accept all files */
+ public static final FileFilter ALL = new FileFilter() {
+ public boolean accept(File f) {
+ return true;
+ }
+ };
+ public static final FileFilter DIRS_AND_WRITABLE_CLASSES = new FileFilter() {
+ public boolean accept(File file) {
+ return ((null != file) && (file.isDirectory() || (file.canWrite() && file.getName().toLowerCase().endsWith(".class"))));
+ }
+ };
+ private static final boolean PERMIT_CVS;
+ static {
+ String name = FileUtil.class.getName() + ".PERMIT_CVS";
+ PERMIT_CVS = LangUtil.getBoolean(name, false);
+ }
+
+ /** @return true if file exists and is a zip file */
+ public static boolean isZipFile(File file) {
+ try {
+ return (null != file) && new ZipFile(file) != null;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ /** @return true if path ends with .zip or .jar */
+ // public static boolean hasZipSuffix(String path) {
+ // return ((null != path) && (0 != zipSuffixLength(path)));
+ // }
+ /** @return 0 if file has no zip/jar suffix or 4 otherwise */
+ public static int zipSuffixLength(File file) {
+ return (null == file ? 0 : zipSuffixLength(file.getPath()));
+ }
+
+ /** @return 0 if no zip/jar suffix or 4 otherwise */
+ public static int zipSuffixLength(String path) {
+ if ((null != path) && (4 < path.length())) {
+ String test = path.substring(path.length() - 4).toLowerCase();
+ if (".zip".equals(test) || ".jar".equals(test)) {
+ return 4;
+ }
+ }
+ return 0;
+ }
+
+ /** @return true if file path has a source suffix */
+ public static boolean hasSourceSuffix(File file) {
+ return ((null != file) && hasSourceSuffix(file.getPath()));
+ }
+
+ /** @return true if path ends with .java or .aj */
+ public static boolean hasSourceSuffix(String path) {
+ return ((null != path) && (0 != sourceSuffixLength(path)));
+ }
+
+ /**
+ * @return 0 if file has no source suffix or the length of the suffix otherwise
+ */
+ public static int sourceSuffixLength(File file) {
+ return (null == file ? 0 : sourceSuffixLength(file.getPath()));
+ }
+
+ /** @return 0 if no source suffix or the length of the suffix otherwise */
+ public static int sourceSuffixLength(String path) {
+ if (LangUtil.isEmpty(path)) {
+ return 0;
+ }
+
+ for (Iterator<String> iter = SOURCE_SUFFIXES.iterator(); iter.hasNext();) {
+ String suffix = iter.next();
+ if (path.endsWith(suffix) || path.toLowerCase().endsWith(suffix)) {
+ return suffix.length();
+ }
+ }
+ return 0;
+ }
+
+ /** @return true if this is a readable directory */
+ public static boolean canReadDir(File dir) {
+ return ((null != dir) && dir.canRead() && dir.isDirectory());
+ }
+
+ /** @return true if this is a readable file */
+ public static boolean canReadFile(File file) {
+ return ((null != file) && file.canRead() && file.isFile());
+ }
+
+ /** @return true if dir is a writable directory */
+ public static boolean canWriteDir(File dir) {
+ return ((null != dir) && dir.canWrite() && dir.isDirectory());
+ }
+
+ /** @return true if this is a writable file */
+ public static boolean canWriteFile(File file) {
+ return ((null != file) && file.canWrite() && file.isFile());
+ }
+
+ // /**
+ // * @throws IllegalArgumentException unless file is readable and not a
+ // * directory
+ // */
+ // public static void throwIaxUnlessCanReadFile(File file, String label) {
+ // if (!canReadFile(file)) {
+ // throw new IllegalArgumentException(label + " not readable file: " +
+ // file);
+ // }
+ // }
+
+ /**
+ * @throws IllegalArgumentException unless dir is a readable directory
+ */
+ public static void throwIaxUnlessCanReadDir(File dir, String label) {
+ if (!canReadDir(dir)) {
+ throw new IllegalArgumentException(label + " not readable dir: " + dir);
+ }
+ }
+
+ /**
+ * @throws IllegalArgumentException unless file is readable and not a directory
+ */
+ public static void throwIaxUnlessCanWriteFile(File file, String label) {
+ if (!canWriteFile(file)) {
+ throw new IllegalArgumentException(label + " not writable file: " + file);
+ }
+ }
+
+ /** @throws IllegalArgumentException unless dir is a readable directory */
+ public static void throwIaxUnlessCanWriteDir(File dir, String label) {
+ if (!canWriteDir(dir)) {
+ throw new IllegalArgumentException(label + " not writable dir: " + dir);
+ }
+ }
+
+ /** @return array same length as input, with String paths */
+ public static String[] getPaths(File[] files) {
+ if ((null == files) || (0 == files.length)) {
+ return new String[0];
+ }
+ String[] result = new String[files.length];
+ for (int i = 0; i < result.length; i++) {
+ if (null != files[i]) {
+ result[i] = files[i].getPath();
+ }
+ }
+ return result;
+ }
+
+ /** @return array same length as input, with String paths */
+ public static String[] getPaths(List<File> files) {
+ final int size = (null == files ? 0 : files.size());
+ if (0 == size) {
+ return new String[0];
+ }
+ String[] result = new String[size];
+ for (int i = 0; i < size; i++) {
+ File file = files.get(i);
+ if (null != file) {
+ result[i] = file.getPath();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Extract the name of a class from the path to its file. If the basedir is null, then the class is assumed to be in the default
+ * package unless the classFile has one of the top-level suffixes { com, org, java, javax } as a parent directory.
+ *
+ * @param basedir the File of the base directory (prefix of classFile)
+ * @param classFile the File of the class to extract the name for
+ * @throws IllegalArgumentException if classFile is null or does not end with ".class" or a non-null basedir is not a prefix of
+ * classFile
+ */
+ public static String fileToClassName(File basedir, File classFile) {
+ LangUtil.throwIaxIfNull(classFile, "classFile");
+ String classFilePath = normalizedPath(classFile);
+ if (!classFilePath.endsWith(".class")) {
+ String m = classFile + " does not end with .class";
+ throw new IllegalArgumentException(m);
+ }
+ classFilePath = classFilePath.substring(0, classFilePath.length() - 6);
+ if (null != basedir) {
+ String basePath = normalizedPath(basedir);
+ if (!classFilePath.startsWith(basePath)) {
+ String m = classFile + " does not start with " + basedir;
+ throw new IllegalArgumentException(m);
+ }
+ classFilePath = classFilePath.substring(basePath.length() + 1);
+ } else {
+ final String[] suffixes = new String[] { "com", "org", "java", "javax" };
+ boolean found = false;
+ for (int i = 0; !found && (i < suffixes.length); i++) {
+ int loc = classFilePath.indexOf(suffixes[i] + "/");
+ if ((0 == loc) || ((-1 != loc) && ('/' == classFilePath.charAt(loc - 1)))) {
+ classFilePath = classFilePath.substring(loc);
+ found = true;
+ }
+ }
+ if (!found) {
+ int loc = classFilePath.lastIndexOf("/");
+ if (-1 != loc) { // treat as default package
+ classFilePath = classFilePath.substring(loc + 1);
+ }
+ }
+ }
+ return classFilePath.replace('/', '.');
+ }
+
+ /**
+ * Normalize path for comparisons by rendering absolute, clipping basedir prefix, trimming and changing '\\' to '/'
+ *
+ * @param file the File with the path to normalize
+ * @param basedir the File for the prefix of the file to normalize - ignored if null
+ * @return "" if null or normalized path otherwise
+ * @throws IllegalArgumentException if basedir is not a prefix of file
+ */
+ public static String normalizedPath(File file, File basedir) {
+ String filePath = normalizedPath(file);
+ if (null != basedir) {
+ String basePath = normalizedPath(basedir);
+ if (filePath.startsWith(basePath)) {
+ filePath = filePath.substring(basePath.length());
+ if (filePath.startsWith("/")) {
+ filePath = filePath.substring(1);
+ }
+ }
+ }
+ return filePath;
+ }
+
+ /**
+ * Render a set of files to String as a path by getting absolute paths of each and delimiting with infix.
+ *
+ * @param files the File[] to flatten - may be null or empty
+ * @param infix the String delimiter internally between entries (if null, then use File.pathSeparator). (alias to
+ * <code>flatten(getAbsolutePaths(files), infix)</code>
+ * @return String with absolute paths to entries in order, delimited with infix
+ */
+ public static String flatten(File[] files, String infix) {
+ if (LangUtil.isEmpty(files)) {
+ return "";
+ }
+ return flatten(getPaths(files), infix);
+ }
+
+ /**
+ * Flatten File[] to String.
+ *
+ * @param files the File[] of paths to flatten - null ignored
+ * @param infix the String infix to use - null treated as File.pathSeparator
+ */
+ public static String flatten(String[] paths, String infix) {
+ if (null == infix) {
+ infix = File.pathSeparator;
+ }
+ StringBuffer result = new StringBuffer();
+ boolean first = true;
+ for (int i = 0; i < paths.length; i++) {
+ String path = paths[i];
+ if (null == path) {
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else {
+ result.append(infix);
+ }
+ result.append(path);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Normalize path for comparisons by rendering absolute trimming and changing '\\' to '/'
+ *
+ * @return "" if null or normalized path otherwise
+ */
+ public static String normalizedPath(File file) {
+ return (null == file ? "" : weakNormalize(file.getAbsolutePath()));
+ }
+
+ /**
+ * Weakly normalize path for comparisons by trimming and changing '\\' to '/'
+ */
+ public static String weakNormalize(String path) {
+ if (null != path) {
+ path = path.replace('\\', '/').trim();
+ }
+ return path;
+ }
+
+ /**
+ * Get best File for the first-readable path in input paths, treating entries prefixed "sp:" as system property keys. Safe to
+ * call in static initializers.
+ *
+ * @param paths the String[] of paths to check.
+ * @return null if not found, or valid File otherwise
+ */
+ public static File getBestFile(String[] paths) {
+ if (null == paths) {
+ return null;
+ }
+ File result = null;
+ for (int i = 0; (null == result) && (i < paths.length); i++) {
+ String path = paths[i];
+ if (null == path) {
+ continue;
+ }
+ if (path.startsWith("sp:")) {
+ try {
+ path = System.getProperty(path.substring(3));
+ } catch (Throwable t) {
+ path = null;
+ }
+ if (null == path) {
+ continue;
+ }
+ }
+ try {
+ File f = new File(path);
+ if (f.exists() && f.canRead()) {
+ result = FileUtil.getBestFile(f);
+ }
+ } catch (Throwable t) {
+ // swallow
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Render as best file, canonical or absolute.
+ *
+ * @param file the File to get the best File for (not null)
+ * @return File of the best-available path
+ * @throws IllegalArgumentException if file is null
+ */
+ public static File getBestFile(File file) {
+ LangUtil.throwIaxIfNull(file, "file");
+ if (file.exists()) {
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ return file.getAbsoluteFile();
+ }
+ } else {
+ return file;
+ }
+ }
+
+ /**
+ * Render as best path, canonical or absolute.
+ *
+ * @param file the File to get the path for (not null)
+ * @return String of the best-available path
+ * @throws IllegalArgumentException if file is null
+ */
+ public static String getBestPath(File file) {
+ LangUtil.throwIaxIfNull(file, "file");
+ if (file.exists()) {
+ try {
+ return file.getCanonicalPath();
+ } catch (IOException e) {
+ return file.getAbsolutePath();
+ }
+ } else {
+ return file.getPath();
+ }
+ }
+
+ /** @return array same length as input, with String absolute paths */
+ public static String[] getAbsolutePaths(File[] files) {
+ if ((null == files) || (0 == files.length)) {
+ return new String[0];
+ }
+ String[] result = new String[files.length];
+ for (int i = 0; i < result.length; i++) {
+ if (null != files[i]) {
+ result[i] = files[i].getAbsolutePath();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Recursively delete the contents of dir, but not the dir itself
+ *
+ * @return the total number of files deleted
+ */
+ public static int deleteContents(File dir) {
+ return deleteContents(dir, ALL);
+ }
+
+ /**
+ * Recursively delete some contents of dir, but not the dir itself. This deletes any subdirectory which is empty after its files
+ * are deleted.
+ *
+ * @return the total number of files deleted
+ */
+ public static int deleteContents(File dir, FileFilter filter) {
+ return deleteContents(dir, filter, true);
+ }
+
+ /**
+ * Recursively delete some contents of dir, but not the dir itself. If deleteEmptyDirs is true, this deletes any subdirectory
+ * which is empty after its files are deleted.
+ *
+ * @param dir the File directory (if a file, the the file is deleted)
+ * @return the total number of files deleted
+ */
+ public static int deleteContents(File dir, FileFilter filter,
+ boolean deleteEmptyDirs) {
+ if (null == dir) {
+ throw new IllegalArgumentException("null dir");
+ }
+ if ((!dir.exists()) || (!dir.canWrite())) {
+ return 0;
+ }
+ if (!dir.isDirectory()) {
+ dir.delete();
+ return 1;
+ }
+ String[] fromFiles = dir.list();
+ if (fromFiles == null) {
+ return 0;
+ }
+ int result = 0;
+ for (int i = 0; i < fromFiles.length; i++) {
+ String string = fromFiles[i];
+ File file = new File(dir, string);
+ if ((null == filter) || filter.accept(file)) {
+ if (file.isDirectory()) {
+ result += deleteContents(file, filter, deleteEmptyDirs);
+ String[] fileContent = file.list();
+ if (deleteEmptyDirs && fileContent != null
+ && 0 == fileContent.length) {
+ file.delete();
+ }
+ } else {
+ /* boolean ret = */
+ file.delete();
+ result++;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copy contents of fromDir into toDir
+ *
+ * @param fromDir must exist and be readable
+ * @param toDir must exist or be creatable and be writable
+ * @return the total number of files copied
+ */
+ public static int copyDir(File fromDir, File toDir) throws IOException {
+ return copyDir(fromDir, toDir, null, null);
+ }
+
+ /**
+ * Recursively copy files in fromDir (with any fromSuffix) to toDir, replacing fromSuffix with toSuffix if any. This silently
+ * ignores dirs and files that are not readable but throw IOException for directories that are not writable. This does not clean
+ * out the original contents of toDir. (subdirectories are not renamed per directory rules)
+ *
+ * @param fromSuffix select files with this suffix - select all if null or empty
+ * @param toSuffix replace fromSuffix with toSuffix in the destination file name - ignored if null or empty, appended to name if
+ * fromSuffix is null or empty
+ * @return the total number of files copied
+ */
+ public static int copyDir(File fromDir, File toDir, final String fromSuffix, String toSuffix) throws IOException {
+ return copyDir(fromDir, toDir, fromSuffix, toSuffix, (FileFilter) null);
+ }
+
+ // /**
+ // * Recursively copy files in fromDir (with any fromSuffix) to toDir,
+ // * replacing fromSuffix with toSuffix if any, and adding the destination
+ // * file to any collector. This silently ignores dirs and files that are
+ // not
+ // * readable but throw IOException for directories that are not writable.
+ // * This does not clean out the original contents of toDir. (subdirectories
+ // * are not renamed per directory rules) This calls any delegate
+ // * FilenameFilter to collect any selected file.
+ // *
+ // * @param fromSuffix select files with this suffix - select all if null or
+ // * empty
+ // * @param toSuffix replace fromSuffix with toSuffix in the destination
+ // file
+ // * name - ignored if null or empty, appended to name if
+ // * fromSuffix is null or empty
+ // * @param collector the List sink for destination files - ignored if null
+ // * @return the total number of files copied
+ // */
+ // public static int copyDir(File fromDir, File toDir, final String
+ // fromSuffix, final String toSuffix, final List collector)
+ // throws IOException {
+ // // int before = collector.size();
+ // if (null == collector) {
+ // return copyDir(fromDir, toDir, fromSuffix, toSuffix);
+ // } else {
+ // FileFilter collect = new FileFilter() {
+ // public boolean accept(File pathname) {
+ // return collector.add(pathname);
+ // }
+ // };
+ // return copyDir(fromDir, toDir, fromSuffix, toSuffix, collect);
+ // }
+ // }
+
+ /**
+ * Recursively copy files in fromDir (with any fromSuffix) to toDir, replacing fromSuffix with toSuffix if any. This silently
+ * ignores dirs and files that are not readable but throw IOException for directories that are not writable. This does not clean
+ * out the original contents of toDir. (subdirectories are not renamed per directory rules) This calls any delegate
+ * FilenameFilter to collect any selected file.
+ *
+ * @param fromSuffix select files with this suffix - select all if null or empty
+ * @param toSuffix replace fromSuffix with toSuffix in the destination file name - ignored if null or empty, appended to name if
+ * fromSuffix is null or empty
+ * @return the total number of files copied
+ */
+ public static int copyDir(File fromDir, File toDir, final String fromSuffix, final String toSuffix, final FileFilter delegate)
+ throws IOException {
+
+ if ((null == fromDir) || (!fromDir.canRead())) {
+ return 0;
+ }
+ final boolean haveSuffix = ((null != fromSuffix) && (0 < fromSuffix.length()));
+ final int slen = (!haveSuffix ? 0 : fromSuffix.length());
+
+ if (!toDir.exists()) {
+ toDir.mkdirs();
+ }
+ final String[] fromFiles;
+ if (!haveSuffix) {
+ fromFiles = fromDir.list();
+ } else {
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return (new File(dir, name).isDirectory() || (name.endsWith(fromSuffix)));
+ }
+ };
+ fromFiles = fromDir.list(filter);
+ }
+ int result = 0;
+ final int MAX = (null == fromFiles ? 0 : fromFiles.length);
+ for (int i = 0; i < MAX; i++) {
+ String filename = fromFiles[i];
+ File fromFile = new File(fromDir, filename);
+ if (fromFile.canRead()) {
+ if (fromFile.isDirectory()) {
+ result += copyDir(fromFile, new File(toDir, filename), fromSuffix, toSuffix, delegate);
+ } else if (fromFile.isFile()) {
+ if (haveSuffix) {
+ filename = filename.substring(0, filename.length() - slen);
+ }
+ if (null != toSuffix) {
+ filename = filename + toSuffix;
+ }
+ File targetFile = new File(toDir, filename);
+ if ((null == delegate) || delegate.accept(targetFile)) {
+ copyFile(fromFile, targetFile);
+ }
+ result++;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Recursively list files in srcDir.
+ *
+ * @return ArrayList with String paths of File under srcDir (relative to srcDir)
+ */
+ public static String[] listFiles(File srcDir) {
+ ArrayList<String> result = new ArrayList<String>();
+ if ((null != srcDir) && srcDir.canRead()) {
+ listFiles(srcDir, null, result);
+ }
+ return result.toArray(new String[0]);
+ }
+
+ public static final FileFilter aspectjSourceFileFilter = new FileFilter() {
+ public boolean accept(File pathname) {
+ String name = pathname.getName().toLowerCase();
+ return name.endsWith(".java") || name.endsWith(".aj");
+ }
+ };
+
+ /**
+ * Recursively list files in srcDir.
+ *
+ * @return ArrayList with String paths of File under srcDir (relative to srcDir)
+ */
+ public static File[] listFiles(File srcDir, FileFilter fileFilter) {
+ ArrayList<File> result = new ArrayList<File>();
+ if ((null != srcDir) && srcDir.canRead()) {
+ listFiles(srcDir, result, fileFilter);
+ }
+ return result.toArray(new File[result.size()]);
+ }
+
+ /**
+ * Recursively list .class files in specified directory
+ *
+ * @return List of File objects
+ */
+ public static List<File> listClassFiles(File dir) {
+ ArrayList<File> result = new ArrayList<File>();
+ if ((null != dir) && dir.canRead()) {
+ listClassFiles(dir, result);
+ }
+ return result;
+ }
+
+ /**
+ * Convert String[] paths to File[] as offset of base directory
+ *
+ * @param basedir the non-null File base directory for File to create with paths
+ * @param paths the String[] of paths to create
+ * @return File[] with same length as paths
+ */
+ public static File[] getBaseDirFiles(File basedir, String[] paths) {
+ return getBaseDirFiles(basedir, paths, (String[]) null);
+ }
+
+ /**
+ * Convert String[] paths to File[] as offset of base directory
+ *
+ * @param basedir the non-null File base directory for File to create with paths
+ * @param paths the String[] of paths to create
+ * @param suffixes the String[] of suffixes to limit sources to - ignored if null
+ * @return File[] with same length as paths
+ */
+ public static File[] getBaseDirFiles(File basedir, String[] paths, String[] suffixes) {
+ LangUtil.throwIaxIfNull(basedir, "basedir");
+ LangUtil.throwIaxIfNull(paths, "paths");
+ File[] result = null;
+ if (!LangUtil.isEmpty(suffixes)) {
+ ArrayList<File> list = new ArrayList<File>();
+ for (int i = 0; i < paths.length; i++) {
+ String path = paths[i];
+ for (int j = 0; j < suffixes.length; j++) {
+ if (path.endsWith(suffixes[j])) {
+ list.add(new File(basedir, paths[i]));
+ break;
+ }
+ }
+ }
+ result = list.toArray(new File[0]);
+ } else {
+ result = new File[paths.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = newFile(basedir, paths[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Create a new File, resolving paths ".." and "." specially.
+ *
+ * @param dir the File for the parent directory of the file
+ * @param path the path in the parent directory (filename only?)
+ * @return File for the new file.
+ */
+ private static File newFile(File dir, String path) {
+ if (".".equals(path)) {
+ return dir;
+ } else if ("..".equals(path)) {
+ File parentDir = dir.getParentFile();
+ if (null != parentDir) {
+ return parentDir;
+ } else {
+ return new File(dir, "..");
+ }
+ } else {
+ return new File(dir, path);
+ }
+ }
+
+ /**
+ * Copy files from source dir into destination directory, creating any needed directories. This differs from copyDir in not
+ * being recursive; each input with the source dir creates a full path. However, if the source is a directory, it is copied as
+ * such.
+ *
+ * @param srcDir an existing, readable directory containing relativePaths files
+ * @param relativePaths a set of paths relative to srcDir to readable File to copy
+ * @param destDir an existing, writable directory to copy files to
+ * @throws IllegalArgumentException if input invalid, IOException if operations fail
+ */
+ public static File[] copyFiles(File srcDir, String[] relativePaths, File destDir) throws IllegalArgumentException, IOException {
+ final String[] paths = relativePaths;
+ throwIaxUnlessCanReadDir(srcDir, "srcDir");
+ throwIaxUnlessCanWriteDir(destDir, "destDir");
+ LangUtil.throwIaxIfNull(paths, "relativePaths");
+ File[] result = new File[paths.length];
+ for (int i = 0; i < paths.length; i++) {
+ String path = paths[i];
+ LangUtil.throwIaxIfNull(path, "relativePaths-entry");
+ File src = newFile(srcDir, paths[i]);
+ File dest = newFile(destDir, path);
+ File destParent = dest.getParentFile();
+ if (!destParent.exists()) {
+ destParent.mkdirs();
+ }
+ LangUtil.throwIaxIfFalse(canWriteDir(destParent), "dest-entry-parent");
+ copyFile(src, dest); // both file-dir and dir-dir copies
+ result[i] = dest;
+ }
+ return result;
+ }
+
+ /**
+ * Copy fromFile to toFile, handling file-file, dir-dir, and file-dir copies.
+ *
+ * @param fromFile the File path of the file or directory to copy - must be readable
+ * @param toFile the File path of the target file or directory - must be writable (will be created if it does not exist)
+ */
+ public static void copyFile(File fromFile, File toFile) throws IOException {
+ LangUtil.throwIaxIfNull(fromFile, "fromFile");
+ LangUtil.throwIaxIfNull(toFile, "toFile");
+ LangUtil.throwIaxIfFalse(!toFile.equals(fromFile), "same file");
+ if (toFile.isDirectory()) { // existing directory
+ throwIaxUnlessCanWriteDir(toFile, "toFile");
+ if (fromFile.isFile()) { // file-dir
+ File targFile = new File(toFile, fromFile.getName());
+ copyValidFiles(fromFile, targFile);
+ } else if (fromFile.isDirectory()) { // dir-dir
+ copyDir(fromFile, toFile);
+ } else {
+ LangUtil.throwIaxIfFalse(false, "not dir or file: " + fromFile);
+ }
+ } else if (toFile.isFile()) { // target file exists
+ if (fromFile.isDirectory()) {
+ LangUtil.throwIaxIfFalse(false, "can't copy to file dir: " + fromFile);
+ }
+ copyValidFiles(fromFile, toFile); // file-file
+ } else { // target file is a non-existent path -- could be file or dir
+ /* File toFileParent = */ensureParentWritable(toFile);
+ if (fromFile.isFile()) {
+ copyValidFiles(fromFile, toFile);
+ } else if (fromFile.isDirectory()) {
+ toFile.mkdirs();
+ throwIaxUnlessCanWriteDir(toFile, "toFile");
+ copyDir(fromFile, toFile);
+ } else {
+ LangUtil.throwIaxIfFalse(false, "not dir or file: " + fromFile);
+ }
+ }
+ }
+
+ /**
+ * Ensure that the parent directory to path can be written. If the path has a null parent, DEFAULT_PARENT is tested. If the path
+ * parent does not exist, this tries to create it.
+ *
+ * @param path the File path whose parent should be writable
+ * @return the File path of the writable parent directory
+ * @throws IllegalArgumentException if parent cannot be written or path is null.
+ */
+ public static File ensureParentWritable(File path) {
+ LangUtil.throwIaxIfNull(path, "path");
+ File pathParent = path.getParentFile();
+ if (null == pathParent) {
+ pathParent = DEFAULT_PARENT;
+ }
+ if (!pathParent.canWrite()) {
+ pathParent.mkdirs();
+ }
+ throwIaxUnlessCanWriteDir(pathParent, "pathParent");
+ return pathParent;
+ }
+
+ /**
+ * Copy file to file.
+ *
+ * @param fromFile the File to copy (readable, non-null file)
+ * @param toFile the File to copy to (non-null, parent dir exists)
+ * @throws IOException
+ */
+ public static void copyValidFiles(File fromFile, File toFile) throws IOException {
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ try {
+ in = new FileInputStream(fromFile);
+ out = new FileOutputStream(toFile);
+ copyStream(in, out);
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ }
+ }
+
+ /** do line-based copying */
+ @SuppressWarnings("deprecation")
+ public static void copyStream(DataInputStream in, PrintStream out) throws IOException {
+ LangUtil.throwIaxIfNull(in, "in");
+ LangUtil.throwIaxIfNull(in, "out");
+ String s;
+ while (null != (s = in.readLine())) {
+ out.println(s);
+ }
+ }
+
+ public static void copyStream(InputStream in, OutputStream out) throws IOException {
+ final int MAX = 4096;
+ byte[] buf = new byte[MAX];
+ for (int bytesRead = in.read(buf, 0, MAX); bytesRead != -1; bytesRead = in.read(buf, 0, MAX)) {
+ out.write(buf, 0, bytesRead);
+ }
+ }
+
+ public static void copyStream(Reader in, Writer out) throws IOException {
+ final int MAX = 4096;
+ char[] buf = new char[MAX];
+ for (int bytesRead = in.read(buf, 0, MAX); bytesRead != -1; bytesRead = in.read(buf, 0, MAX)) {
+ out.write(buf, 0, bytesRead);
+ }
+ }
+
+ /**
+ * Make a new child directory of parent
+ *
+ * @param parent a File for the parent (writable)
+ * @param child a prefix for the child directory
+ * @return a File dir that exists with parentDir as the parent file or null
+ */
+ public static File makeNewChildDir(File parent, String child) {
+ if (null == parent || !parent.canWrite() || !parent.isDirectory()) {
+ throw new IllegalArgumentException("bad parent: " + parent);
+ } else if (null == child) {
+ child = "makeNewChildDir";
+ } else if (!isValidFileName(child)) {
+ throw new IllegalArgumentException("bad child: " + child);
+ }
+ File result = new File(parent, child);
+ int safety = 1000;
+ for (String suffix = FileUtil.randomFileString(); ((0 < --safety) && result.exists()); suffix = FileUtil.randomFileString()) {
+ result = new File(parent, child + suffix);
+ }
+ if (result.exists()) {
+ System.err.println("exhausted files for child dir in " + parent);
+ return null;
+ }
+ return ((result.mkdirs() && result.exists()) ? result : null);
+ }
+
+ /**
+ * Make a new temporary directory in the same directory that the system uses for temporary files, or if that files, in the
+ * current directory.
+ *
+ * @param name the preferred (simple) name of the directory - may be null.
+ * @return File of an existing new temp dir, or null if unable to create
+ */
+ public static File getTempDir(String name) {
+ if (null == name) {
+ name = "FileUtil_getTempDir";
+ } else if (!isValidFileName(name)) {
+ throw new IllegalArgumentException(" invalid: " + name);
+ }
+ File result = null;
+ File tempFile = null;
+ try {
+ tempFile = File.createTempFile("ignoreMe", ".txt");
+ File tempParent = tempFile.getParentFile();
+ result = makeNewChildDir(tempParent, name);
+ } catch (IOException t) {
+ result = makeNewChildDir(new File("."), name);
+ } finally {
+ if (null != tempFile) {
+ tempFile.delete();
+ }
+ }
+ return result;
+ }
+
+ public static URL[] getFileURLs(File[] files) {
+ if ((null == files) || (0 == files.length)) {
+ return new URL[0];
+ }
+ URL[] result = new URL[files.length]; // XXX dangerous non-copy...
+ for (int i = 0; i < result.length; i++) {
+ result[i] = getFileURL(files[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Get URL for a File. This appends "/" for directories. prints errors to System.err
+ *
+ * @param file the File to convert to URL (not null)
+ */
+ @SuppressWarnings("deprecation")
+ public static URL getFileURL(File file) {
+ LangUtil.throwIaxIfNull(file, "file");
+ URL result = null;
+ try {
+ result = file.toURL();// TODO AV - was toURI.toURL that does not
+ // works on Java 1.3
+ if (null != result) {
+ return result;
+ }
+ String url = "file:" + file.getAbsolutePath().replace('\\', '/');
+ result = new URL(url + (file.isDirectory() ? "/" : ""));
+ } catch (MalformedURLException e) {
+ String m = "Util.makeURL(\"" + file.getPath() + "\" MUE " + e.getMessage();
+ System.err.println(m);
+ }
+ return result;
+ }
+
+ /**
+ * Write contents to file, returning null on success or error message otherwise. This tries to make any necessary parent
+ * directories first.
+ *
+ * @param file the File to write (not null)
+ * @param contents the String to write (use "" if null)
+ * @return String null on no error, error otherwise
+ */
+ public static String writeAsString(File file, String contents) {
+ LangUtil.throwIaxIfNull(file, "file");
+ if (null == contents) {
+ contents = "";
+ }
+ Writer out = null;
+ try {
+ File parentDir = file.getParentFile();
+ if (!parentDir.exists() && !parentDir.mkdirs()) {
+ return "unable to make parent dir for " + file;
+ }
+ Reader in = new StringReader(contents);
+ out = new FileWriter(file);
+ FileUtil.copyStream(in, out);
+ return null;
+ } catch (IOException e) {
+ return LangUtil.unqualifiedClassName(e) + " writing " + file + ": " + e.getMessage();
+ } finally {
+ if (null != out) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ } // ignored
+ }
+ }
+ }
+
+ /**
+ * Reads a boolean array with our encoding
+ */
+ public static boolean[] readBooleanArray(DataInputStream s) throws IOException {
+ int len = s.readInt();
+ boolean[] ret = new boolean[len];
+ for (int i = 0; i < len; i++) {
+ ret[i] = s.readBoolean();
+ }
+ return ret;
+ }
+
+ /**
+ * Writes a boolean array with our encoding
+ */
+ public static void writeBooleanArray(boolean[] a, DataOutputStream s) throws IOException {
+ int len = a.length;
+ s.writeInt(len);
+ for (int i = 0; i < len; i++) {
+ s.writeBoolean(a[i]);
+ }
+ }
+
+ /**
+ * Reads an int array with our encoding
+ */
+ public static int[] readIntArray(DataInputStream s) throws IOException {
+ int len = s.readInt();
+ int[] ret = new int[len];
+ for (int i = 0; i < len; i++) {
+ ret[i] = s.readInt();
+ }
+ return ret;
+ }
+
+ /**
+ * Writes an int array with our encoding
+ */
+ public static void writeIntArray(int[] a, DataOutputStream s) throws IOException {
+ int len = a.length;
+ s.writeInt(len);
+ for (int i = 0; i < len; i++) {
+ s.writeInt(a[i]);
+ }
+ }
+
+ /**
+ * Reads an int array with our encoding
+ */
+ public static String[] readStringArray(DataInputStream s) throws IOException {
+ int len = s.readInt();
+ String[] ret = new String[len];
+ for (int i = 0; i < len; i++) {
+ ret[i] = s.readUTF();
+ }
+ return ret;
+ }
+
+ /**
+ * Writes an int array with our encoding
+ */
+ public static void writeStringArray(String[] a, DataOutputStream s) throws IOException {
+ if (a == null) {
+ s.writeInt(0);
+ return;
+ }
+ int len = a.length;
+ s.writeInt(len);
+ for (int i = 0; i < len; i++) {
+ s.writeUTF(a[i]);
+ }
+ }
+
+ /**
+ * Returns the contents of this file as a String
+ */
+ public static String readAsString(File file) throws IOException {
+ BufferedReader r = new BufferedReader(new FileReader(file));
+ StringBuffer b = new StringBuffer();
+ while (true) {
+ int ch = r.read();
+ if (ch == -1) {
+ break;
+ }
+ b.append((char) ch);
+ }
+ r.close();
+ return b.toString();
+ }
+
+ // /**
+ // * Returns the contents of this stream as a String
+ // */
+ // public static String readAsString(InputStream in) throws IOException {
+ // BufferedReader r = new BufferedReader(new InputStreamReader(in));
+ // StringBuffer b = new StringBuffer();
+ // while (true) {
+ // int ch = r.read();
+ // if (ch == -1)
+ // break;
+ // b.append((char) ch);
+ // }
+ // in.close();
+ // r.close();
+ // return b.toString();
+ // }
+
+ /**
+ * Returns the contents of this file as a byte[]
+ */
+ public static byte[] readAsByteArray(File file) throws IOException {
+ FileInputStream in = new FileInputStream(file);
+ byte[] ret = FileUtil.readAsByteArray(in);
+ in.close();
+ return ret;
+ }
+
+ /**
+ * Reads this input stream and returns contents as a byte[]
+ */
+ public static byte[] readAsByteArray(InputStream inStream) throws IOException {
+ int size = 1024;
+ byte[] ba = new byte[size];
+ int readSoFar = 0;
+
+ while (true) {
+ int nRead = inStream.read(ba, readSoFar, size - readSoFar);
+ if (nRead == -1) {
+ break;
+ }
+ readSoFar += nRead;
+ if (readSoFar == size) {
+ int newSize = size * 2;
+ byte[] newBa = new byte[newSize];
+ System.arraycopy(ba, 0, newBa, 0, size);
+ ba = newBa;
+ size = newSize;
+ }
+ }
+
+ byte[] newBa = new byte[readSoFar];
+ System.arraycopy(ba, 0, newBa, 0, readSoFar);
+ return newBa;
+ }
+
+ final static String FILECHARS = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ /** @return semi-random String of length 6 usable as filename suffix */
+ static String randomFileString() {
+ final double FILECHARS_length = FILECHARS.length();
+ final int LEN = 6;
+ final char[] result = new char[LEN];
+ int index = (int) (Math.random() * 6d);
+ for (int i = 0; i < LEN; i++) {
+ if (index >= LEN) {
+ index = 0;
+ }
+ result[index++] = FILECHARS.charAt((int) (Math.random() * FILECHARS_length));
+ }
+ return new String(result);
+ }
+
+ public static InputStream getStreamFromZip(String zipFile, String name) {
+ try {
+ ZipFile zf = new ZipFile(zipFile);
+ try {
+ ZipEntry entry = zf.getEntry(name);
+ return zf.getInputStream(entry);
+ } finally {
+ // ??? is it safe not to close this zf.close();
+ }
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+ //
+ // public static void extractJar(String zipFile, String outDir) throws
+ // IOException {
+ // ZipInputStream zs = new ZipInputStream(new FileInputStream(zipFile));
+ // ZipEntry entry;
+ // while ((entry = zs.getNextEntry()) != null) {
+ // if (entry.isDirectory())
+ // continue;
+ // byte[] in = readAsByteArray(zs);
+ //
+ // File outFile = new File(outDir + "/" + entry.getName());
+ // // if (!outFile.getParentFile().exists())
+ // // System.err.println("parent: " + outFile.getParentFile());
+ // // System.err.println("parent: " + outFile.getParentFile());
+ // outFile.getParentFile().mkdirs();
+ // FileOutputStream os = new FileOutputStream(outFile);
+ // os.write(in);
+ // os.close();
+ // zs.closeEntry();
+ // }
+ // zs.close();
+ // }
+
+ /**
+ * Do line-based search for literal text in source files, returning file:line where found.
+ *
+ * @param sought the String text to seek in the file
+ * @param sources the List of String paths to the source files
+ * @param listAll if false, only list first match in file
+ * @param errorSink the PrintStream to print any errors to (one per line) (use null to silently ignore errors)
+ * @return List of String of the form file:line for each found entry (never null, might be empty)
+ */
+ // OPTIMIZE only used by tests? move it out
+ public static List<String> lineSeek(String sought, List<String> sources, boolean listAll, PrintStream errorSink) {
+ if (LangUtil.isEmpty(sought) || LangUtil.isEmpty(sources)) {
+ return Collections.emptyList();
+ }
+ ArrayList<String> result = new ArrayList<String>();
+ for (Iterator<String> iter = sources.iterator(); iter.hasNext();) {
+ String path = iter.next();
+ String error = lineSeek(sought, path, listAll, result);
+ if ((null != error) && (null != errorSink)) {
+ errorSink.println(error);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Do line-based search for literal text in source file, returning line where found as a String in the form
+ * {sourcePath}:line:column submitted to the collecting parameter sink. Any error is rendered to String and returned as the
+ * result.
+ *
+ * @param sought the String text to seek in the file
+ * @param sources the List of String paths to the source files
+ * @param listAll if false, only list first match in file
+ * @param List sink the List for String entries of the form {sourcePath}:line:column
+ * @return String error if any, or add String entries to sink
+ */
+ public static String lineSeek(String sought, String sourcePath, boolean listAll, ArrayList<String> sink) {
+ if (LangUtil.isEmpty(sought) || LangUtil.isEmpty(sourcePath)) {
+ return "nothing sought";
+ }
+ if (LangUtil.isEmpty(sourcePath)) {
+ return "no sourcePath";
+ }
+ final File file = new File(sourcePath);
+ if (!file.canRead() || !file.isFile()) {
+ return "sourcePath not a readable file";
+ }
+ int lineNum = 0;
+ FileReader fin = null;
+ try {
+ fin = new FileReader(file);
+ BufferedReader reader = new BufferedReader(fin);
+ String line;
+ while (null != (line = reader.readLine())) {
+ lineNum++;
+ int loc = line.indexOf(sought);
+ if (-1 != loc) {
+ sink.add(sourcePath + ":" + lineNum + ":" + loc);
+ if (!listAll) {
+ break;
+ }
+ }
+ }
+ } catch (IOException e) {
+ return LangUtil.unqualifiedClassName(e) + " reading " + sourcePath + ":" + lineNum;
+ } finally {
+ try {
+ if (null != fin) {
+ fin.close();
+ }
+ } catch (IOException e) {
+ } // ignore
+ }
+ return null;
+ }
+
+ public static BufferedOutputStream makeOutputStream(File file) throws FileNotFoundException {
+ File parent = file.getParentFile();
+ if (parent != null) {
+ parent.mkdirs();
+ }
+ return new BufferedOutputStream(new FileOutputStream(file));
+ }
+
+ /**
+ * Sleep until after the last last-modified stamp from the files.
+ *
+ * @param files the File[] of files to inspect for last modified times (this ignores null or empty files array and null or
+ * non-existing components of files array)
+ * @return true if succeeded without 100 interrupts
+ */
+ public static boolean sleepPastFinalModifiedTime(File[] files) {
+ if ((null == files) || (0 == files.length)) {
+ return true;
+ }
+ long delayUntil = System.currentTimeMillis();
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ if ((null == file) || !file.exists()) {
+ continue;
+ }
+ long nextModTime = file.lastModified();
+ if (nextModTime > delayUntil) {
+ delayUntil = nextModTime;
+ }
+ }
+ return LangUtil.sleepUntil(++delayUntil);
+ }
+
+ private static void listClassFiles(final File baseDir, ArrayList<File> result) {
+ File[] files = baseDir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File f = files[i];
+ if (f.isDirectory()) {
+ listClassFiles(f, result);
+ } else {
+ if (f.getName().endsWith(".class")) {
+ result.add(f);
+ }
+ }
+ }
+ }
+
+ private static void listFiles(final File baseDir, ArrayList<File> result, FileFilter filter) {
+ File[] files = baseDir.listFiles();
+ // hack https://bugs.eclipse.org/bugs/show_bug.cgi?id=48650
+ final boolean skipCVS = (!PERMIT_CVS && (filter == aspectjSourceFileFilter));
+ for (int i = 0; i < files.length; i++) {
+ File f = files[i];
+ if (f.isDirectory()) {
+ if (skipCVS) {
+ String name = f.getName().toLowerCase();
+ if ("cvs".equals(name) || "sccs".equals(name)) {
+ continue;
+ }
+ }
+ listFiles(f, result, filter);
+ } else {
+ if (filter.accept(f)) {
+ result.add(f);
+ }
+ }
+ }
+ }
+
+ /** @return true if input is not null and contains no path separator */
+ private static boolean isValidFileName(String input) {
+ return ((null != input) && (-1 == input.indexOf(File.pathSeparator)));
+ }
+
+ private static void listFiles(final File baseDir, String dir, ArrayList<String> result) {
+ final String dirPrefix = (null == dir ? "" : dir + "/");
+ final File dirFile = (null == dir ? baseDir : new File(baseDir.getPath() + "/" + dir));
+ final String[] files = dirFile.list();
+ for (int i = 0; i < files.length; i++) {
+ File f = new File(dirFile, files[i]);
+ String path = dirPrefix + files[i];
+ if (f.isDirectory()) {
+ listFiles(baseDir, path, result);
+ } else {
+ result.add(path);
+ }
+ }
+ }
+
+ private FileUtil() {
+ }
+
+ public static List<String> makeClasspath(URL[] urls) {
+ List<String> ret = new LinkedList<String>();
+ if (urls != null) {
+ for (int i = 0; i < urls.length; i++) {
+ ret.add(toPathString(urls[i]));
+ }
+ }
+ return ret;
+ }
+
+ private static String toPathString(URL url) {
+ try {
+ return url.toURI().getPath();
+ } catch (URISyntaxException e) {
+ System.err.println("Warning!! Malformed URL may cause problems: "+url); // TODO: Better way to report this?
+ // In this case it was likely not using properly escaped
+ // characters so we just use the 'bad' method that doesn't decode
+ // special chars
+ return url.getPath();
+ }
+ }
+
+ /**
+ * A pipe when run reads from an input stream to an output stream, optionally sleeping between reads.
+ *
+ * @see #copyStream(InputStream, OutputStream)
+ */
+ public static class Pipe implements Runnable {
+ private final InputStream in;
+ private final OutputStream out;
+ private final long sleep;
+ private ByteArrayOutputStream snoop;
+ private long totalWritten;
+ private Throwable thrown;
+ private boolean halt;
+ /**
+ * Seem to be unable to detect erroroneous closing of System.out...
+ */
+ private final boolean closeInput;
+ private final boolean closeOutput;
+
+ /**
+ * If true, then continue processing stream until no characters are returned when halting.
+ */
+ private boolean finishStream;
+
+ private boolean done; // true after completing() completes
+
+ /**
+ * alias for <code>Pipe(in, out, 100l, false, false)</code>
+ *
+ * @param in the InputStream source to read
+ * @param out the OutputStream sink to write
+ */
+ Pipe(InputStream in, OutputStream out) {
+ this(in, out, 100l, false, false);
+ }
+
+ /**
+ * @param in the InputStream source to read
+ * @param out the OutputStream sink to write
+ * @param tryClosingStreams if true, then try closing both streams when done
+ * @param sleep milliseconds to delay between reads (pinned to 0..1 minute)
+ */
+ Pipe(InputStream in, OutputStream out, long sleep, boolean closeInput, boolean closeOutput) {
+ LangUtil.throwIaxIfNull(in, "in");
+ LangUtil.throwIaxIfNull(out, "out");
+ this.in = in;
+ this.out = out;
+ this.closeInput = closeInput;
+ this.closeOutput = closeOutput;
+ this.sleep = Math.min(0l, Math.max(60l * 1000l, sleep));
+ }
+
+ public void setSnoop(ByteArrayOutputStream snoop) {
+ this.snoop = snoop;
+ }
+
+ /**
+ * Run the pipe. This halts on the first Throwable thrown or when a read returns -1 (for end-of-file) or on demand.
+ */
+ public void run() {
+ totalWritten = 0;
+ if (halt) {
+ return;
+ }
+ try {
+ final int MAX = 4096;
+ byte[] buf = new byte[MAX];
+ // TODO this blocks, hanging the harness
+ int count = in.read(buf, 0, MAX);
+ ByteArrayOutputStream mySnoop;
+ while ((halt && finishStream && (0 < count)) || (!halt && (-1 != count))) {
+ out.write(buf, 0, count);
+ mySnoop = snoop;
+ if (null != mySnoop) {
+ mySnoop.write(buf, 0, count);
+ }
+ totalWritten += count;
+ if (halt && !finishStream) {
+ break;
+ }
+ if (!halt && (0 < sleep)) {
+ Thread.sleep(sleep);
+ }
+ if (halt && !finishStream) {
+ break;
+ }
+ count = in.read(buf, 0, MAX);
+ }
+ } catch (Throwable e) {
+ thrown = e;
+ } finally {
+ halt = true;
+ if (closeInput) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (closeOutput) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ done = true;
+ completing(totalWritten, thrown);
+ }
+
+ }
+
+ /**
+ * Tell the pipe to halt the next time it gains control.
+ *
+ * @param wait if true, this waits synchronously until pipe is done
+ * @param finishStream if true, then continue until a read from the input stream returns no bytes, then halt.
+ * @return true if <code>run()</code> will return the next time it gains control
+ */
+ public boolean halt(boolean wait, boolean finishStream) {
+ if (!halt) {
+ halt = true;
+ }
+ if (wait) {
+ while (!done) {
+ synchronized (this) {
+ notifyAll();
+ }
+ if (!done) {
+ try {
+ Thread.sleep(5l);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ }
+ }
+ return halt;
+ }
+
+ /** @return the total number of bytes written */
+ public long totalWritten() {
+ return totalWritten;
+ }
+
+ /** @return any exception thrown when reading/writing */
+ public Throwable getThrown() {
+ return thrown;
+ }
+
+ /**
+ * This is called when the pipe is completing. This implementation does nothing. Subclasses implement this to get notice.
+ * Note that halt(true, true) might or might not have completed before this method is called.
+ */
+ protected void completing(long totalWritten, Throwable thrown) {
+ }
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * 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.util;
+
+/**
+ * This class implements boolean that include a "maybe"
+ */
+public abstract class FuzzyBoolean {
+ public abstract boolean alwaysTrue();
+ public abstract boolean alwaysFalse();
+ public abstract boolean maybeTrue();
+ public abstract boolean maybeFalse();
+
+ public abstract FuzzyBoolean and(FuzzyBoolean other);
+ public abstract FuzzyBoolean or(FuzzyBoolean other);
+ public abstract FuzzyBoolean not();
+
+ private static class YesFuzzyBoolean extends FuzzyBoolean {
+ public boolean alwaysFalse() {
+ return false;
+ }
+
+ public boolean alwaysTrue() {
+ return true;
+ }
+
+ public boolean maybeFalse() {
+ return false;
+ }
+
+ public boolean maybeTrue() {
+ return true;
+ }
+
+ public FuzzyBoolean and(FuzzyBoolean other) {
+ return other;
+ }
+
+ public FuzzyBoolean not() {
+ return FuzzyBoolean.NO;
+ }
+
+ public FuzzyBoolean or(FuzzyBoolean other) {
+ return this;
+ }
+
+ public String toString() {
+ return "YES";
+ }
+ }
+ private static class NoFuzzyBoolean extends FuzzyBoolean {
+ public boolean alwaysFalse() {
+ return true;
+ }
+
+ public boolean alwaysTrue() {
+ return false;
+ }
+
+
+ public boolean maybeFalse() {
+ return true;
+ }
+
+ public boolean maybeTrue() {
+ return false;
+ }
+
+ public FuzzyBoolean and(FuzzyBoolean other) {
+ return this;
+ }
+
+ public FuzzyBoolean not() {
+ return FuzzyBoolean.YES;
+ }
+
+ public FuzzyBoolean or(FuzzyBoolean other) {
+ return other;
+ }
+
+ public String toString() {
+ return "NO";
+ }
+ }
+ private static class NeverFuzzyBoolean extends FuzzyBoolean {
+ public boolean alwaysFalse() {
+ return true;
+ }
+
+ public boolean alwaysTrue() {
+ return false;
+ }
+
+
+ public boolean maybeFalse() {
+ return true;
+ }
+
+ public boolean maybeTrue() {
+ return false;
+ }
+
+ public FuzzyBoolean and(FuzzyBoolean other) {
+ return this;
+ }
+
+ public FuzzyBoolean not() {
+ return this;
+ }
+
+ public FuzzyBoolean or(FuzzyBoolean other) {
+ return this;
+ }
+
+ public String toString() {
+ return "NEVER";
+ }
+ }
+
+ private static class MaybeFuzzyBoolean extends FuzzyBoolean {
+ public boolean alwaysFalse() {
+ return false;
+ }
+
+ public boolean alwaysTrue() {
+ return false;
+ }
+
+
+ public boolean maybeFalse() {
+ return true;
+ }
+
+ public boolean maybeTrue() {
+ return true;
+ }
+
+ public FuzzyBoolean and(FuzzyBoolean other) {
+ return other.alwaysFalse() ? other : this;
+ }
+
+ public FuzzyBoolean not() {
+ return this;
+ }
+
+ public FuzzyBoolean or(FuzzyBoolean other) {
+ return other.alwaysTrue() ? other : this;
+ }
+
+ public String toString() {
+ return "MAYBE";
+ }
+ }
+
+ public static final FuzzyBoolean YES = new YesFuzzyBoolean();
+ public static final FuzzyBoolean NO = new NoFuzzyBoolean();
+ public static final FuzzyBoolean MAYBE = new MaybeFuzzyBoolean();
+ public static final FuzzyBoolean NEVER = new NeverFuzzyBoolean();
+
+ public static final FuzzyBoolean fromBoolean(boolean b) {
+ return b ? YES : NO;
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * 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
+ *
+ * ******************************************************************/
+package org.aspectj.util;
+
+/**
+ * Encapsulate generic signature parsing
+ *
+ * @author Adrian Colyer
+ * @author Andy Clement
+ */
+public class GenericSignature {
+
+ /**
+ * structure holding a parsed class signature
+ */
+ public static class ClassSignature {
+ public FormalTypeParameter[] formalTypeParameters = FormalTypeParameter.NONE;
+ public ClassTypeSignature superclassSignature;
+ public ClassTypeSignature[] superInterfaceSignatures = ClassTypeSignature.NONE;
+
+ public String toString() {
+ StringBuffer ret = new StringBuffer();
+ ret.append(formalTypeParameters.toString());
+ ret.append(superclassSignature.toString());
+ for (int i = 0; i < superInterfaceSignatures.length; i++) {
+ ret.append(superInterfaceSignatures[i].toString());
+ }
+ return ret.toString();
+ }
+ }
+
+ public static class MethodTypeSignature {
+ public FormalTypeParameter[] formalTypeParameters = new FormalTypeParameter[0];
+ public TypeSignature[] parameters = new TypeSignature[0];
+ public TypeSignature returnType;
+ public FieldTypeSignature[] throwsSignatures = new FieldTypeSignature[0];
+
+ public MethodTypeSignature(FormalTypeParameter[] aFormalParameterList, TypeSignature[] aParameterList,
+ TypeSignature aReturnType, FieldTypeSignature[] aThrowsSignatureList) {
+ this.formalTypeParameters = aFormalParameterList;
+ this.parameters = aParameterList;
+ this.returnType = aReturnType;
+ this.throwsSignatures = aThrowsSignatureList;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ if (formalTypeParameters.length > 0) {
+ sb.append("<");
+ for (int i = 0; i < formalTypeParameters.length; i++) {
+ sb.append(formalTypeParameters[i].toString());
+ }
+ sb.append(">");
+ }
+ sb.append("(");
+ for (int i = 0; i < parameters.length; i++) {
+ sb.append(parameters[i].toString());
+ }
+ sb.append(")");
+ sb.append(returnType.toString());
+ for (int i = 0; i < throwsSignatures.length; i++) {
+ sb.append("^");
+ sb.append(throwsSignatures[i].toString());
+ }
+ return sb.toString();
+ }
+ }
+
+ /**
+ * structure capturing a FormalTypeParameter from the Signature grammar
+ */
+ public static class FormalTypeParameter {
+ public static final FormalTypeParameter[] NONE = new FormalTypeParameter[0];
+ public String identifier;
+ public FieldTypeSignature classBound;
+ public FieldTypeSignature[] interfaceBounds;
+
+ public String toString() {
+ StringBuffer ret = new StringBuffer();
+ ret.append("T");
+ ret.append(identifier);
+ ret.append(":");
+ ret.append(classBound.toString());
+ for (int i = 0; i < interfaceBounds.length; i++) {
+ ret.append(":");
+ ret.append(interfaceBounds[i].toString());
+ }
+ return ret.toString();
+ }
+ }
+
+ public static abstract class TypeSignature {
+ public boolean isBaseType() {
+ return false;
+ }
+ }
+
+ public static class BaseTypeSignature extends TypeSignature {
+ private final String sig;
+
+ public BaseTypeSignature(String aPrimitiveType) {
+ sig = aPrimitiveType;
+ }
+
+ public boolean isBaseType() {
+ return true;
+ }
+
+ public String toString() {
+ return sig;
+ }
+ }
+
+ public static abstract class FieldTypeSignature extends TypeSignature {
+ public boolean isClassTypeSignature() {
+ return false;
+ }
+
+ public boolean isTypeVariableSignature() {
+ return false;
+ }
+
+ public boolean isArrayTypeSignature() {
+ return false;
+ }
+ }
+
+ public static class ClassTypeSignature extends FieldTypeSignature {
+
+ public static final ClassTypeSignature[] NONE = new ClassTypeSignature[0];
+ public String classSignature;
+ public SimpleClassTypeSignature outerType;
+ public SimpleClassTypeSignature[] nestedTypes;
+
+ public ClassTypeSignature(String sig, String identifier) {
+ this.classSignature = sig;
+ this.outerType = new SimpleClassTypeSignature(identifier);
+ this.nestedTypes = new SimpleClassTypeSignature[0];
+ }
+
+ public ClassTypeSignature(String sig, SimpleClassTypeSignature outer, SimpleClassTypeSignature[] inners) {
+ this.classSignature = sig;
+ this.outerType = outer;
+ this.nestedTypes = inners;
+ }
+
+ public boolean isClassTypeSignature() {
+ return true;
+ }
+
+ public String toString() {
+ return classSignature;
+ }
+ }
+
+ public static class TypeVariableSignature extends FieldTypeSignature {
+ public String typeVariableName;
+
+ public TypeVariableSignature(String typeVarToken) {
+ this.typeVariableName = typeVarToken.substring(1);
+ }
+
+ public boolean isTypeVariableSignature() {
+ return true;
+ }
+
+ public String toString() {
+ return "T" + typeVariableName + ";";
+ }
+ }
+
+ public static class ArrayTypeSignature extends FieldTypeSignature {
+ public TypeSignature typeSig;
+
+ public ArrayTypeSignature(TypeSignature aTypeSig) {
+ this.typeSig = aTypeSig;
+ }
+
+ public boolean isArrayTypeSignature() {
+ return true;
+ }
+
+ public String toString() {
+ return "[" + typeSig.toString();
+ }
+ }
+
+ public static class SimpleClassTypeSignature {
+ public String identifier;
+ public TypeArgument[] typeArguments;
+
+ public SimpleClassTypeSignature(String identifier) {
+ this.identifier = identifier;
+ this.typeArguments = new TypeArgument[0];
+ }
+
+ public SimpleClassTypeSignature(String identifier, TypeArgument[] args) {
+ this.identifier = identifier;
+ this.typeArguments = args;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(identifier);
+ if (typeArguments.length > 0) {
+ sb.append("<");
+ for (int i = 0; i < typeArguments.length; i++) {
+ sb.append(typeArguments[i].toString());
+ }
+ sb.append(">");
+ }
+ return sb.toString();
+ }
+ }
+
+ public static class TypeArgument {
+ public boolean isWildcard = false;
+ public boolean isPlus = false;
+ public boolean isMinus = false;
+ public FieldTypeSignature signature; // null if isWildcard
+
+ public TypeArgument() {
+ isWildcard = true;
+ }
+
+ public TypeArgument(boolean plus, boolean minus, FieldTypeSignature aSig) {
+ this.isPlus = plus;
+ this.isMinus = minus;
+ this.signature = aSig;
+ }
+
+ public String toString() {
+ if (isWildcard)
+ return "*";
+ StringBuffer sb = new StringBuffer();
+ if (isPlus)
+ sb.append("+");
+ if (isMinus)
+ sb.append("-");
+ sb.append(signature.toString());
+ return sb.toString();
+ }
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2005-2008 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
+ *
+ * ******************************************************************/
+package org.aspectj.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.aspectj.util.GenericSignature.ArrayTypeSignature;
+import org.aspectj.util.GenericSignature.BaseTypeSignature;
+import org.aspectj.util.GenericSignature.ClassTypeSignature;
+import org.aspectj.util.GenericSignature.FieldTypeSignature;
+import org.aspectj.util.GenericSignature.FormalTypeParameter;
+import org.aspectj.util.GenericSignature.MethodTypeSignature;
+import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
+import org.aspectj.util.GenericSignature.TypeArgument;
+import org.aspectj.util.GenericSignature.TypeSignature;
+import org.aspectj.util.GenericSignature.TypeVariableSignature;
+
+/**
+ * Parses the generic signature attribute as defined in the JVM spec.
+ *
+ * @author Adrian Colyer
+ * @author Andy Clement
+ */
+public class GenericSignatureParser {
+
+ private String inputString;
+ private String[] tokenStream; // for parse in flight
+ private int tokenIndex = 0;
+
+ /**
+ * AMC. Parse the signature string interpreting it as a ClassSignature according to the grammar defined in Section 4.4.4 of the
+ * JVM specification.
+ */
+ public GenericSignature.ClassSignature parseAsClassSignature(String sig) {
+ this.inputString = sig;
+ tokenStream = tokenize(sig);
+ tokenIndex = 0;
+ GenericSignature.ClassSignature classSig = new GenericSignature.ClassSignature();
+ // FormalTypeParameters-opt
+ if (maybeEat("<")) {
+ List<FormalTypeParameter> formalTypeParametersList = new ArrayList<FormalTypeParameter>();
+ do {
+ formalTypeParametersList.add(parseFormalTypeParameter());
+ } while (!maybeEat(">"));
+ classSig.formalTypeParameters = new FormalTypeParameter[formalTypeParametersList.size()];
+ formalTypeParametersList.toArray(classSig.formalTypeParameters);
+ }
+ classSig.superclassSignature = parseClassTypeSignature();
+ List<ClassTypeSignature> superIntSigs = new ArrayList<ClassTypeSignature>();
+ while (tokenIndex < tokenStream.length) {
+ superIntSigs.add(parseClassTypeSignature());
+ }
+ classSig.superInterfaceSignatures = new ClassTypeSignature[superIntSigs.size()];
+ superIntSigs.toArray(classSig.superInterfaceSignatures);
+ return classSig;
+ }
+
+ /**
+ * AMC. Parse the signature string interpreting it as a MethodTypeSignature according to the grammar defined in Section 4.4.4 of
+ * the JVM specification.
+ */
+ public MethodTypeSignature parseAsMethodSignature(String sig) {
+ this.inputString = sig;
+ tokenStream = tokenize(sig);
+ tokenIndex = 0;
+ FormalTypeParameter[] formals = new FormalTypeParameter[0];
+ TypeSignature returnType = null;
+ // FormalTypeParameters-opt
+ if (maybeEat("<")) {
+ List<FormalTypeParameter> formalTypeParametersList = new ArrayList<FormalTypeParameter>();
+ do {
+ formalTypeParametersList.add(parseFormalTypeParameter());
+ } while (!maybeEat(">"));
+ formals = new FormalTypeParameter[formalTypeParametersList.size()];
+ formalTypeParametersList.toArray(formals);
+ }
+ // Parameters
+ eat("(");
+ List<TypeSignature> paramList = new ArrayList<TypeSignature>();
+ while (!maybeEat(")")) {
+ FieldTypeSignature fsig = parseFieldTypeSignature(true);
+ if (fsig != null) {
+ paramList.add(fsig);
+ } else {
+ paramList.add(new GenericSignature.BaseTypeSignature(eatIdentifier()));
+ }
+ }
+ TypeSignature[] params = new TypeSignature[paramList.size()];
+ paramList.toArray(params);
+ // return type
+ returnType = parseFieldTypeSignature(true);
+ if (returnType == null)
+ returnType = new GenericSignature.BaseTypeSignature(eatIdentifier());
+ // throws
+ List<FieldTypeSignature> throwsList = new ArrayList<FieldTypeSignature>();
+ while (maybeEat("^")) {
+ FieldTypeSignature fsig = parseFieldTypeSignature(false);
+ throwsList.add(fsig);
+ }
+ FieldTypeSignature[] throwsSigs = new FieldTypeSignature[throwsList.size()];
+ throwsList.toArray(throwsSigs);
+ return new GenericSignature.MethodTypeSignature(formals, params, returnType, throwsSigs);
+ }
+
+ /**
+ * AMC. Parse the signature string interpreting it as a FieldTypeSignature according to the grammar defined in Section 4.4.4 of
+ * the JVM specification.
+ */
+ public FieldTypeSignature parseAsFieldSignature(String sig) {
+ this.inputString = sig;
+ tokenStream = tokenize(sig);
+ tokenIndex = 0;
+ return parseFieldTypeSignature(false);
+ }
+
+ private FormalTypeParameter parseFormalTypeParameter() {
+ FormalTypeParameter ftp = new FormalTypeParameter();
+ // Identifier
+ ftp.identifier = eatIdentifier();
+ // ClassBound
+ eat(":");
+ ftp.classBound = parseFieldTypeSignature(true);
+ if (ftp.classBound == null) {
+ ftp.classBound = new ClassTypeSignature("Ljava/lang/Object;", "Ljava/lang/Object");
+ }
+ // Optional InterfaceBounds
+ List<FieldTypeSignature> optionalBounds = new ArrayList<FieldTypeSignature>();
+ while (maybeEat(":")) {
+ optionalBounds.add(parseFieldTypeSignature(false));
+ }
+ ftp.interfaceBounds = new FieldTypeSignature[optionalBounds.size()];
+ optionalBounds.toArray(ftp.interfaceBounds);
+ return ftp;
+ }
+
+ private FieldTypeSignature parseFieldTypeSignature(boolean isOptional) {
+ if (isOptional) {
+ // anything other than 'L', 'T' or '[' and we're out of here
+ if (!tokenStream[tokenIndex].startsWith("L") && !tokenStream[tokenIndex].startsWith("T")
+ && !tokenStream[tokenIndex].startsWith("[")) {
+ return null;
+ }
+ }
+ if (maybeEat("[")) {
+ return parseArrayTypeSignature();
+ } else if (tokenStream[tokenIndex].startsWith("L")) {
+ return parseClassTypeSignature();
+ } else if (tokenStream[tokenIndex].startsWith("T")) {
+ return parseTypeVariableSignature();
+ } else {
+ throw new IllegalStateException("Expecting [,L, or T, but found " + tokenStream[tokenIndex] + " while unpacking "
+ + inputString);
+ }
+ }
+
+ private ArrayTypeSignature parseArrayTypeSignature() {
+ // opening [ already eaten
+ FieldTypeSignature fieldType = parseFieldTypeSignature(true);
+ if (fieldType != null) {
+ return new ArrayTypeSignature(fieldType);
+ } else {
+ // must be BaseType array
+ return new ArrayTypeSignature(new BaseTypeSignature(eatIdentifier()));
+ }
+ }
+
+ // L PackageSpecifier* SimpleClassTypeSignature ClassTypeSignature* ;
+ private ClassTypeSignature parseClassTypeSignature() {
+ SimpleClassTypeSignature outerType = null;
+ SimpleClassTypeSignature[] nestedTypes = new SimpleClassTypeSignature[0];
+ StringBuffer ret = new StringBuffer();
+ String identifier = eatIdentifier();
+ ret.append(identifier);
+ while (maybeEat("/")) {
+ ret.append("/"); // dont forget this...
+ ret.append(eatIdentifier());
+ }
+ identifier = ret.toString();
+ // now we have either a "." indicating the start of a nested type,
+ // or a "<" indication type arguments, or ";" and we are done.
+ while (!maybeEat(";")) {
+ if (tokenStream[tokenIndex].equals(".")) {
+ // outer type completed
+ outerType = new SimpleClassTypeSignature(identifier);
+ nestedTypes = parseNestedTypesHelper(ret);
+ } else if (tokenStream[tokenIndex].equals("<")) {
+ ret.append("<");
+ TypeArgument[] tArgs = maybeParseTypeArguments();
+ for (int i = 0; i < tArgs.length; i++) {
+ ret.append(tArgs[i].toString());
+ }
+ ret.append(">");
+ outerType = new SimpleClassTypeSignature(identifier, tArgs);
+ nestedTypes = parseNestedTypesHelper(ret);
+ } else {
+ throw new IllegalStateException("Expecting .,<, or ;, but found " + tokenStream[tokenIndex] + " while unpacking "
+ + inputString);
+ }
+ }
+ ret.append(";");
+ if (outerType == null)
+ outerType = new SimpleClassTypeSignature(ret.toString());
+ return new ClassTypeSignature(ret.toString(), outerType, nestedTypes);
+ }
+
+ /**
+ * Helper method to digest nested types, slightly more complex than necessary to cope with some android related
+ * incorrect classes (see bug 406167)
+ */
+ private SimpleClassTypeSignature[] parseNestedTypesHelper(StringBuffer ret) {
+ boolean brokenSignature = false;
+ SimpleClassTypeSignature[] nestedTypes;
+ List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
+ while (maybeEat(".")) {
+ ret.append(".");
+ SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
+ if (tokenStream[tokenIndex].equals("/")) {
+ if (!brokenSignature) {
+ System.err.println("[See bug 406167] Bad class file signature encountered, nested types appear package qualified, ignoring those incorrect pieces. Signature: "+inputString);
+ }
+ brokenSignature = true;
+ // hit something like: Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;
+ // and we are looking at the '/' after the com
+ tokenIndex++; // pointing at the next identifier
+ while (tokenStream[tokenIndex+1].equals("/")) {
+ tokenIndex+=2; // jump over an 'identifier' '/' pair
+ }
+ // now tokenIndex is the final bit of the name (which we'll treat as the inner type name)
+ sig = parseSimpleClassTypeSignature();
+ }
+ ret.append(sig.toString());
+ nestedTypeList.add(sig);
+ };
+ nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
+ nestedTypeList.toArray(nestedTypes);
+ return nestedTypes;
+ }
+
+ private SimpleClassTypeSignature parseSimpleClassTypeSignature() {
+ String identifier = eatIdentifier();
+ TypeArgument[] tArgs = maybeParseTypeArguments();
+ if (tArgs != null) {
+ return new SimpleClassTypeSignature(identifier, tArgs);
+ } else {
+ return new SimpleClassTypeSignature(identifier);
+ }
+ }
+
+ private TypeArgument parseTypeArgument() {
+ boolean isPlus = false;
+ boolean isMinus = false;
+ if (maybeEat("*")) {
+ return new TypeArgument();
+ } else if (maybeEat("+")) {
+ isPlus = true;
+ } else if (maybeEat("-")) {
+ isMinus = true;
+ }
+ FieldTypeSignature sig = parseFieldTypeSignature(false);
+ return new TypeArgument(isPlus, isMinus, sig);
+ }
+
+ private TypeArgument[] maybeParseTypeArguments() {
+ if (maybeEat("<")) {
+ List<TypeArgument> typeArgs = new ArrayList<TypeArgument>();
+ do {
+ TypeArgument arg = parseTypeArgument();
+ typeArgs.add(arg);
+ } while (!maybeEat(">"));
+ TypeArgument[] tArgs = new TypeArgument[typeArgs.size()];
+ typeArgs.toArray(tArgs);
+ return tArgs;
+ } else {
+ return null;
+ }
+ }
+
+ private TypeVariableSignature parseTypeVariableSignature() {
+ TypeVariableSignature tv = new TypeVariableSignature(eatIdentifier());
+ eat(";");
+ return tv;
+ }
+
+ private boolean maybeEat(String token) {
+ if (tokenStream.length <= tokenIndex)
+ return false;
+ if (tokenStream[tokenIndex].equals(token)) {
+ tokenIndex++;
+ return true;
+ }
+ return false;
+ }
+
+ private void eat(String token) {
+ if (!tokenStream[tokenIndex].equals(token)) {
+ throw new IllegalStateException("Expecting " + token + " but found " + tokenStream[tokenIndex] + " while unpacking "
+ + inputString);
+ }
+ tokenIndex++;
+ }
+
+ private String eatIdentifier() {
+ return tokenStream[tokenIndex++];
+ }
+
+ /**
+ * non-private for test visibility Splits a string containing a generic signature into tokens for consumption by the parser.
+ */
+ public String[] tokenize(String signatureString) {
+ char[] chars = signatureString.toCharArray();
+ int index = 0;
+ List<String> tokens = new ArrayList<String>();
+ StringBuffer identifier = new StringBuffer();
+ boolean inParens = false;
+ boolean inArray = false;
+ boolean couldSeePrimitive = false;
+ do {
+ switch (chars[index]) {
+ case '<':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add("<");
+ break;
+ case '>':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add(">");
+ break;
+ case ':':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add(":");
+ break;
+ case '/':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add("/");
+ couldSeePrimitive = false;
+ break;
+ case ';':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add(";");
+ couldSeePrimitive = true;
+ inArray = false;
+ break;
+ case '^':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ tokens.add("^");
+ break;
+ case '+':
+ tokens.add("+");
+ break;
+ case '-':
+ tokens.add("-");
+ break;
+ case '*':
+ tokens.add("*");
+ break;
+ case '.':
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ identifier = new StringBuffer();
+ couldSeePrimitive = false;
+ tokens.add(".");
+ break;
+ case '(':
+ tokens.add("(");
+ inParens = true;
+ couldSeePrimitive = true;
+ break;
+ case ')':
+ tokens.add(")");
+ inParens = false;
+ break;
+ case '[':
+ tokens.add("[");
+ couldSeePrimitive = true;
+ inArray = true;
+ break;
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'V':
+ case 'Z':
+ if ((inParens || inArray) && couldSeePrimitive && identifier.length() == 0) {
+ tokens.add(new String("" + chars[index]));
+ } else {
+ identifier.append(chars[index]);
+ }
+ inArray = false;
+ break;
+ case 'L':
+ couldSeePrimitive = false;
+ // deliberate fall-through
+ default:
+ identifier.append(chars[index]);
+ }
+ } while ((++index) < chars.length);
+ if (identifier.length() > 0)
+ tokens.add(identifier.toString());
+ String[] tokenArray = new String[tokens.size()];
+ tokens.toArray(tokenArray);
+ return tokenArray;
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2008 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:
+ * Andy Clement
+ * ******************************************************************/
+package org.aspectj.util;
+
+/**
+ * Abstraction of a structure model
+ *
+ * @author Andy Clement
+ */
+public interface IStructureModel {
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 2018 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
+ * ******************************************************************/
+package org.aspectj.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.security.PrivilegedActionException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ *
+ */
+public class LangUtil {
+
+ public static final String EOL;
+
+ public static final String JRT_FS = "jrt-fs.jar";
+
+ private static double vmVersion;
+
+ /**
+ * @return the vm version (1.1, 1.2, 1.3, 1.4, etc)
+ */
+ public static String getVmVersionString() {
+ return Double.toString(vmVersion);
+ }
+
+ public static double getVmVersion() {
+ return vmVersion;
+ }
+
+ static {
+ StringWriter buf = new StringWriter();
+ PrintWriter writer = new PrintWriter(buf);
+ writer.println("");
+ String eol = "\n";
+ try {
+ buf.close();
+ StringBuffer sb = buf.getBuffer();
+ if (sb != null) {
+ eol = buf.toString();
+ }
+ } catch (Throwable t) {
+ }
+ EOL = eol;
+ }
+
+ static {
+ // http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
+ // http://openjdk.java.net/jeps/223 "New Version-String Scheme"
+ try {
+ String vm = System.getProperty("java.version"); // JLS 20.18.7
+ if (vm == null) {
+ vm = System.getProperty("java.runtime.version");
+ }
+ if (vm == null) {
+ vm = System.getProperty("java.vm.version");
+ }
+ if (vm == null) {
+ new RuntimeException(
+ "System properties appear damaged, cannot find: java.version/java.runtime.version/java.vm.version")
+ .printStackTrace(System.err);
+ vmVersion = 1.5;
+ } else {
+ // Version: [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
+ // Care about the first set of digits and second set if first digit is 1
+ try {
+ List<Integer> numbers = getFirstNumbers(vm);
+ if (numbers.get(0) == 1) {
+ // Old school for 1.0 > 1.8
+ vmVersion = numbers.get(0)+(numbers.get(1)/10d);
+ } else {
+ // numbers.get(0) is the major version (9 and above)
+ // Note here the number will be 9 (or 10), *not* 1.9 or 1.10
+ vmVersion = numbers.get(0);
+ }
+ } catch (Throwable t) {
+ // Give up
+ vmVersion = 1.5;
+ }
+ }
+ } catch (Throwable t) {
+ new RuntimeException(
+ "System properties appear damaged, cannot find: java.version/java.runtime.version/java.vm.version", t)
+ .printStackTrace(System.err);
+ vmVersion = 1.5;
+ }
+ }
+
+ private static List<Integer> getFirstNumbers(String vm) {
+ List<Integer> result = new ArrayList<Integer>();
+ StringTokenizer st = new StringTokenizer(vm,".-_");
+ try {
+ result.add(Integer.parseInt(st.nextToken()));
+ result.add(Integer.parseInt(st.nextToken()));
+ } catch (Exception e) {
+ // NoSuchElementException if no more tokens
+ // NumberFormatException if not a number
+ }
+ return result;
+ }
+
+ public static boolean is13VMOrGreater() {
+ return 1.3 <= vmVersion;
+ }
+
+ public static boolean is14VMOrGreater() {
+ return 1.4 <= vmVersion;
+ }
+
+ public static boolean is15VMOrGreater() {
+ return 1.5 <= vmVersion;
+ }
+
+ public static boolean is16VMOrGreater() {
+ return 1.6 <= vmVersion;
+ }
+
+ public static boolean is17VMOrGreater() {
+ return 1.7 <= vmVersion;
+ }
+
+ public static boolean is18VMOrGreater() {
+ return 1.8 <= vmVersion;
+ }
+
+ public static boolean is19VMOrGreater() {
+ return 9 <= vmVersion;
+ }
+
+ public static boolean is10VMOrGreater() {
+ return 10 <= vmVersion;
+ }
+
+ public static boolean is11VMOrGreater() {
+ return 11 <= vmVersion;
+ }
+
+ /**
+ * Shorthand for "if null, throw IllegalArgumentException"
+ *
+ * @throws IllegalArgumentException "null {name}" if o is null
+ */
+ public static final void throwIaxIfNull(final Object o, final String name) {
+ if (null == o) {
+ String message = "null " + (null == name ? "input" : name);
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Shorthand for "if not null or not assignable, throw IllegalArgumentException"
+ *
+ * @param c the Class to check - use null to ignore type check
+ * @throws IllegalArgumentException "null {name}" if o is null
+ */
+ public static final void throwIaxIfNotAssignable(final Object ra[], final Class<?> c, final String name) {
+ throwIaxIfNull(ra, name);
+ String label = (null == name ? "input" : name);
+ for (int i = 0; i < ra.length; i++) {
+ if (null == ra[i]) {
+ String m = " null " + label + "[" + i + "]";
+ throw new IllegalArgumentException(m);
+ } else if (null != c) {
+ Class<?> actualClass = ra[i].getClass();
+ if (!c.isAssignableFrom(actualClass)) {
+ String message = label + " not assignable to " + c.getName();
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+ }
+
+ /**
+ * Shorthand for "if not null or not assignable, throw IllegalArgumentException"
+ *
+ * @throws IllegalArgumentException "null {name}" if o is null
+ */
+ public static final void throwIaxIfNotAssignable(final Object o, final Class<?> c, final String name) {
+ throwIaxIfNull(o, name);
+ if (null != c) {
+ Class<?> actualClass = o.getClass();
+ if (!c.isAssignableFrom(actualClass)) {
+ String message = name + " not assignable to " + c.getName();
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+
+ // /**
+ // * Shorthand for
+ // "if any not null or not assignable, throw IllegalArgumentException"
+ // * @throws IllegalArgumentException "{name} is not assignable to {c}"
+ // */
+ // public static final void throwIaxIfNotAllAssignable(final Collection
+ // collection,
+ // final Class c, final String name) {
+ // throwIaxIfNull(collection, name);
+ // if (null != c) {
+ // for (Iterator iter = collection.iterator(); iter.hasNext();) {
+ // throwIaxIfNotAssignable(iter.next(), c, name);
+ //
+ // }
+ // }
+ // }
+ /**
+ * Shorthand for "if false, throw IllegalArgumentException"
+ *
+ * @throws IllegalArgumentException "{message}" if test is false
+ */
+ public static final void throwIaxIfFalse(final boolean test, final String message) {
+ if (!test) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ // /** @return ((null == s) || (0 == s.trim().length())); */
+ // public static boolean isEmptyTrimmed(String s) {
+ // return ((null == s) || (0 == s.length())
+ // || (0 == s.trim().length()));
+ // }
+
+ /** @return ((null == s) || (0 == s.length())); */
+ public static boolean isEmpty(String s) {
+ return ((null == s) || (0 == s.length()));
+ }
+
+ /** @return ((null == ra) || (0 == ra.length)) */
+ public static boolean isEmpty(Object[] ra) {
+ return ((null == ra) || (0 == ra.length));
+ }
+
+ /** @return ((null == ra) || (0 == ra.length)) */
+ public static boolean isEmpty(byte[] ra) {
+ return ((null == ra) || (0 == ra.length));
+ }
+
+ /** @return ((null == collection) || (0 == collection.size())) */
+ public static boolean isEmpty(Collection<?> collection) {
+ return ((null == collection) || (0 == collection.size()));
+ }
+
+ /** @return ((null == map) || (0 == map.size())) */
+ public static boolean isEmpty(Map<?,?> map) {
+ return ((null == map) || (0 == map.size()));
+ }
+
+ /**
+ * Splits <code>text</code> at whitespace.
+ *
+ * @param text <code>String</code> to split.
+ */
+ public static String[] split(String text) {
+ return strings(text).toArray(new String[0]);
+ }
+
+ /**
+ * Splits <code>input</code> at commas, trimming any white space.
+ *
+ * @param input <code>String</code> to split.
+ * @return List of String of elements.
+ */
+ public static List<String> commaSplit(String input) {
+ return anySplit(input, ",");
+ }
+
+ /**
+ * Split string as classpath, delimited at File.pathSeparator. Entries are not trimmed, but empty entries are ignored.
+ *
+ * @param classpath the String to split - may be null or empty
+ * @return String[] of classpath entries
+ */
+ public static String[] splitClasspath(String classpath) {
+ if (LangUtil.isEmpty(classpath)) {
+ return new String[0];
+ }
+ StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator);
+ ArrayList<String> result = new ArrayList<String>(st.countTokens());
+ while (st.hasMoreTokens()) {
+ String entry = st.nextToken();
+ if (!LangUtil.isEmpty(entry)) {
+ result.add(entry);
+ }
+ }
+ return result.toArray(new String[0]);
+ }
+
+ /**
+ * Get System property as boolean, but use default value where the system property is not set.
+ *
+ * @return true if value is set to true, false otherwise
+ */
+ public static boolean getBoolean(String propertyName, boolean defaultValue) {
+ if (null != propertyName) {
+ try {
+ String value = System.getProperty(propertyName);
+ if (null != value) {
+ return Boolean.valueOf(value).booleanValue();
+ }
+ } catch (Throwable t) {
+ // default below
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Splits <code>input</code>, removing delimiter and trimming any white space. Returns an empty collection if the input is null.
+ * If delimiter is null or empty or if the input contains no delimiters, the input itself is returned after trimming white
+ * space.
+ *
+ * @param input <code>String</code> to split.
+ * @param delim <code>String</code> separators for input.
+ * @return List of String of elements.
+ */
+ public static List<String> anySplit(String input, String delim) {
+ if (null == input) {
+ return Collections.emptyList();
+ }
+ ArrayList<String> result = new ArrayList<String>();
+
+ if (LangUtil.isEmpty(delim) || (-1 == input.indexOf(delim))) {
+ result.add(input.trim());
+ } else {
+ StringTokenizer st = new StringTokenizer(input, delim);
+ while (st.hasMoreTokens()) {
+ result.add(st.nextToken().trim());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Splits strings into a <code>List</code> using a <code>StringTokenizer</code>.
+ *
+ * @param text <code>String</code> to split.
+ */
+ public static List<String> strings(String text) {
+ if (LangUtil.isEmpty(text)) {
+ return Collections.emptyList();
+ }
+ List<String> strings = new ArrayList<String>();
+ StringTokenizer tok = new StringTokenizer(text);
+ while (tok.hasMoreTokens()) {
+ strings.add(tok.nextToken());
+ }
+ return strings;
+ }
+
+ /** @return a non-null unmodifiable List */
+ public static <T> List<T> safeList(List<T> list) {
+ return (null == list ? Collections.<T>emptyList() : Collections.unmodifiableList(list));
+ }
+
+ // /**
+ // * 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]);
+ // }
+ //
+ // /**
+ // * 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]);
+ // }
+
+ /**
+ * copy non-null two-dimensional String[][]
+ *
+ * @see extractOptions(String[], String[][])
+ */
+ public static String[][] copyStrings(String[][] in) {
+ String[][] out = new String[in.length][];
+ for (int i = 0; i < out.length; i++) {
+ out[i] = new String[in[i].length];
+ System.arraycopy(in[i], 0, out[i], 0, out[i].length);
+ }
+ return out;
+ }
+
+ /**
+ * Extract options and arguments to input option list, returning remainder. The input options will be nullified if not found.
+ * e.g.,
+ *
+ * <pre>
+ * String[] options = new String[][] { new String[] { "-verbose" }, new String[] { "-classpath", null } };
+ * String[] args = extractOptions(args, options);
+ * boolean verbose = null != options[0][0];
+ * boolean classpath = options[1][1];
+ * </pre>
+ *
+ * @param args the String[] input options
+ * @param options the String[][]options to find in the input args - not null for each String[] component the first subcomponent
+ * is the option itself, and there is one String subcomponent for each additional argument.
+ * @return String[] of args remaining after extracting options to extracted
+ */
+ public static String[] extractOptions(String[] args, String[][] options) {
+ if (LangUtil.isEmpty(args) || LangUtil.isEmpty(options)) {
+ return args;
+ }
+ BitSet foundSet = new BitSet();
+ String[] result = new String[args.length];
+ int resultIndex = 0;
+ for (int j = 0; j < args.length; j++) {
+ boolean found = false;
+ for (int i = 0; !found && (i < options.length); i++) {
+ String[] option = options[i];
+ LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(option), "options");
+ String sought = option[0];
+ found = sought.equals(args[j]);
+ if (found) {
+ foundSet.set(i);
+ int doMore = option.length - 1;
+ if (0 < doMore) {
+ final int MAX = j + doMore;
+ if (MAX >= args.length) {
+ String s = "expecting " + doMore + " args after ";
+ throw new IllegalArgumentException(s + args[j]);
+ }
+ for (int k = 1; k < option.length; k++) {
+ option[k] = args[++j];
+ }
+ }
+ }
+ }
+ if (!found) {
+ result[resultIndex++] = args[j];
+ }
+ }
+
+ // unset any not found
+ for (int i = 0; i < options.length; i++) {
+ if (!foundSet.get(i)) {
+ options[i][0] = null;
+ }
+ }
+ // fixup remainder
+ if (resultIndex < args.length) {
+ String[] temp = new String[resultIndex];
+ System.arraycopy(result, 0, temp, 0, resultIndex);
+ args = temp;
+ }
+
+ return args;
+ }
+
+ //
+ // /**
+ // * Extract options and arguments to input parameter list, returning
+ // remainder.
+ // * @param args the String[] input options
+ // * @param validOptions the String[] options to find in the input args -
+ // not null
+ // * @param optionArgs the int[] number of arguments for each option in
+ // validOptions
+ // * (if null, then no arguments for any option)
+ // * @param extracted the List for the matched options
+ // * @return String[] of args remaining after extracting options to
+ // extracted
+ // */
+ // public static String[] extractOptions(String[] args, String[]
+ // validOptions,
+ // int[] optionArgs, List extracted) {
+ // if (LangUtil.isEmpty(args)
+ // || LangUtil.isEmpty(validOptions) ) {
+ // return args;
+ // }
+ // if (null != optionArgs) {
+ // if (optionArgs.length != validOptions.length) {
+ // throw new IllegalArgumentException("args must match options");
+ // }
+ // }
+ // String[] result = new String[args.length];
+ // int resultIndex = 0;
+ // for (int j = 0; j < args.length; j++) {
+ // boolean found = false;
+ // for (int i = 0; !found && (i < validOptions.length); i++) {
+ // String sought = validOptions[i];
+ // int doMore = (null == optionArgs ? 0 : optionArgs[i]);
+ // if (LangUtil.isEmpty(sought)) {
+ // continue;
+ // }
+ // found = sought.equals(args[j]);
+ // if (found) {
+ // if (null != extracted) {
+ // extracted.add(sought);
+ // }
+ // if (0 < doMore) {
+ // final int MAX = j + doMore;
+ // if (MAX >= args.length) {
+ // String s = "expecting " + doMore + " args after ";
+ // throw new IllegalArgumentException(s + args[j]);
+ // }
+ // if (null != extracted) {
+ // while (j < MAX) {
+ // extracted.add(args[++j]);
+ // }
+ // } else {
+ // j = MAX;
+ // }
+ // }
+ // break;
+ // }
+ // }
+ // if (!found) {
+ // result[resultIndex++] = args[j];
+ // }
+ // }
+ // if (resultIndex < args.length) {
+ // String[] temp = new String[resultIndex];
+ // System.arraycopy(result, 0, temp, 0, resultIndex);
+ // args = temp;
+ // }
+ // return args;
+ // }
+
+ // /** @return String[] of entries in validOptions found in args */
+ // public static String[] selectOptions(String[] args, String[]
+ // validOptions) {
+ // if (LangUtil.isEmpty(args) || LangUtil.isEmpty(validOptions)) {
+ // return new String[0];
+ // }
+ // ArrayList result = new ArrayList();
+ // for (int i = 0; i < validOptions.length; i++) {
+ // String sought = validOptions[i];
+ // if (LangUtil.isEmpty(sought)) {
+ // continue;
+ // }
+ // for (int j = 0; j < args.length; j++) {
+ // if (sought.equals(args[j])) {
+ // result.add(sought);
+ // break;
+ // }
+ // }
+ // }
+ // return (String[]) result.toArray(new String[0]);
+ // }
+
+ // /** @return String[] of entries in validOptions found in args */
+ // public static String[] selectOptions(List args, String[] validOptions) {
+ // if (LangUtil.isEmpty(args) || LangUtil.isEmpty(validOptions)) {
+ // return new String[0];
+ // }
+ // ArrayList result = new ArrayList();
+ // for (int i = 0; i < validOptions.length; i++) {
+ // String sought = validOptions[i];
+ // if (LangUtil.isEmpty(sought)) {
+ // continue;
+ // }
+ // for (Iterator iter = args.iterator(); iter.hasNext();) {
+ // String arg = (String) iter.next();
+ // if (sought.equals(arg)) {
+ // result.add(sought);
+ // break;
+ // }
+ // }
+ // }
+ // return (String[]) result.toArray(new String[0]);
+ // }
+
+ // /**
+ // * 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 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] = (String[]) 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;
+ // }
+
+ // /**
+ // * 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;
+ // }
+
+ /**
+ * Convert arrays safely. The number of elements in the result will be 1 smaller for each element that is null or not
+ * assignable. This will use sink if it has exactly the right size. The result will always have the same component type as sink.
+ *
+ * @return an array with the same component type as sink containing any assignable elements in source (in the same order).
+ * @throws IllegalArgumentException if either is null
+ */
+ public static Object[] safeCopy(Object[] source, Object[] sink) {
+ final Class<?> sinkType = (null == sink ? Object.class : sink.getClass().getComponentType());
+ final int sourceLength = (null == source ? 0 : source.length);
+ final int sinkLength = (null == sink ? 0 : sink.length);
+
+ final int resultSize;
+ ArrayList<Object> result = null;
+ if (0 == sourceLength) {
+ resultSize = 0;
+ } else {
+ result = new ArrayList<Object>(sourceLength);
+ for (int i = 0; i < sourceLength; i++) {
+ if ((null != source[i]) && (sinkType.isAssignableFrom(source[i].getClass()))) {
+ result.add(source[i]);
+ }
+ }
+ resultSize = result.size();
+ }
+ if (resultSize != sinkLength) {
+ sink = (Object[]) Array.newInstance(sinkType, result.size());
+ }
+ if (0 < resultSize) {
+ sink = result.toArray(sink);
+ }
+ return sink;
+ }
+
+ /**
+ * @return a String with the unqualified class name of the class (or "null")
+ */
+ public static String unqualifiedClassName(Class<?> c) {
+ if (null == c) {
+ return "null";
+ }
+ String name = c.getName();
+ int loc = name.lastIndexOf(".");
+ if (-1 != loc) {
+ name = name.substring(1 + loc);
+ }
+ return name;
+ }
+
+ /**
+ * @return a String with the unqualified class name of the object (or "null")
+ */
+ public static String unqualifiedClassName(Object o) {
+ return LangUtil.unqualifiedClassName(null == o ? null : o.getClass());
+ }
+
+ /** inefficient way to replace all instances of sought with replace */
+ public static String replace(String in, String sought, String replace) {
+ if (LangUtil.isEmpty(in) || LangUtil.isEmpty(sought)) {
+ return in;
+ }
+ StringBuffer result = new StringBuffer();
+ final int len = sought.length();
+ int start = 0;
+ int loc;
+ while (-1 != (loc = in.indexOf(sought, start))) {
+ result.append(in.substring(start, loc));
+ if (!LangUtil.isEmpty(replace)) {
+ result.append(replace);
+ }
+ start = loc + len;
+ }
+ result.append(in.substring(start));
+ return result.toString();
+ }
+
+ /** render i right-justified with a given width less than about 40 */
+ public static String toSizedString(long i, int width) {
+ String result = "" + i;
+ int size = result.length();
+ if (width > size) {
+ final String pad = " ";
+ final int padLength = pad.length();
+ if (width > padLength) {
+ width = padLength;
+ }
+ int topad = width - size;
+ result = pad.substring(0, topad) + result;
+ }
+ return result;
+ }
+
+ // /** clip StringBuffer to maximum number of lines */
+ // static String clipBuffer(StringBuffer buffer, int maxLines) {
+ // if ((null == buffer) || (1 > buffer.length())) return "";
+ // StringBuffer result = new StringBuffer();
+ // int j = 0;
+ // final int MAX = maxLines;
+ // final int N = buffer.length();
+ // for (int i = 0, srcBegin = 0; i < MAX; srcBegin += j) {
+ // // todo: replace with String variant if/since getting char?
+ // char[] chars = new char[128];
+ // int srcEnd = srcBegin+chars.length;
+ // if (srcEnd >= N) {
+ // srcEnd = N-1;
+ // }
+ // if (srcBegin == srcEnd) break;
+ // //log("srcBegin:" + srcBegin + ":srcEnd:" + srcEnd);
+ // buffer.getChars(srcBegin, srcEnd, chars, 0);
+ // for (j = 0; j < srcEnd-srcBegin/*chars.length*/; j++) {
+ // char c = chars[j];
+ // if (c == '\n') {
+ // i++;
+ // j++;
+ // break;
+ // }
+ // }
+ // try { result.append(chars, 0, j); }
+ // catch (Throwable t) { }
+ // }
+ // return result.toString();
+ // }
+
+ /**
+ * @return "({UnqualifiedExceptionClass}) {message}"
+ */
+ public static String renderExceptionShort(Throwable e) {
+ if (null == e) {
+ return "(Throwable) null";
+ }
+ return "(" + LangUtil.unqualifiedClassName(e) + ") " + e.getMessage();
+ }
+
+ /**
+ * Renders exception <code>t</code> after unwrapping and eliding any test packages.
+ *
+ * @param t <code>Throwable</code> to print.
+ * @see #maxStackTrace
+ */
+ public static String renderException(Throwable t) {
+ return renderException(t, true);
+ }
+
+ /**
+ * Renders exception <code>t</code>, unwrapping, optionally eliding and limiting total number of lines.
+ *
+ * @param t <code>Throwable</code> to print.
+ * @param elide true to limit to 100 lines and elide test packages
+ * @see StringChecker#TEST_PACKAGES
+ */
+ public static String renderException(Throwable t, boolean elide) {
+ if (null == t) {
+ return "null throwable";
+ }
+ t = unwrapException(t);
+ StringBuffer stack = stackToString(t, false);
+ if (elide) {
+ elideEndingLines(StringChecker.TEST_PACKAGES, stack, 100);
+ }
+ return stack.toString();
+ }
+
+ /**
+ * Trim ending lines from a StringBuffer, clipping to maxLines and further removing any number of trailing lines accepted by
+ * checker.
+ *
+ * @param checker returns true if trailing line should be elided.
+ * @param stack StringBuffer with lines to elide
+ * @param maxLines int for maximum number of resulting lines
+ */
+ static void elideEndingLines(StringChecker checker, StringBuffer stack, int maxLines) {
+ if (null == checker || (null == stack) || (0 == stack.length())) {
+ return;
+ }
+ final LinkedList<String> lines = new LinkedList<String>();
+ StringTokenizer st = new StringTokenizer(stack.toString(), "\n\r");
+ while (st.hasMoreTokens() && (0 < --maxLines)) {
+ lines.add(st.nextToken());
+ }
+ st = null;
+
+ String line;
+ int elided = 0;
+ while (!lines.isEmpty()) {
+ line = lines.getLast();
+ if (!checker.acceptString(line)) {
+ break;
+ } else {
+ elided++;
+ lines.removeLast();
+ }
+ }
+ if ((elided > 0) || (maxLines < 1)) {
+ final int EOL_LEN = EOL.length();
+ int totalLength = 0;
+ while (!lines.isEmpty()) {
+ totalLength += EOL_LEN + lines.getFirst().length();
+ lines.removeFirst();
+ }
+ if (stack.length() > totalLength) {
+ stack.setLength(totalLength);
+ if (elided > 0) {
+ stack.append(" (... " + elided + " lines...)");
+ }
+ }
+ }
+ }
+
+ /** Dump message and stack to StringBuffer. */
+ public static StringBuffer stackToString(Throwable throwable, boolean skipMessage) {
+ if (null == throwable) {
+ return new StringBuffer();
+ }
+ StringWriter buf = new StringWriter();
+ PrintWriter writer = new PrintWriter(buf);
+ if (!skipMessage) {
+ writer.println(throwable.getMessage());
+ }
+ throwable.printStackTrace(writer);
+ try {
+ buf.close();
+ } catch (IOException ioe) {
+ } // ignored
+ return buf.getBuffer();
+ }
+
+ /** @return Throwable input or tail of any wrapped exception chain */
+ public static Throwable unwrapException(Throwable t) {
+ Throwable current = t;
+ Throwable next = null;
+ while (current != null) {
+ // Java 1.2 exceptions that carry exceptions
+ if (current instanceof InvocationTargetException) {
+ next = ((InvocationTargetException) current).getTargetException();
+ } else if (current instanceof ClassNotFoundException) {
+ next = ((ClassNotFoundException) current).getException();
+ } else if (current instanceof ExceptionInInitializerError) {
+ next = ((ExceptionInInitializerError) current).getException();
+ } else if (current instanceof PrivilegedActionException) {
+ next = ((PrivilegedActionException) current).getException();
+ } else if (current instanceof SQLException) {
+ next = ((SQLException) current).getNextException();
+ }
+ // ...getException():
+ // javax.naming.event.NamingExceptionEvent
+ // javax.naming.ldap.UnsolicitedNotification
+ // javax.xml.parsers.FactoryConfigurationError
+ // javax.xml.transform.TransformerFactoryConfigurationError
+ // javax.xml.transform.TransformerException
+ // org.xml.sax.SAXException
+ // 1.4: Throwable.getCause
+ // java.util.logging.LogRecord.getThrown()
+ if (null == next) {
+ break;
+ } else {
+ current = next;
+ next = null;
+ }
+ }
+ return current;
+ }
+
+ /**
+ * Replacement for Arrays.asList(..) which gacks on null and returns a List in which remove is an unsupported operation.
+ *
+ * @param array the Object[] to convert (may be null)
+ * @return the List corresponding to array (never null)
+ */
+ public static <T> List<T> arrayAsList(T[] array) {
+ if ((null == array) || (1 > array.length)) {
+ return Collections.emptyList();
+ }
+ ArrayList<T> list = new ArrayList<T>();
+ list.addAll(Arrays.asList(array));
+ return list;
+ }
+
+ /** check if input contains any packages to elide. */
+ public static class StringChecker {
+ static StringChecker TEST_PACKAGES = new StringChecker(new String[] { "org.aspectj.testing",
+ "org.eclipse.jdt.internal.junit", "junit.framework.",
+ "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" });
+
+ String[] infixes;
+
+ /** @param infixes adopted */
+ StringChecker(String[] infixes) {
+ this.infixes = infixes;
+ }
+
+ /** @return true if input contains infixes */
+ public boolean acceptString(String input) {
+ boolean result = false;
+ if (!LangUtil.isEmpty(input)) {
+ for (int i = 0; !result && (i < infixes.length); i++) {
+ result = (-1 != input.indexOf(infixes[i]));
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Gen classpath.
+ *
+ * @param bootclasspath
+ * @param classpath
+ * @param classesDir
+ * @param outputJar
+ * @return String combining classpath elements
+ */
+ public static String makeClasspath( // XXX dumb implementation
+ String bootclasspath, String classpath, String classesDir, String outputJar) {
+ StringBuffer sb = new StringBuffer();
+ addIfNotEmpty(bootclasspath, sb, File.pathSeparator);
+ addIfNotEmpty(classpath, sb, File.pathSeparator);
+ if (!addIfNotEmpty(classesDir, sb, File.pathSeparator)) {
+ addIfNotEmpty(outputJar, sb, File.pathSeparator);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * @param input ignored if null
+ * @param sink the StringBuffer to add input to - return false if null
+ * @param delimiter the String to append to input when added - ignored if empty
+ * @return true if input + delimiter added to sink
+ */
+ private static boolean addIfNotEmpty(String input, StringBuffer sink, String delimiter) {
+ if (LangUtil.isEmpty(input) || (null == sink)) {
+ return false;
+ }
+ sink.append(input);
+ if (!LangUtil.isEmpty(delimiter)) {
+ sink.append(delimiter);
+ }
+ return true;
+ }
+
+ /**
+ * Create or initialize a process controller to run a process in another VM asynchronously.
+ *
+ * @param controller the ProcessController to initialize, if not null
+ * @param classpath
+ * @param mainClass
+ * @param args
+ * @return initialized ProcessController
+ */
+ public static ProcessController makeProcess(ProcessController controller, String classpath, String mainClass, String[] args) {
+ File java = LangUtil.getJavaExecutable();
+ ArrayList<String> cmd = new ArrayList<String>();
+ cmd.add(java.getAbsolutePath());
+ cmd.add("-classpath");
+ cmd.add(classpath);
+ cmd.add(mainClass);
+ if (!LangUtil.isEmpty(args)) {
+ cmd.addAll(Arrays.asList(args));
+ }
+ String[] command = cmd.toArray(new String[0]);
+ if (null == controller) {
+ controller = new ProcessController();
+ }
+ controller.init(command, mainClass);
+ return controller;
+ }
+
+ // /**
+ // * Create a process to run asynchronously.
+ // * @param controller if not null, initialize this one
+ // * @param command the String[] command to run
+ // * @param controller the ProcessControl for streams and results
+ // */
+ // public static ProcessController makeProcess( // not needed?
+ // ProcessController controller,
+ // String[] command,
+ // String label) {
+ // if (null == controller) {
+ // controller = new ProcessController();
+ // }
+ // controller.init(command, label);
+ // return controller;
+ // }
+
+ /**
+ * Find java executable File path from java.home system property.
+ *
+ * @return File associated with the java command, or null if not found.
+ */
+ public static File getJavaExecutable() {
+ String javaHome = null;
+ File result = null;
+ // java.home
+ // java.class.path
+ // java.ext.dirs
+ try {
+ javaHome = System.getProperty("java.home");
+ } catch (Throwable t) {
+ // ignore
+ }
+ if (null != javaHome) {
+ File binDir = new File(javaHome, "bin");
+ if (binDir.isDirectory() && binDir.canRead()) {
+ String[] execs = new String[] { "java", "java.exe" };
+ for (int i = 0; i < execs.length; i++) {
+ result = new File(binDir, execs[i]);
+ if (result.canRead()) {
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ // /**
+ // * Sleep for a particular period (in milliseconds).
+ // *
+ // * @param time the long time in milliseconds to sleep
+ // * @return true if delay succeeded, false if interrupted 100 times
+ // */
+ // public static boolean sleep(long milliseconds) {
+ // if (milliseconds == 0) {
+ // return true;
+ // } else if (milliseconds < 0) {
+ // throw new IllegalArgumentException("negative: " + milliseconds);
+ // }
+ // return sleepUntil(milliseconds + System.currentTimeMillis());
+ // }
+
+ /**
+ * Sleep until a particular time.
+ *
+ * @param time the long time in milliseconds to sleep until
+ * @return true if delay succeeded, false if interrupted 100 times
+ */
+ public static boolean sleepUntil(long time) {
+ if (time == 0) {
+ return true;
+ } else if (time < 0) {
+ throw new IllegalArgumentException("negative: " + time);
+ }
+ // final Thread thread = Thread.currentThread();
+ long curTime = System.currentTimeMillis();
+ for (int i = 0; (i < 100) && (curTime < time); i++) {
+ try {
+ Thread.sleep(time - curTime);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ curTime = System.currentTimeMillis();
+ }
+ return (curTime >= time);
+ }
+
+ /**
+ * Handle an external process asynchrously. <code>start()</code> launches a main thread to wait for the process and pipes
+ * streams (in child threads) through to the corresponding streams (e.g., the process System.err to this System.err). This can
+ * complete normally, by exception, or on demand by a client. Clients can implement <code>doCompleting(..)</code> to get notice
+ * when the process completes.
+ * <p>
+ * The following sample code creates a process with a completion callback starts it, and some time later retries the process.
+ *
+ * <pre>
+ * LangUtil.ProcessController controller = new LangUtil.ProcessController() {
+ * protected void doCompleting(LangUtil.ProcessController.Thrown thrown, int result) {
+ * // signal result
+ * }
+ * };
+ * controller.init(new String[] { "java", "-version" }, "java version");
+ * controller.start();
+ * // some time later...
+ * // retry...
+ * if (!controller.completed()) {
+ * controller.stop();
+ * controller.reinit();
+ * controller.start();
+ * }
+ * </pre>
+ *
+ * <u>warning</u>: Currently this does not close the input or output streams, since doing so prevents their use later.
+ */
+ public static class ProcessController {
+ /*
+ * XXX not verified thread-safe, but should be. Known problems: - user stops (completed = true) then exception thrown from
+ * destroying process (stop() expects !completed) ...
+ */
+ private String[] command;
+ private String[] envp;
+ private String label;
+
+ private boolean init;
+ private boolean started;
+ private boolean completed;
+ /** if true, stopped by user when not completed */
+ private boolean userStopped;
+
+ private Process process;
+ private FileUtil.Pipe errStream;
+ private FileUtil.Pipe outStream;
+ private FileUtil.Pipe inStream;
+ private ByteArrayOutputStream errSnoop;
+ private ByteArrayOutputStream outSnoop;
+
+ private int result;
+ private Thrown thrown;
+
+ public ProcessController() {
+ }
+
+ /**
+ * Permit re-running using the same command if this is not started or if completed. Can also call this when done with
+ * results to release references associated with results (e.g., stack traces).
+ */
+ public final void reinit() {
+ if (!init) {
+ throw new IllegalStateException("must init(..) before reinit()");
+ }
+ if (started && !completed) {
+ throw new IllegalStateException("not completed - do stop()");
+ }
+ // init everything but command and label
+ started = false;
+ completed = false;
+ result = Integer.MIN_VALUE;
+ thrown = null;
+ process = null;
+ errStream = null;
+ outStream = null;
+ inStream = null;
+ }
+
+ public final void init(String classpath, String mainClass, String[] args) {
+ init(LangUtil.getJavaExecutable(), classpath, mainClass, args);
+ }
+
+ public final void init(File java, String classpath, String mainClass, String[] args) {
+ LangUtil.throwIaxIfNull(java, "java");
+ LangUtil.throwIaxIfNull(mainClass, "mainClass");
+ LangUtil.throwIaxIfNull(args, "args");
+ ArrayList<String> cmd = new ArrayList<String>();
+ cmd.add(java.getAbsolutePath());
+ cmd.add("-classpath");
+ cmd.add(classpath);
+ cmd.add(mainClass);
+ if (!LangUtil.isEmpty(args)) {
+ cmd.addAll(Arrays.asList(args));
+ }
+ init(cmd.toArray(new String[0]), mainClass);
+ }
+
+ public final void init(String[] command, String label) {
+ this.command = (String[]) LangUtil.safeCopy(command, new String[0]);
+ if (1 > this.command.length) {
+ throw new IllegalArgumentException("empty command");
+ }
+ this.label = LangUtil.isEmpty(label) ? command[0] : label;
+ init = true;
+ reinit();
+ }
+
+ public final void setEnvp(String[] envp) {
+ this.envp = (String[]) LangUtil.safeCopy(envp, new String[0]);
+ if (1 > this.envp.length) {
+ throw new IllegalArgumentException("empty envp");
+ }
+ }
+
+ public final void setErrSnoop(ByteArrayOutputStream snoop) {
+ errSnoop = snoop;
+ if (null != errStream) {
+ errStream.setSnoop(errSnoop);
+ }
+ }
+
+ public final void setOutSnoop(ByteArrayOutputStream snoop) {
+ outSnoop = snoop;
+ if (null != outStream) {
+ outStream.setSnoop(outSnoop);
+ }
+ }
+
+ /**
+ * Start running the process and pipes asynchronously.
+ *
+ * @return Thread started or null if unable to start thread (results available via <code>getThrown()</code>, etc.)
+ */
+ public final Thread start() {
+ if (!init) {
+ throw new IllegalStateException("not initialized");
+ }
+ synchronized (this) {
+ if (started) {
+ throw new IllegalStateException("already started");
+ }
+ started = true;
+ }
+ try {
+ process = Runtime.getRuntime().exec(command);
+ } catch (IOException e) {
+ stop(e, Integer.MIN_VALUE);
+ return null;
+ }
+ errStream = new FileUtil.Pipe(process.getErrorStream(), System.err);
+ if (null != errSnoop) {
+ errStream.setSnoop(errSnoop);
+ }
+ outStream = new FileUtil.Pipe(process.getInputStream(), System.out);
+ if (null != outSnoop) {
+ outStream.setSnoop(outSnoop);
+ }
+ inStream = new FileUtil.Pipe(System.in, process.getOutputStream());
+ // start 4 threads, process & pipes for in, err, out
+ Runnable processRunner = new Runnable() {
+ @Override
+ public void run() {
+ Throwable thrown = null;
+ int result = Integer.MIN_VALUE;
+ try {
+ // pipe threads are children
+ new Thread(errStream).start();
+ new Thread(outStream).start();
+ new Thread(inStream).start();
+ process.waitFor();
+ result = process.exitValue();
+ } catch (Throwable e) {
+ thrown = e;
+ } finally {
+ stop(thrown, result);
+ }
+ }
+ };
+ Thread result = new Thread(processRunner, label);
+ result.start();
+ return result;
+ }
+
+ /**
+ * Destroy any process, stop any pipes. This waits for the pipes to clear (reading until no more input is available), but
+ * does not wait for the input stream for the pipe to close (i.e., not waiting for end-of-file on input stream).
+ */
+ public final synchronized void stop() {
+ if (completed) {
+ return;
+ }
+ userStopped = true;
+ stop(null, Integer.MIN_VALUE);
+ }
+
+ public final String[] getCommand() {
+ String[] toCopy = command;
+ if (LangUtil.isEmpty(toCopy)) {
+ return new String[0];
+ }
+ String[] result = new String[toCopy.length];
+ System.arraycopy(toCopy, 0, result, 0, result.length);
+ return result;
+ }
+
+ public final boolean completed() {
+ return completed;
+ }
+
+ public final boolean started() {
+ return started;
+ }
+
+ public final boolean userStopped() {
+ return userStopped;
+ }
+
+ /**
+ * Get any Throwable thrown. Note that the process can complete normally (with a valid return value), at the same time the
+ * pipes throw exceptions, and that this may return some exceptions even if the process is not complete.
+ *
+ * @return null if not complete or Thrown containing exceptions thrown by the process and streams.
+ */
+ public final Thrown getThrown() { // cache this
+ return makeThrown(null);
+ }
+
+ public final int getResult() {
+ return result;
+ }
+
+ /**
+ * Subclasses implement this to get synchronous notice of completion. All pipes and processes should be complete at this
+ * time. To get the exceptions thrown for the pipes, use <code>getThrown()</code>. If there is an exception, the process
+ * completed abruptly (including side-effects of the user halting the process). If <code>userStopped()</code> is true, then
+ * some client asked that the process be destroyed using <code>stop()</code>. Otherwise, the result code should be the
+ * result value returned by the process.
+ *
+ * @param thrown same as <code>getThrown().fromProcess</code>.
+ * @param result same as <code>getResult()</code>
+ * @see getThrown()
+ * @see getResult()
+ * @see stop()
+ */
+ protected void doCompleting(Thrown thrown, int result) {
+ }
+
+ /**
+ * Handle termination (on-demand, abrupt, or normal) by destroying and/or halting process and pipes.
+ *
+ * @param thrown ignored if null
+ * @param result ignored if Integer.MIN_VALUE
+ */
+ private final synchronized void stop(Throwable thrown, int result) {
+ if (completed) {
+ throw new IllegalStateException("already completed");
+ } else if (null != this.thrown) {
+ throw new IllegalStateException("already set thrown: " + thrown);
+ }
+ // assert null == this.thrown
+ this.thrown = makeThrown(thrown);
+ if (null != process) {
+ process.destroy();
+ }
+ if (null != inStream) {
+ inStream.halt(false, true); // this will block if waiting
+ inStream = null;
+ }
+ if (null != outStream) {
+ outStream.halt(true, true);
+ outStream = null;
+ }
+ if (null != errStream) {
+ errStream.halt(true, true);
+ errStream = null;
+ }
+ if (Integer.MIN_VALUE != result) {
+ this.result = result;
+ }
+ completed = true;
+ doCompleting(this.thrown, result);
+ }
+
+ /**
+ * Create snapshot of Throwable's thrown.
+ *
+ * @param thrown ignored if null or if this.thrown is not null
+ */
+ private final synchronized Thrown makeThrown(Throwable processThrown) {
+ if (null != thrown) {
+ return thrown;
+ }
+ return new Thrown(processThrown, (null == outStream ? null : outStream.getThrown()), (null == errStream ? null
+ : errStream.getThrown()), (null == inStream ? null : inStream.getThrown()));
+ }
+
+ public static class Thrown {
+ public final Throwable fromProcess;
+ public final Throwable fromErrPipe;
+ public final Throwable fromOutPipe;
+ public final Throwable fromInPipe;
+ /** true only if some Throwable is not null */
+ public final boolean thrown;
+
+ private Thrown(Throwable fromProcess, Throwable fromOutPipe, Throwable fromErrPipe, Throwable fromInPipe) {
+ this.fromProcess = fromProcess;
+ this.fromErrPipe = fromErrPipe;
+ this.fromOutPipe = fromOutPipe;
+ this.fromInPipe = fromInPipe;
+ thrown = ((null != fromProcess) || (null != fromInPipe) || (null != fromOutPipe) || (null != fromErrPipe));
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ append(sb, fromProcess, "process");
+ append(sb, fromOutPipe, " stdout");
+ append(sb, fromErrPipe, " stderr");
+ append(sb, fromInPipe, " stdin");
+ if (0 == sb.length()) {
+ return "Thrown (none)";
+ } else {
+ return sb.toString();
+ }
+ }
+
+ private void append(StringBuffer sb, Throwable thrown, String label) {
+ if (null != thrown) {
+ sb.append("from " + label + ": ");
+ sb.append(LangUtil.renderExceptionShort(thrown));
+ sb.append(LangUtil.EOL);
+ }
+ }
+ } // class Thrown
+ }
+
+ public static String getJrtFsFilePath() {
+ return getJavaHome() + File.separator + "lib" + File.separator + JRT_FS;
+ }
+
+ public static String getJavaHome() {
+ return System.getProperty("java.home");
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class implements a partial order
+ *
+ * It includes routines for doing a topo-sort
+ */
+
+public class PartialOrder {
+
+ /**
+ * All classes that want to be part of a partial order must implement PartialOrder.PartialComparable.
+ */
+ public static interface PartialComparable {
+ /**
+ * @returns <ul>
+ * <li>+1 if this is greater than other</li>
+ * <li>-1 if this is less than other</li>
+ * <li>0 if this is not comparable to other</li>
+ * </ul>
+ *
+ * <b> Note: returning 0 from this method doesn't mean the same thing as returning 0 from
+ * java.util.Comparable.compareTo()</b>
+ */
+ public int compareTo(Object other);
+
+ /**
+ * This method can provide a deterministic ordering for elements that are strictly not comparable. If you have no need for
+ * this, this method can just return 0 whenever called.
+ */
+ public int fallbackCompareTo(Object other);
+ }
+
+ private static class SortObject<T extends PartialComparable> {
+ T object;
+ List<SortObject<T>> smallerObjects = new LinkedList<SortObject<T>>();
+ List<SortObject<T>> biggerObjects = new LinkedList<SortObject<T>>();
+
+ public SortObject(T o) {
+ object = o;
+ }
+
+ boolean hasNoSmallerObjects() {
+ return smallerObjects.size() == 0;
+ }
+
+ boolean removeSmallerObject(SortObject<T> o) {
+ smallerObjects.remove(o);
+ return hasNoSmallerObjects();
+ }
+
+ void addDirectedLinks(SortObject<T> other) {
+ int cmp = object.compareTo(other.object);
+ if (cmp == 0) {
+ return;
+ }
+ if (cmp > 0) {
+ this.smallerObjects.add(other);
+ other.biggerObjects.add(this);
+ } else {
+ this.biggerObjects.add(other);
+ other.smallerObjects.add(this);
+ }
+ }
+
+ public String toString() {
+ return object.toString(); // +smallerObjects+biggerObjects;
+ }
+ }
+
+ private static <T extends PartialComparable> void addNewPartialComparable(List<SortObject<T>> graph, T o) {
+ SortObject<T> so = new SortObject<T>(o);
+ for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
+ SortObject<T> other = i.next();
+ so.addDirectedLinks(other);
+ }
+ graph.add(so);
+ }
+
+ private static <T extends PartialComparable> void removeFromGraph(List<SortObject<T>> graph, SortObject<T> o) {
+ for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
+ SortObject<T> other = i.next();
+
+ if (o == other) {
+ i.remove();
+ }
+ // ??? could use this to build up a new queue of objects with no
+ // ??? smaller ones
+ other.removeSmallerObject(o);
+ }
+ }
+
+ /**
+ * @param objects must all implement PartialComparable
+ *
+ * @returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
+ *
+ */
+ public static <T extends PartialComparable> List<T> sort(List<T> objects) {
+ // lists of size 0 or 1 don't need any sorting
+ if (objects.size() < 2) {
+ return objects;
+ }
+
+ // ??? we might want to optimize a few other cases of small size
+
+ // ??? I don't like creating this data structure, but it does give good
+ // ??? separation of concerns.
+ List<SortObject<T>> sortList = new LinkedList<SortObject<T>>();
+ for (Iterator<T> i = objects.iterator(); i.hasNext();) {
+ addNewPartialComparable(sortList, i.next());
+ }
+
+ // System.out.println(sortList);
+
+ // now we have built our directed graph
+ // use a simple sort algorithm from here
+ // can increase efficiency later
+ // List ret = new ArrayList(objects.size());
+ final int N = objects.size();
+ for (int index = 0; index < N; index++) {
+ // System.out.println(sortList);
+ // System.out.println("-->" + ret);
+
+ SortObject<T> leastWithNoSmallers = null;
+
+ for (SortObject<T> so: sortList) {
+ if (so.hasNoSmallerObjects()) {
+ if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {
+ leastWithNoSmallers = so;
+ }
+ }
+ }
+
+ if (leastWithNoSmallers == null) {
+ return null;
+ }
+
+ removeFromGraph(sortList, leastWithNoSmallers);
+ objects.set(index, leastWithNoSmallers.object);
+ }
+
+ return objects;
+ }
+
+ /***********************************************************************************
+ * /* a minimal testing harness
+ ***********************************************************************************/
+ static class Token implements PartialComparable {
+ private String s;
+
+ Token(String s) {
+ this.s = s;
+ }
+
+ public int compareTo(Object other) {
+ Token t = (Token) other;
+
+ int cmp = s.charAt(0) - t.s.charAt(0);
+ if (cmp == 1) {
+ return 1;
+ }
+ if (cmp == -1) {
+ return -1;
+ }
+ return 0;
+ }
+
+ public int fallbackCompareTo(Object other) {
+ return -s.compareTo(((Token) other).s);
+ }
+
+ public String toString() {
+ return s;
+ }
+ }
+
+ public static void main(String[] args) {
+ List<Token> l = new ArrayList<Token>();
+ l.add(new Token("a1"));
+ l.add(new Token("c2"));
+ l.add(new Token("b3"));
+ l.add(new Token("f4"));
+ l.add(new Token("e5"));
+ l.add(new Token("d6"));
+ l.add(new Token("c7"));
+ l.add(new Token("b8"));
+
+ l.add(new Token("z"));
+ l.add(new Token("x"));
+
+ l.add(new Token("f9"));
+ l.add(new Token("e10"));
+ l.add(new Token("a11"));
+ l.add(new Token("d12"));
+ l.add(new Token("b13"));
+ l.add(new Token("c14"));
+
+ System.out.println(l);
+
+ sort(l);
+
+ System.out.println(l);
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * 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
+ * ******************************************************************/
+
+
+package org.aspectj.util;
+
+import java.io.File;
+import java.lang.reflect.*;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+//import java.util.StringTokenizer;
+
+public class Reflection {
+ public static final Class<?>[] MAIN_PARM_TYPES = new Class[] {String[].class};
+
+ private Reflection() {
+ }
+
+ public static Object invokestaticN(Class<?> class_, String name, Object[] args) {
+ return invokeN(class_, name, null, args);
+ }
+
+ public static Object invoke(Class<?> class_, Object target, String name, Object arg1, Object arg2) {
+ return invokeN(class_, name, target, new Object[] { arg1, arg2 });
+ }
+
+ public static Object invoke(Class<?> class_, Object target, String name, Object arg1, Object arg2, Object arg3) {
+ return invokeN(class_, name, target, new Object[] { arg1, arg2, arg3 });
+ }
+
+
+ public static Object invokeN(Class<?> class_, String name, Object target, Object[] args) {
+ Method meth = getMatchingMethod(class_, name, args);
+ try {
+ return meth.invoke(target, args);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.toString());
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (t instanceof Error) throw (Error)t;
+ if (t instanceof RuntimeException) throw (RuntimeException)t;
+ t.printStackTrace();
+ throw new RuntimeException(t.toString());
+ }
+ }
+
+
+ public static Method getMatchingMethod(Class<?> class_, String name, Object[] args) {
+ Method[] meths = class_.getMethods();
+ for (int i=0; i < meths.length; i++) {
+ Method meth = meths[i];
+ if (meth.getName().equals(name) && isCompatible(meth, args)) {
+ return meth;
+ }
+ }
+ return null;
+ }
+
+ private static boolean isCompatible(Method meth, Object[] args) {
+ // ignore methods with overloading other than lengths
+ return meth.getParameterTypes().length == args.length;
+ }
+
+
+
+
+ public static Object getStaticField(Class<?> class_, String name) {
+ try {
+ return class_.getField(name).get(null);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("unimplemented");
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ public static void runMainInSameVM(
+ String classpath,
+ String className,
+ String[] args)
+ throws SecurityException, NoSuchMethodException,
+ IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException, ClassNotFoundException {
+ LangUtil.throwIaxIfNull(className, "class name");
+ if (LangUtil.isEmpty(classpath)) {
+ Class<?> mainClass = Class.forName(className);
+ runMainInSameVM(mainClass, args);
+ return;
+ }
+ ArrayList<File> dirs = new ArrayList<File>();
+ ArrayList<File> libs = new ArrayList<File>();
+ ArrayList<URL> urls = new ArrayList<URL>();
+ String[] entries = LangUtil.splitClasspath(classpath);
+ for (int i = 0; i < entries.length; i++) {
+ String entry = entries[i];
+ URL url = makeURL(entry);
+ if (null != url) {
+ urls.add(url);
+ }
+ File file = new File(entries[i]);
+// tolerate bad entries b/c bootclasspath sometimes has them
+// if (!file.canRead()) {
+// throw new IllegalArgumentException("cannot read " + file);
+// }
+ if (FileUtil.isZipFile(file)) {
+ libs.add(file);
+ } else if (file.isDirectory()) {
+ dirs.add(file);
+ } else {
+ // not URL, zip, or dir - unsure what to do
+ }
+ }
+ File[] dirRa = (File[]) dirs.toArray(new File[0]);
+ File[] libRa = (File[]) libs.toArray(new File[0]);
+ URL[] urlRa = (URL[]) urls.toArray(new URL[0]);
+ runMainInSameVM(urlRa, libRa, dirRa, className, args);
+ }
+
+ public static void runMainInSameVM(
+ URL[] urls,
+ File[] libs,
+ File[] dirs,
+ String className,
+ String[] args)
+ throws SecurityException, NoSuchMethodException,
+ IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException, ClassNotFoundException {
+ LangUtil.throwIaxIfNull(className, "class name");
+ LangUtil.throwIaxIfNotAssignable(libs, File.class, "jars");
+ LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs");
+ URL[] libUrls = FileUtil.getFileURLs(libs);
+ if (!LangUtil.isEmpty(libUrls)) {
+ if (!LangUtil.isEmpty(urls)) {
+ URL[] temp = new URL[libUrls.length + urls.length];
+ System.arraycopy(urls, 0, temp, 0, urls.length);
+ System.arraycopy(urls, 0, temp, libUrls.length, urls.length);
+ urls = temp;
+ } else {
+ urls = libUrls;
+ }
+ }
+ UtilClassLoader loader = new UtilClassLoader(urls, dirs);
+ Class<?> targetClass = null;
+ try {
+ targetClass = loader.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ String s = "unable to load class " + className
+ + " using class loader " + loader;
+ throw new ClassNotFoundException(s);
+ }
+ Method main = targetClass.getMethod("main", MAIN_PARM_TYPES);
+ main.invoke(null, new Object[] { args });
+ }
+
+ public static void runMainInSameVM(Class<?> mainClass, String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+ LangUtil.throwIaxIfNull(mainClass, "main class");
+ Method main = mainClass.getMethod("main", MAIN_PARM_TYPES);
+ main.invoke(null, new Object[] { args });
+ }
+
+ /** @return URL if the input is valid as such */
+ private static URL makeURL(String s) {
+ try {
+ return new URL(s);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2017 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
+ * ******************************************************************/package org.aspectj.util;
+
+import java.lang.ref.*;
+import java.util.*;
+
+public class SoftHashMap<K,V> extends AbstractMap<K,V> {
+ private Map<K, SpecialValue> map;
+ private ReferenceQueue<? super V> rq = new ReferenceQueue();
+
+ public SoftHashMap() {
+ this.map = new HashMap<K,SpecialValue>();
+ }
+
+ class SpecialValue extends SoftReference<V> {
+ private final K key;
+
+ SpecialValue(K k, V v) {
+ super(v, rq);
+ this.key = k;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void processQueue() {
+ SpecialValue sv = null;
+ while ((sv = (SpecialValue)rq.poll()) != null) {
+ map.remove(sv.key);
+ }
+ }
+
+ @Override
+ public V get(Object key) {
+ SpecialValue ref = map.get(key);
+ if (ref == null) {
+ map.remove(key);
+ return null;
+ }
+ V value = ref.get();
+ if (value == null) {
+ map.remove(ref.key);
+ return null;
+ }
+ return value;
+ }
+
+ @Override
+ public V put(K k, V v) {
+ processQueue();
+ SpecialValue sv = new SpecialValue(k, v);
+ SpecialValue result = map.put(k, sv);
+ return (result == null ? null : result.get());
+ }
+
+ @Override
+ public java.util.Set<Map.Entry<K,V>> entrySet() {
+ if (map.isEmpty()) { return Collections.<K,V>emptyMap().entrySet(); }
+ Map<K,V> currentContents = new HashMap<K,V>();
+ for (Map.Entry<K,SpecialValue> entry: map.entrySet()) {
+ V currentValueForEntry = entry.getValue().get();
+ if (currentValueForEntry != null) {
+ currentContents.put(entry.getKey(), currentValueForEntry);
+ }
+ }
+ return currentContents.entrySet();
+ }
+
+ @Override
+ public void clear() {
+ processQueue();
+ map.clear();
+ }
+
+ @Override
+ public int size() {
+ processQueue();
+ return map.size();
+ }
+
+ @Override
+ public V remove(Object k) {
+ processQueue();
+ SpecialValue ref = map.remove(k);
+ if (ref == null) {
+ return null;
+ }
+ return ref.get();
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * 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
+ * ******************************************************************/
+
+package org.aspectj.util;
+
+import java.io.*;
+
+public class TypeSafeEnum {
+ private byte key;
+ private String name;
+
+ public TypeSafeEnum(String name, int key) {
+ this.name = name;
+ if (key > Byte.MAX_VALUE || key < Byte.MIN_VALUE) {
+ throw new IllegalArgumentException("key doesn't fit into a byte: " + key);
+ }
+ this.key = (byte) key;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public byte getKey() {
+ return key;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(key);
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * 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:
+ * Isberg initial implementation
+ * ******************************************************************/
+
+package org.aspectj.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Load classes as File from File[] dirs or URL[] jars.
+ */
+public class UtilClassLoader extends URLClassLoader {
+
+ /** seek classes in dirs first */
+ List<File> dirs;
+
+ /** save URL[] only for toString */
+ private URL[] urlsForDebugString;
+
+ public UtilClassLoader(URL[] urls, File[] dirs) {
+ super(urls);
+ LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs");
+ this.urlsForDebugString = urls;
+ ArrayList<File> dcopy = new ArrayList<File>();
+
+ if (!LangUtil.isEmpty(dirs)) {
+ dcopy.addAll(Arrays.asList(dirs));
+ }
+ this.dirs = Collections.unmodifiableList(dcopy);
+ }
+
+
+ public URL getResource(String name) {
+ return ClassLoader.getSystemResource(name);
+ }
+
+ public InputStream getResourceAsStream(String name) {
+ return ClassLoader.getSystemResourceAsStream(name);
+ }
+
+ public synchronized Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ // search the cache, our dirs (if maybe test),
+ // the system, the superclass (URL[]),
+ // and our dirs again (if not maybe test)
+ ClassNotFoundException thrown = null;
+ Class<?> result = findLoadedClass(name);
+ if (null != result) {
+ resolve = false;
+ } else {
+ try {
+ result = findSystemClass(name);
+ } catch (ClassNotFoundException e) {
+ thrown = e;
+ }
+ }
+ if (null == result) {
+ try {
+ result = super.loadClass(name, resolve);
+ } catch (ClassNotFoundException e) {
+ thrown = e;
+ }
+ if (null != result) { // resolved by superclass
+ return result;
+ }
+ }
+ if (null == result) {
+ byte[] data = readClass(name);
+ if (data != null) {
+ result = defineClass(name, data, 0, data.length);
+ } // handle ClassFormatError?
+ }
+
+ if (null == result) {
+ throw (null != thrown ? thrown : new ClassNotFoundException(name));
+ }
+ if (resolve) {
+ resolveClass(result);
+ }
+ return result;
+ }
+
+ /** @return null if class not found or byte[] of class otherwise */
+ private byte[] readClass(String className) throws ClassNotFoundException {
+ final String fileName = className.replace('.', '/')+".class";
+ for (Iterator<File> iter = dirs.iterator(); iter.hasNext();) {
+ File file = new File(iter.next(), fileName);
+ if (file.canRead()) {
+ return getClassData(file);
+ }
+ }
+ return null;
+ }
+
+ private byte[] getClassData(File f) {
+ try {
+ FileInputStream stream= new FileInputStream(f);
+ ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
+ byte[] b= new byte[4096];
+ int n;
+ while ((n= stream.read(b)) != -1) {
+ out.write(b, 0, n);
+ }
+ stream.close();
+ out.close();
+ return out.toByteArray();
+ } catch (IOException e) {
+ }
+ return null;
+ }
+
+ /** @return String with debug info: urls and classes used */
+ public String toString() {
+ return "UtilClassLoader(urls="
+ + Arrays.asList(urlsForDebugString)
+ + ", dirs="
+ + dirs
+ + ")";
+ }
+}
+
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * @author Andy Clement
- * @author Kris De Volder
- */
-public class FileUtil {
- /** default parent directory File when a file has a null parent */
- public static final File DEFAULT_PARENT = new File("."); // XXX user.dir?
-
- /** unmodifiable List of String source file suffixes (including leading ".") */
- public static final List<String> SOURCE_SUFFIXES = Collections.unmodifiableList(Arrays.asList(new String[] { ".java", ".aj" }));
-
- public static final FileFilter ZIP_FILTER = new FileFilter() {
- public boolean accept(File file) {
- return isZipFile(file);
- }
-
- public String toString() {
- return "ZIP_FILTER";
- }
- };
-
- // public static final FileFilter SOURCE_FILTER = new FileFilter() {
- // public boolean accept(File file) {
- // return hasSourceSuffix(file);
- // }
- //
- // public String toString() {
- // return "SOURCE_FILTER";
- // }
- // };
-
- final static int[] INT_RA = new int[0];
-
- /** accept all files */
- public static final FileFilter ALL = new FileFilter() {
- public boolean accept(File f) {
- return true;
- }
- };
- public static final FileFilter DIRS_AND_WRITABLE_CLASSES = new FileFilter() {
- public boolean accept(File file) {
- return ((null != file) && (file.isDirectory() || (file.canWrite() && file.getName().toLowerCase().endsWith(".class"))));
- }
- };
- private static final boolean PERMIT_CVS;
- static {
- String name = FileUtil.class.getName() + ".PERMIT_CVS";
- PERMIT_CVS = LangUtil.getBoolean(name, false);
- }
-
- /** @return true if file exists and is a zip file */
- public static boolean isZipFile(File file) {
- try {
- return (null != file) && new ZipFile(file) != null;
- } catch (IOException e) {
- return false;
- }
- }
-
- /** @return true if path ends with .zip or .jar */
- // public static boolean hasZipSuffix(String path) {
- // return ((null != path) && (0 != zipSuffixLength(path)));
- // }
- /** @return 0 if file has no zip/jar suffix or 4 otherwise */
- public static int zipSuffixLength(File file) {
- return (null == file ? 0 : zipSuffixLength(file.getPath()));
- }
-
- /** @return 0 if no zip/jar suffix or 4 otherwise */
- public static int zipSuffixLength(String path) {
- if ((null != path) && (4 < path.length())) {
- String test = path.substring(path.length() - 4).toLowerCase();
- if (".zip".equals(test) || ".jar".equals(test)) {
- return 4;
- }
- }
- return 0;
- }
-
- /** @return true if file path has a source suffix */
- public static boolean hasSourceSuffix(File file) {
- return ((null != file) && hasSourceSuffix(file.getPath()));
- }
-
- /** @return true if path ends with .java or .aj */
- public static boolean hasSourceSuffix(String path) {
- return ((null != path) && (0 != sourceSuffixLength(path)));
- }
-
- /**
- * @return 0 if file has no source suffix or the length of the suffix otherwise
- */
- public static int sourceSuffixLength(File file) {
- return (null == file ? 0 : sourceSuffixLength(file.getPath()));
- }
-
- /** @return 0 if no source suffix or the length of the suffix otherwise */
- public static int sourceSuffixLength(String path) {
- if (LangUtil.isEmpty(path)) {
- return 0;
- }
-
- for (Iterator<String> iter = SOURCE_SUFFIXES.iterator(); iter.hasNext();) {
- String suffix = iter.next();
- if (path.endsWith(suffix) || path.toLowerCase().endsWith(suffix)) {
- return suffix.length();
- }
- }
- return 0;
- }
-
- /** @return true if this is a readable directory */
- public static boolean canReadDir(File dir) {
- return ((null != dir) && dir.canRead() && dir.isDirectory());
- }
-
- /** @return true if this is a readable file */
- public static boolean canReadFile(File file) {
- return ((null != file) && file.canRead() && file.isFile());
- }
-
- /** @return true if dir is a writable directory */
- public static boolean canWriteDir(File dir) {
- return ((null != dir) && dir.canWrite() && dir.isDirectory());
- }
-
- /** @return true if this is a writable file */
- public static boolean canWriteFile(File file) {
- return ((null != file) && file.canWrite() && file.isFile());
- }
-
- // /**
- // * @throws IllegalArgumentException unless file is readable and not a
- // * directory
- // */
- // public static void throwIaxUnlessCanReadFile(File file, String label) {
- // if (!canReadFile(file)) {
- // throw new IllegalArgumentException(label + " not readable file: " +
- // file);
- // }
- // }
-
- /**
- * @throws IllegalArgumentException unless dir is a readable directory
- */
- public static void throwIaxUnlessCanReadDir(File dir, String label) {
- if (!canReadDir(dir)) {
- throw new IllegalArgumentException(label + " not readable dir: " + dir);
- }
- }
-
- /**
- * @throws IllegalArgumentException unless file is readable and not a directory
- */
- public static void throwIaxUnlessCanWriteFile(File file, String label) {
- if (!canWriteFile(file)) {
- throw new IllegalArgumentException(label + " not writable file: " + file);
- }
- }
-
- /** @throws IllegalArgumentException unless dir is a readable directory */
- public static void throwIaxUnlessCanWriteDir(File dir, String label) {
- if (!canWriteDir(dir)) {
- throw new IllegalArgumentException(label + " not writable dir: " + dir);
- }
- }
-
- /** @return array same length as input, with String paths */
- public static String[] getPaths(File[] files) {
- if ((null == files) || (0 == files.length)) {
- return new String[0];
- }
- String[] result = new String[files.length];
- for (int i = 0; i < result.length; i++) {
- if (null != files[i]) {
- result[i] = files[i].getPath();
- }
- }
- return result;
- }
-
- /** @return array same length as input, with String paths */
- public static String[] getPaths(List<File> files) {
- final int size = (null == files ? 0 : files.size());
- if (0 == size) {
- return new String[0];
- }
- String[] result = new String[size];
- for (int i = 0; i < size; i++) {
- File file = files.get(i);
- if (null != file) {
- result[i] = file.getPath();
- }
- }
- return result;
- }
-
- /**
- * Extract the name of a class from the path to its file. If the basedir is null, then the class is assumed to be in the default
- * package unless the classFile has one of the top-level suffixes { com, org, java, javax } as a parent directory.
- *
- * @param basedir the File of the base directory (prefix of classFile)
- * @param classFile the File of the class to extract the name for
- * @throws IllegalArgumentException if classFile is null or does not end with ".class" or a non-null basedir is not a prefix of
- * classFile
- */
- public static String fileToClassName(File basedir, File classFile) {
- LangUtil.throwIaxIfNull(classFile, "classFile");
- String classFilePath = normalizedPath(classFile);
- if (!classFilePath.endsWith(".class")) {
- String m = classFile + " does not end with .class";
- throw new IllegalArgumentException(m);
- }
- classFilePath = classFilePath.substring(0, classFilePath.length() - 6);
- if (null != basedir) {
- String basePath = normalizedPath(basedir);
- if (!classFilePath.startsWith(basePath)) {
- String m = classFile + " does not start with " + basedir;
- throw new IllegalArgumentException(m);
- }
- classFilePath = classFilePath.substring(basePath.length() + 1);
- } else {
- final String[] suffixes = new String[] { "com", "org", "java", "javax" };
- boolean found = false;
- for (int i = 0; !found && (i < suffixes.length); i++) {
- int loc = classFilePath.indexOf(suffixes[i] + "/");
- if ((0 == loc) || ((-1 != loc) && ('/' == classFilePath.charAt(loc - 1)))) {
- classFilePath = classFilePath.substring(loc);
- found = true;
- }
- }
- if (!found) {
- int loc = classFilePath.lastIndexOf("/");
- if (-1 != loc) { // treat as default package
- classFilePath = classFilePath.substring(loc + 1);
- }
- }
- }
- return classFilePath.replace('/', '.');
- }
-
- /**
- * Normalize path for comparisons by rendering absolute, clipping basedir prefix, trimming and changing '\\' to '/'
- *
- * @param file the File with the path to normalize
- * @param basedir the File for the prefix of the file to normalize - ignored if null
- * @return "" if null or normalized path otherwise
- * @throws IllegalArgumentException if basedir is not a prefix of file
- */
- public static String normalizedPath(File file, File basedir) {
- String filePath = normalizedPath(file);
- if (null != basedir) {
- String basePath = normalizedPath(basedir);
- if (filePath.startsWith(basePath)) {
- filePath = filePath.substring(basePath.length());
- if (filePath.startsWith("/")) {
- filePath = filePath.substring(1);
- }
- }
- }
- return filePath;
- }
-
- /**
- * Render a set of files to String as a path by getting absolute paths of each and delimiting with infix.
- *
- * @param files the File[] to flatten - may be null or empty
- * @param infix the String delimiter internally between entries (if null, then use File.pathSeparator). (alias to
- * <code>flatten(getAbsolutePaths(files), infix)</code>
- * @return String with absolute paths to entries in order, delimited with infix
- */
- public static String flatten(File[] files, String infix) {
- if (LangUtil.isEmpty(files)) {
- return "";
- }
- return flatten(getPaths(files), infix);
- }
-
- /**
- * Flatten File[] to String.
- *
- * @param files the File[] of paths to flatten - null ignored
- * @param infix the String infix to use - null treated as File.pathSeparator
- */
- public static String flatten(String[] paths, String infix) {
- if (null == infix) {
- infix = File.pathSeparator;
- }
- StringBuffer result = new StringBuffer();
- boolean first = true;
- for (int i = 0; i < paths.length; i++) {
- String path = paths[i];
- if (null == path) {
- continue;
- }
- if (first) {
- first = false;
- } else {
- result.append(infix);
- }
- result.append(path);
- }
- return result.toString();
- }
-
- /**
- * Normalize path for comparisons by rendering absolute trimming and changing '\\' to '/'
- *
- * @return "" if null or normalized path otherwise
- */
- public static String normalizedPath(File file) {
- return (null == file ? "" : weakNormalize(file.getAbsolutePath()));
- }
-
- /**
- * Weakly normalize path for comparisons by trimming and changing '\\' to '/'
- */
- public static String weakNormalize(String path) {
- if (null != path) {
- path = path.replace('\\', '/').trim();
- }
- return path;
- }
-
- /**
- * Get best File for the first-readable path in input paths, treating entries prefixed "sp:" as system property keys. Safe to
- * call in static initializers.
- *
- * @param paths the String[] of paths to check.
- * @return null if not found, or valid File otherwise
- */
- public static File getBestFile(String[] paths) {
- if (null == paths) {
- return null;
- }
- File result = null;
- for (int i = 0; (null == result) && (i < paths.length); i++) {
- String path = paths[i];
- if (null == path) {
- continue;
- }
- if (path.startsWith("sp:")) {
- try {
- path = System.getProperty(path.substring(3));
- } catch (Throwable t) {
- path = null;
- }
- if (null == path) {
- continue;
- }
- }
- try {
- File f = new File(path);
- if (f.exists() && f.canRead()) {
- result = FileUtil.getBestFile(f);
- }
- } catch (Throwable t) {
- // swallow
- }
- }
- return result;
- }
-
- /**
- * Render as best file, canonical or absolute.
- *
- * @param file the File to get the best File for (not null)
- * @return File of the best-available path
- * @throws IllegalArgumentException if file is null
- */
- public static File getBestFile(File file) {
- LangUtil.throwIaxIfNull(file, "file");
- if (file.exists()) {
- try {
- return file.getCanonicalFile();
- } catch (IOException e) {
- return file.getAbsoluteFile();
- }
- } else {
- return file;
- }
- }
-
- /**
- * Render as best path, canonical or absolute.
- *
- * @param file the File to get the path for (not null)
- * @return String of the best-available path
- * @throws IllegalArgumentException if file is null
- */
- public static String getBestPath(File file) {
- LangUtil.throwIaxIfNull(file, "file");
- if (file.exists()) {
- try {
- return file.getCanonicalPath();
- } catch (IOException e) {
- return file.getAbsolutePath();
- }
- } else {
- return file.getPath();
- }
- }
-
- /** @return array same length as input, with String absolute paths */
- public static String[] getAbsolutePaths(File[] files) {
- if ((null == files) || (0 == files.length)) {
- return new String[0];
- }
- String[] result = new String[files.length];
- for (int i = 0; i < result.length; i++) {
- if (null != files[i]) {
- result[i] = files[i].getAbsolutePath();
- }
- }
- return result;
- }
-
- /**
- * Recursively delete the contents of dir, but not the dir itself
- *
- * @return the total number of files deleted
- */
- public static int deleteContents(File dir) {
- return deleteContents(dir, ALL);
- }
-
- /**
- * Recursively delete some contents of dir, but not the dir itself. This deletes any subdirectory which is empty after its files
- * are deleted.
- *
- * @return the total number of files deleted
- */
- public static int deleteContents(File dir, FileFilter filter) {
- return deleteContents(dir, filter, true);
- }
-
- /**
- * Recursively delete some contents of dir, but not the dir itself. If deleteEmptyDirs is true, this deletes any subdirectory
- * which is empty after its files are deleted.
- *
- * @param dir the File directory (if a file, the the file is deleted)
- * @return the total number of files deleted
- */
- public static int deleteContents(File dir, FileFilter filter,
- boolean deleteEmptyDirs) {
- if (null == dir) {
- throw new IllegalArgumentException("null dir");
- }
- if ((!dir.exists()) || (!dir.canWrite())) {
- return 0;
- }
- if (!dir.isDirectory()) {
- dir.delete();
- return 1;
- }
- String[] fromFiles = dir.list();
- if (fromFiles == null) {
- return 0;
- }
- int result = 0;
- for (int i = 0; i < fromFiles.length; i++) {
- String string = fromFiles[i];
- File file = new File(dir, string);
- if ((null == filter) || filter.accept(file)) {
- if (file.isDirectory()) {
- result += deleteContents(file, filter, deleteEmptyDirs);
- String[] fileContent = file.list();
- if (deleteEmptyDirs && fileContent != null
- && 0 == fileContent.length) {
- file.delete();
- }
- } else {
- /* boolean ret = */
- file.delete();
- result++;
- }
- }
- }
- return result;
- }
-
- /**
- * Copy contents of fromDir into toDir
- *
- * @param fromDir must exist and be readable
- * @param toDir must exist or be creatable and be writable
- * @return the total number of files copied
- */
- public static int copyDir(File fromDir, File toDir) throws IOException {
- return copyDir(fromDir, toDir, null, null);
- }
-
- /**
- * Recursively copy files in fromDir (with any fromSuffix) to toDir, replacing fromSuffix with toSuffix if any. This silently
- * ignores dirs and files that are not readable but throw IOException for directories that are not writable. This does not clean
- * out the original contents of toDir. (subdirectories are not renamed per directory rules)
- *
- * @param fromSuffix select files with this suffix - select all if null or empty
- * @param toSuffix replace fromSuffix with toSuffix in the destination file name - ignored if null or empty, appended to name if
- * fromSuffix is null or empty
- * @return the total number of files copied
- */
- public static int copyDir(File fromDir, File toDir, final String fromSuffix, String toSuffix) throws IOException {
- return copyDir(fromDir, toDir, fromSuffix, toSuffix, (FileFilter) null);
- }
-
- // /**
- // * Recursively copy files in fromDir (with any fromSuffix) to toDir,
- // * replacing fromSuffix with toSuffix if any, and adding the destination
- // * file to any collector. This silently ignores dirs and files that are
- // not
- // * readable but throw IOException for directories that are not writable.
- // * This does not clean out the original contents of toDir. (subdirectories
- // * are not renamed per directory rules) This calls any delegate
- // * FilenameFilter to collect any selected file.
- // *
- // * @param fromSuffix select files with this suffix - select all if null or
- // * empty
- // * @param toSuffix replace fromSuffix with toSuffix in the destination
- // file
- // * name - ignored if null or empty, appended to name if
- // * fromSuffix is null or empty
- // * @param collector the List sink for destination files - ignored if null
- // * @return the total number of files copied
- // */
- // public static int copyDir(File fromDir, File toDir, final String
- // fromSuffix, final String toSuffix, final List collector)
- // throws IOException {
- // // int before = collector.size();
- // if (null == collector) {
- // return copyDir(fromDir, toDir, fromSuffix, toSuffix);
- // } else {
- // FileFilter collect = new FileFilter() {
- // public boolean accept(File pathname) {
- // return collector.add(pathname);
- // }
- // };
- // return copyDir(fromDir, toDir, fromSuffix, toSuffix, collect);
- // }
- // }
-
- /**
- * Recursively copy files in fromDir (with any fromSuffix) to toDir, replacing fromSuffix with toSuffix if any. This silently
- * ignores dirs and files that are not readable but throw IOException for directories that are not writable. This does not clean
- * out the original contents of toDir. (subdirectories are not renamed per directory rules) This calls any delegate
- * FilenameFilter to collect any selected file.
- *
- * @param fromSuffix select files with this suffix - select all if null or empty
- * @param toSuffix replace fromSuffix with toSuffix in the destination file name - ignored if null or empty, appended to name if
- * fromSuffix is null or empty
- * @return the total number of files copied
- */
- public static int copyDir(File fromDir, File toDir, final String fromSuffix, final String toSuffix, final FileFilter delegate)
- throws IOException {
-
- if ((null == fromDir) || (!fromDir.canRead())) {
- return 0;
- }
- final boolean haveSuffix = ((null != fromSuffix) && (0 < fromSuffix.length()));
- final int slen = (!haveSuffix ? 0 : fromSuffix.length());
-
- if (!toDir.exists()) {
- toDir.mkdirs();
- }
- final String[] fromFiles;
- if (!haveSuffix) {
- fromFiles = fromDir.list();
- } else {
- FilenameFilter filter = new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return (new File(dir, name).isDirectory() || (name.endsWith(fromSuffix)));
- }
- };
- fromFiles = fromDir.list(filter);
- }
- int result = 0;
- final int MAX = (null == fromFiles ? 0 : fromFiles.length);
- for (int i = 0; i < MAX; i++) {
- String filename = fromFiles[i];
- File fromFile = new File(fromDir, filename);
- if (fromFile.canRead()) {
- if (fromFile.isDirectory()) {
- result += copyDir(fromFile, new File(toDir, filename), fromSuffix, toSuffix, delegate);
- } else if (fromFile.isFile()) {
- if (haveSuffix) {
- filename = filename.substring(0, filename.length() - slen);
- }
- if (null != toSuffix) {
- filename = filename + toSuffix;
- }
- File targetFile = new File(toDir, filename);
- if ((null == delegate) || delegate.accept(targetFile)) {
- copyFile(fromFile, targetFile);
- }
- result++;
- }
- }
- }
- return result;
- }
-
- /**
- * Recursively list files in srcDir.
- *
- * @return ArrayList with String paths of File under srcDir (relative to srcDir)
- */
- public static String[] listFiles(File srcDir) {
- ArrayList<String> result = new ArrayList<String>();
- if ((null != srcDir) && srcDir.canRead()) {
- listFiles(srcDir, null, result);
- }
- return result.toArray(new String[0]);
- }
-
- public static final FileFilter aspectjSourceFileFilter = new FileFilter() {
- public boolean accept(File pathname) {
- String name = pathname.getName().toLowerCase();
- return name.endsWith(".java") || name.endsWith(".aj");
- }
- };
-
- /**
- * Recursively list files in srcDir.
- *
- * @return ArrayList with String paths of File under srcDir (relative to srcDir)
- */
- public static File[] listFiles(File srcDir, FileFilter fileFilter) {
- ArrayList<File> result = new ArrayList<File>();
- if ((null != srcDir) && srcDir.canRead()) {
- listFiles(srcDir, result, fileFilter);
- }
- return result.toArray(new File[result.size()]);
- }
-
- /**
- * Recursively list .class files in specified directory
- *
- * @return List of File objects
- */
- public static List<File> listClassFiles(File dir) {
- ArrayList<File> result = new ArrayList<File>();
- if ((null != dir) && dir.canRead()) {
- listClassFiles(dir, result);
- }
- return result;
- }
-
- /**
- * Convert String[] paths to File[] as offset of base directory
- *
- * @param basedir the non-null File base directory for File to create with paths
- * @param paths the String[] of paths to create
- * @return File[] with same length as paths
- */
- public static File[] getBaseDirFiles(File basedir, String[] paths) {
- return getBaseDirFiles(basedir, paths, (String[]) null);
- }
-
- /**
- * Convert String[] paths to File[] as offset of base directory
- *
- * @param basedir the non-null File base directory for File to create with paths
- * @param paths the String[] of paths to create
- * @param suffixes the String[] of suffixes to limit sources to - ignored if null
- * @return File[] with same length as paths
- */
- public static File[] getBaseDirFiles(File basedir, String[] paths, String[] suffixes) {
- LangUtil.throwIaxIfNull(basedir, "basedir");
- LangUtil.throwIaxIfNull(paths, "paths");
- File[] result = null;
- if (!LangUtil.isEmpty(suffixes)) {
- ArrayList<File> list = new ArrayList<File>();
- for (int i = 0; i < paths.length; i++) {
- String path = paths[i];
- for (int j = 0; j < suffixes.length; j++) {
- if (path.endsWith(suffixes[j])) {
- list.add(new File(basedir, paths[i]));
- break;
- }
- }
- }
- result = list.toArray(new File[0]);
- } else {
- result = new File[paths.length];
- for (int i = 0; i < result.length; i++) {
- result[i] = newFile(basedir, paths[i]);
- }
- }
- return result;
- }
-
- /**
- * Create a new File, resolving paths ".." and "." specially.
- *
- * @param dir the File for the parent directory of the file
- * @param path the path in the parent directory (filename only?)
- * @return File for the new file.
- */
- private static File newFile(File dir, String path) {
- if (".".equals(path)) {
- return dir;
- } else if ("..".equals(path)) {
- File parentDir = dir.getParentFile();
- if (null != parentDir) {
- return parentDir;
- } else {
- return new File(dir, "..");
- }
- } else {
- return new File(dir, path);
- }
- }
-
- /**
- * Copy files from source dir into destination directory, creating any needed directories. This differs from copyDir in not
- * being recursive; each input with the source dir creates a full path. However, if the source is a directory, it is copied as
- * such.
- *
- * @param srcDir an existing, readable directory containing relativePaths files
- * @param relativePaths a set of paths relative to srcDir to readable File to copy
- * @param destDir an existing, writable directory to copy files to
- * @throws IllegalArgumentException if input invalid, IOException if operations fail
- */
- public static File[] copyFiles(File srcDir, String[] relativePaths, File destDir) throws IllegalArgumentException, IOException {
- final String[] paths = relativePaths;
- throwIaxUnlessCanReadDir(srcDir, "srcDir");
- throwIaxUnlessCanWriteDir(destDir, "destDir");
- LangUtil.throwIaxIfNull(paths, "relativePaths");
- File[] result = new File[paths.length];
- for (int i = 0; i < paths.length; i++) {
- String path = paths[i];
- LangUtil.throwIaxIfNull(path, "relativePaths-entry");
- File src = newFile(srcDir, paths[i]);
- File dest = newFile(destDir, path);
- File destParent = dest.getParentFile();
- if (!destParent.exists()) {
- destParent.mkdirs();
- }
- LangUtil.throwIaxIfFalse(canWriteDir(destParent), "dest-entry-parent");
- copyFile(src, dest); // both file-dir and dir-dir copies
- result[i] = dest;
- }
- return result;
- }
-
- /**
- * Copy fromFile to toFile, handling file-file, dir-dir, and file-dir copies.
- *
- * @param fromFile the File path of the file or directory to copy - must be readable
- * @param toFile the File path of the target file or directory - must be writable (will be created if it does not exist)
- */
- public static void copyFile(File fromFile, File toFile) throws IOException {
- LangUtil.throwIaxIfNull(fromFile, "fromFile");
- LangUtil.throwIaxIfNull(toFile, "toFile");
- LangUtil.throwIaxIfFalse(!toFile.equals(fromFile), "same file");
- if (toFile.isDirectory()) { // existing directory
- throwIaxUnlessCanWriteDir(toFile, "toFile");
- if (fromFile.isFile()) { // file-dir
- File targFile = new File(toFile, fromFile.getName());
- copyValidFiles(fromFile, targFile);
- } else if (fromFile.isDirectory()) { // dir-dir
- copyDir(fromFile, toFile);
- } else {
- LangUtil.throwIaxIfFalse(false, "not dir or file: " + fromFile);
- }
- } else if (toFile.isFile()) { // target file exists
- if (fromFile.isDirectory()) {
- LangUtil.throwIaxIfFalse(false, "can't copy to file dir: " + fromFile);
- }
- copyValidFiles(fromFile, toFile); // file-file
- } else { // target file is a non-existent path -- could be file or dir
- /* File toFileParent = */ensureParentWritable(toFile);
- if (fromFile.isFile()) {
- copyValidFiles(fromFile, toFile);
- } else if (fromFile.isDirectory()) {
- toFile.mkdirs();
- throwIaxUnlessCanWriteDir(toFile, "toFile");
- copyDir(fromFile, toFile);
- } else {
- LangUtil.throwIaxIfFalse(false, "not dir or file: " + fromFile);
- }
- }
- }
-
- /**
- * Ensure that the parent directory to path can be written. If the path has a null parent, DEFAULT_PARENT is tested. If the path
- * parent does not exist, this tries to create it.
- *
- * @param path the File path whose parent should be writable
- * @return the File path of the writable parent directory
- * @throws IllegalArgumentException if parent cannot be written or path is null.
- */
- public static File ensureParentWritable(File path) {
- LangUtil.throwIaxIfNull(path, "path");
- File pathParent = path.getParentFile();
- if (null == pathParent) {
- pathParent = DEFAULT_PARENT;
- }
- if (!pathParent.canWrite()) {
- pathParent.mkdirs();
- }
- throwIaxUnlessCanWriteDir(pathParent, "pathParent");
- return pathParent;
- }
-
- /**
- * Copy file to file.
- *
- * @param fromFile the File to copy (readable, non-null file)
- * @param toFile the File to copy to (non-null, parent dir exists)
- * @throws IOException
- */
- public static void copyValidFiles(File fromFile, File toFile) throws IOException {
- FileInputStream in = null;
- FileOutputStream out = null;
- try {
- in = new FileInputStream(fromFile);
- out = new FileOutputStream(toFile);
- copyStream(in, out);
- } finally {
- if (out != null) {
- out.close();
- }
- if (in != null) {
- in.close();
- }
- }
- }
-
- /** do line-based copying */
- @SuppressWarnings("deprecation")
- public static void copyStream(DataInputStream in, PrintStream out) throws IOException {
- LangUtil.throwIaxIfNull(in, "in");
- LangUtil.throwIaxIfNull(in, "out");
- String s;
- while (null != (s = in.readLine())) {
- out.println(s);
- }
- }
-
- public static void copyStream(InputStream in, OutputStream out) throws IOException {
- final int MAX = 4096;
- byte[] buf = new byte[MAX];
- for (int bytesRead = in.read(buf, 0, MAX); bytesRead != -1; bytesRead = in.read(buf, 0, MAX)) {
- out.write(buf, 0, bytesRead);
- }
- }
-
- public static void copyStream(Reader in, Writer out) throws IOException {
- final int MAX = 4096;
- char[] buf = new char[MAX];
- for (int bytesRead = in.read(buf, 0, MAX); bytesRead != -1; bytesRead = in.read(buf, 0, MAX)) {
- out.write(buf, 0, bytesRead);
- }
- }
-
- /**
- * Make a new child directory of parent
- *
- * @param parent a File for the parent (writable)
- * @param child a prefix for the child directory
- * @return a File dir that exists with parentDir as the parent file or null
- */
- public static File makeNewChildDir(File parent, String child) {
- if (null == parent || !parent.canWrite() || !parent.isDirectory()) {
- throw new IllegalArgumentException("bad parent: " + parent);
- } else if (null == child) {
- child = "makeNewChildDir";
- } else if (!isValidFileName(child)) {
- throw new IllegalArgumentException("bad child: " + child);
- }
- File result = new File(parent, child);
- int safety = 1000;
- for (String suffix = FileUtil.randomFileString(); ((0 < --safety) && result.exists()); suffix = FileUtil.randomFileString()) {
- result = new File(parent, child + suffix);
- }
- if (result.exists()) {
- System.err.println("exhausted files for child dir in " + parent);
- return null;
- }
- return ((result.mkdirs() && result.exists()) ? result : null);
- }
-
- /**
- * Make a new temporary directory in the same directory that the system uses for temporary files, or if that files, in the
- * current directory.
- *
- * @param name the preferred (simple) name of the directory - may be null.
- * @return File of an existing new temp dir, or null if unable to create
- */
- public static File getTempDir(String name) {
- if (null == name) {
- name = "FileUtil_getTempDir";
- } else if (!isValidFileName(name)) {
- throw new IllegalArgumentException(" invalid: " + name);
- }
- File result = null;
- File tempFile = null;
- try {
- tempFile = File.createTempFile("ignoreMe", ".txt");
- File tempParent = tempFile.getParentFile();
- result = makeNewChildDir(tempParent, name);
- } catch (IOException t) {
- result = makeNewChildDir(new File("."), name);
- } finally {
- if (null != tempFile) {
- tempFile.delete();
- }
- }
- return result;
- }
-
- public static URL[] getFileURLs(File[] files) {
- if ((null == files) || (0 == files.length)) {
- return new URL[0];
- }
- URL[] result = new URL[files.length]; // XXX dangerous non-copy...
- for (int i = 0; i < result.length; i++) {
- result[i] = getFileURL(files[i]);
- }
- return result;
- }
-
- /**
- * Get URL for a File. This appends "/" for directories. prints errors to System.err
- *
- * @param file the File to convert to URL (not null)
- */
- @SuppressWarnings("deprecation")
- public static URL getFileURL(File file) {
- LangUtil.throwIaxIfNull(file, "file");
- URL result = null;
- try {
- result = file.toURL();// TODO AV - was toURI.toURL that does not
- // works on Java 1.3
- if (null != result) {
- return result;
- }
- String url = "file:" + file.getAbsolutePath().replace('\\', '/');
- result = new URL(url + (file.isDirectory() ? "/" : ""));
- } catch (MalformedURLException e) {
- String m = "Util.makeURL(\"" + file.getPath() + "\" MUE " + e.getMessage();
- System.err.println(m);
- }
- return result;
- }
-
- /**
- * Write contents to file, returning null on success or error message otherwise. This tries to make any necessary parent
- * directories first.
- *
- * @param file the File to write (not null)
- * @param contents the String to write (use "" if null)
- * @return String null on no error, error otherwise
- */
- public static String writeAsString(File file, String contents) {
- LangUtil.throwIaxIfNull(file, "file");
- if (null == contents) {
- contents = "";
- }
- Writer out = null;
- try {
- File parentDir = file.getParentFile();
- if (!parentDir.exists() && !parentDir.mkdirs()) {
- return "unable to make parent dir for " + file;
- }
- Reader in = new StringReader(contents);
- out = new FileWriter(file);
- FileUtil.copyStream(in, out);
- return null;
- } catch (IOException e) {
- return LangUtil.unqualifiedClassName(e) + " writing " + file + ": " + e.getMessage();
- } finally {
- if (null != out) {
- try {
- out.close();
- } catch (IOException e) {
- } // ignored
- }
- }
- }
-
- /**
- * Reads a boolean array with our encoding
- */
- public static boolean[] readBooleanArray(DataInputStream s) throws IOException {
- int len = s.readInt();
- boolean[] ret = new boolean[len];
- for (int i = 0; i < len; i++) {
- ret[i] = s.readBoolean();
- }
- return ret;
- }
-
- /**
- * Writes a boolean array with our encoding
- */
- public static void writeBooleanArray(boolean[] a, DataOutputStream s) throws IOException {
- int len = a.length;
- s.writeInt(len);
- for (int i = 0; i < len; i++) {
- s.writeBoolean(a[i]);
- }
- }
-
- /**
- * Reads an int array with our encoding
- */
- public static int[] readIntArray(DataInputStream s) throws IOException {
- int len = s.readInt();
- int[] ret = new int[len];
- for (int i = 0; i < len; i++) {
- ret[i] = s.readInt();
- }
- return ret;
- }
-
- /**
- * Writes an int array with our encoding
- */
- public static void writeIntArray(int[] a, DataOutputStream s) throws IOException {
- int len = a.length;
- s.writeInt(len);
- for (int i = 0; i < len; i++) {
- s.writeInt(a[i]);
- }
- }
-
- /**
- * Reads an int array with our encoding
- */
- public static String[] readStringArray(DataInputStream s) throws IOException {
- int len = s.readInt();
- String[] ret = new String[len];
- for (int i = 0; i < len; i++) {
- ret[i] = s.readUTF();
- }
- return ret;
- }
-
- /**
- * Writes an int array with our encoding
- */
- public static void writeStringArray(String[] a, DataOutputStream s) throws IOException {
- if (a == null) {
- s.writeInt(0);
- return;
- }
- int len = a.length;
- s.writeInt(len);
- for (int i = 0; i < len; i++) {
- s.writeUTF(a[i]);
- }
- }
-
- /**
- * Returns the contents of this file as a String
- */
- public static String readAsString(File file) throws IOException {
- BufferedReader r = new BufferedReader(new FileReader(file));
- StringBuffer b = new StringBuffer();
- while (true) {
- int ch = r.read();
- if (ch == -1) {
- break;
- }
- b.append((char) ch);
- }
- r.close();
- return b.toString();
- }
-
- // /**
- // * Returns the contents of this stream as a String
- // */
- // public static String readAsString(InputStream in) throws IOException {
- // BufferedReader r = new BufferedReader(new InputStreamReader(in));
- // StringBuffer b = new StringBuffer();
- // while (true) {
- // int ch = r.read();
- // if (ch == -1)
- // break;
- // b.append((char) ch);
- // }
- // in.close();
- // r.close();
- // return b.toString();
- // }
-
- /**
- * Returns the contents of this file as a byte[]
- */
- public static byte[] readAsByteArray(File file) throws IOException {
- FileInputStream in = new FileInputStream(file);
- byte[] ret = FileUtil.readAsByteArray(in);
- in.close();
- return ret;
- }
-
- /**
- * Reads this input stream and returns contents as a byte[]
- */
- public static byte[] readAsByteArray(InputStream inStream) throws IOException {
- int size = 1024;
- byte[] ba = new byte[size];
- int readSoFar = 0;
-
- while (true) {
- int nRead = inStream.read(ba, readSoFar, size - readSoFar);
- if (nRead == -1) {
- break;
- }
- readSoFar += nRead;
- if (readSoFar == size) {
- int newSize = size * 2;
- byte[] newBa = new byte[newSize];
- System.arraycopy(ba, 0, newBa, 0, size);
- ba = newBa;
- size = newSize;
- }
- }
-
- byte[] newBa = new byte[readSoFar];
- System.arraycopy(ba, 0, newBa, 0, readSoFar);
- return newBa;
- }
-
- final static String FILECHARS = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
- /** @return semi-random String of length 6 usable as filename suffix */
- static String randomFileString() {
- final double FILECHARS_length = FILECHARS.length();
- final int LEN = 6;
- final char[] result = new char[LEN];
- int index = (int) (Math.random() * 6d);
- for (int i = 0; i < LEN; i++) {
- if (index >= LEN) {
- index = 0;
- }
- result[index++] = FILECHARS.charAt((int) (Math.random() * FILECHARS_length));
- }
- return new String(result);
- }
-
- public static InputStream getStreamFromZip(String zipFile, String name) {
- try {
- ZipFile zf = new ZipFile(zipFile);
- try {
- ZipEntry entry = zf.getEntry(name);
- return zf.getInputStream(entry);
- } finally {
- // ??? is it safe not to close this zf.close();
- }
- } catch (IOException ioe) {
- return null;
- }
- }
-
- //
- // public static void extractJar(String zipFile, String outDir) throws
- // IOException {
- // ZipInputStream zs = new ZipInputStream(new FileInputStream(zipFile));
- // ZipEntry entry;
- // while ((entry = zs.getNextEntry()) != null) {
- // if (entry.isDirectory())
- // continue;
- // byte[] in = readAsByteArray(zs);
- //
- // File outFile = new File(outDir + "/" + entry.getName());
- // // if (!outFile.getParentFile().exists())
- // // System.err.println("parent: " + outFile.getParentFile());
- // // System.err.println("parent: " + outFile.getParentFile());
- // outFile.getParentFile().mkdirs();
- // FileOutputStream os = new FileOutputStream(outFile);
- // os.write(in);
- // os.close();
- // zs.closeEntry();
- // }
- // zs.close();
- // }
-
- /**
- * Do line-based search for literal text in source files, returning file:line where found.
- *
- * @param sought the String text to seek in the file
- * @param sources the List of String paths to the source files
- * @param listAll if false, only list first match in file
- * @param errorSink the PrintStream to print any errors to (one per line) (use null to silently ignore errors)
- * @return List of String of the form file:line for each found entry (never null, might be empty)
- */
- // OPTIMIZE only used by tests? move it out
- public static List<String> lineSeek(String sought, List<String> sources, boolean listAll, PrintStream errorSink) {
- if (LangUtil.isEmpty(sought) || LangUtil.isEmpty(sources)) {
- return Collections.emptyList();
- }
- ArrayList<String> result = new ArrayList<String>();
- for (Iterator<String> iter = sources.iterator(); iter.hasNext();) {
- String path = iter.next();
- String error = lineSeek(sought, path, listAll, result);
- if ((null != error) && (null != errorSink)) {
- errorSink.println(error);
- }
- }
- return result;
- }
-
- /**
- * Do line-based search for literal text in source file, returning line where found as a String in the form
- * {sourcePath}:line:column submitted to the collecting parameter sink. Any error is rendered to String and returned as the
- * result.
- *
- * @param sought the String text to seek in the file
- * @param sources the List of String paths to the source files
- * @param listAll if false, only list first match in file
- * @param List sink the List for String entries of the form {sourcePath}:line:column
- * @return String error if any, or add String entries to sink
- */
- public static String lineSeek(String sought, String sourcePath, boolean listAll, ArrayList<String> sink) {
- if (LangUtil.isEmpty(sought) || LangUtil.isEmpty(sourcePath)) {
- return "nothing sought";
- }
- if (LangUtil.isEmpty(sourcePath)) {
- return "no sourcePath";
- }
- final File file = new File(sourcePath);
- if (!file.canRead() || !file.isFile()) {
- return "sourcePath not a readable file";
- }
- int lineNum = 0;
- FileReader fin = null;
- try {
- fin = new FileReader(file);
- BufferedReader reader = new BufferedReader(fin);
- String line;
- while (null != (line = reader.readLine())) {
- lineNum++;
- int loc = line.indexOf(sought);
- if (-1 != loc) {
- sink.add(sourcePath + ":" + lineNum + ":" + loc);
- if (!listAll) {
- break;
- }
- }
- }
- } catch (IOException e) {
- return LangUtil.unqualifiedClassName(e) + " reading " + sourcePath + ":" + lineNum;
- } finally {
- try {
- if (null != fin) {
- fin.close();
- }
- } catch (IOException e) {
- } // ignore
- }
- return null;
- }
-
- public static BufferedOutputStream makeOutputStream(File file) throws FileNotFoundException {
- File parent = file.getParentFile();
- if (parent != null) {
- parent.mkdirs();
- }
- return new BufferedOutputStream(new FileOutputStream(file));
- }
-
- /**
- * Sleep until after the last last-modified stamp from the files.
- *
- * @param files the File[] of files to inspect for last modified times (this ignores null or empty files array and null or
- * non-existing components of files array)
- * @return true if succeeded without 100 interrupts
- */
- public static boolean sleepPastFinalModifiedTime(File[] files) {
- if ((null == files) || (0 == files.length)) {
- return true;
- }
- long delayUntil = System.currentTimeMillis();
- for (int i = 0; i < files.length; i++) {
- File file = files[i];
- if ((null == file) || !file.exists()) {
- continue;
- }
- long nextModTime = file.lastModified();
- if (nextModTime > delayUntil) {
- delayUntil = nextModTime;
- }
- }
- return LangUtil.sleepUntil(++delayUntil);
- }
-
- private static void listClassFiles(final File baseDir, ArrayList<File> result) {
- File[] files = baseDir.listFiles();
- for (int i = 0; i < files.length; i++) {
- File f = files[i];
- if (f.isDirectory()) {
- listClassFiles(f, result);
- } else {
- if (f.getName().endsWith(".class")) {
- result.add(f);
- }
- }
- }
- }
-
- private static void listFiles(final File baseDir, ArrayList<File> result, FileFilter filter) {
- File[] files = baseDir.listFiles();
- // hack https://bugs.eclipse.org/bugs/show_bug.cgi?id=48650
- final boolean skipCVS = (!PERMIT_CVS && (filter == aspectjSourceFileFilter));
- for (int i = 0; i < files.length; i++) {
- File f = files[i];
- if (f.isDirectory()) {
- if (skipCVS) {
- String name = f.getName().toLowerCase();
- if ("cvs".equals(name) || "sccs".equals(name)) {
- continue;
- }
- }
- listFiles(f, result, filter);
- } else {
- if (filter.accept(f)) {
- result.add(f);
- }
- }
- }
- }
-
- /** @return true if input is not null and contains no path separator */
- private static boolean isValidFileName(String input) {
- return ((null != input) && (-1 == input.indexOf(File.pathSeparator)));
- }
-
- private static void listFiles(final File baseDir, String dir, ArrayList<String> result) {
- final String dirPrefix = (null == dir ? "" : dir + "/");
- final File dirFile = (null == dir ? baseDir : new File(baseDir.getPath() + "/" + dir));
- final String[] files = dirFile.list();
- for (int i = 0; i < files.length; i++) {
- File f = new File(dirFile, files[i]);
- String path = dirPrefix + files[i];
- if (f.isDirectory()) {
- listFiles(baseDir, path, result);
- } else {
- result.add(path);
- }
- }
- }
-
- private FileUtil() {
- }
-
- public static List<String> makeClasspath(URL[] urls) {
- List<String> ret = new LinkedList<String>();
- if (urls != null) {
- for (int i = 0; i < urls.length; i++) {
- ret.add(toPathString(urls[i]));
- }
- }
- return ret;
- }
-
- private static String toPathString(URL url) {
- try {
- return url.toURI().getPath();
- } catch (URISyntaxException e) {
- System.err.println("Warning!! Malformed URL may cause problems: "+url); // TODO: Better way to report this?
- // In this case it was likely not using properly escaped
- // characters so we just use the 'bad' method that doesn't decode
- // special chars
- return url.getPath();
- }
- }
-
- /**
- * A pipe when run reads from an input stream to an output stream, optionally sleeping between reads.
- *
- * @see #copyStream(InputStream, OutputStream)
- */
- public static class Pipe implements Runnable {
- private final InputStream in;
- private final OutputStream out;
- private final long sleep;
- private ByteArrayOutputStream snoop;
- private long totalWritten;
- private Throwable thrown;
- private boolean halt;
- /**
- * Seem to be unable to detect erroroneous closing of System.out...
- */
- private final boolean closeInput;
- private final boolean closeOutput;
-
- /**
- * If true, then continue processing stream until no characters are returned when halting.
- */
- private boolean finishStream;
-
- private boolean done; // true after completing() completes
-
- /**
- * alias for <code>Pipe(in, out, 100l, false, false)</code>
- *
- * @param in the InputStream source to read
- * @param out the OutputStream sink to write
- */
- Pipe(InputStream in, OutputStream out) {
- this(in, out, 100l, false, false);
- }
-
- /**
- * @param in the InputStream source to read
- * @param out the OutputStream sink to write
- * @param tryClosingStreams if true, then try closing both streams when done
- * @param sleep milliseconds to delay between reads (pinned to 0..1 minute)
- */
- Pipe(InputStream in, OutputStream out, long sleep, boolean closeInput, boolean closeOutput) {
- LangUtil.throwIaxIfNull(in, "in");
- LangUtil.throwIaxIfNull(out, "out");
- this.in = in;
- this.out = out;
- this.closeInput = closeInput;
- this.closeOutput = closeOutput;
- this.sleep = Math.min(0l, Math.max(60l * 1000l, sleep));
- }
-
- public void setSnoop(ByteArrayOutputStream snoop) {
- this.snoop = snoop;
- }
-
- /**
- * Run the pipe. This halts on the first Throwable thrown or when a read returns -1 (for end-of-file) or on demand.
- */
- public void run() {
- totalWritten = 0;
- if (halt) {
- return;
- }
- try {
- final int MAX = 4096;
- byte[] buf = new byte[MAX];
- // TODO this blocks, hanging the harness
- int count = in.read(buf, 0, MAX);
- ByteArrayOutputStream mySnoop;
- while ((halt && finishStream && (0 < count)) || (!halt && (-1 != count))) {
- out.write(buf, 0, count);
- mySnoop = snoop;
- if (null != mySnoop) {
- mySnoop.write(buf, 0, count);
- }
- totalWritten += count;
- if (halt && !finishStream) {
- break;
- }
- if (!halt && (0 < sleep)) {
- Thread.sleep(sleep);
- }
- if (halt && !finishStream) {
- break;
- }
- count = in.read(buf, 0, MAX);
- }
- } catch (Throwable e) {
- thrown = e;
- } finally {
- halt = true;
- if (closeInput) {
- try {
- in.close();
- } catch (IOException e) {
- // ignore
- }
- }
- if (closeOutput) {
- try {
- out.close();
- } catch (IOException e) {
- // ignore
- }
- }
- done = true;
- completing(totalWritten, thrown);
- }
-
- }
-
- /**
- * Tell the pipe to halt the next time it gains control.
- *
- * @param wait if true, this waits synchronously until pipe is done
- * @param finishStream if true, then continue until a read from the input stream returns no bytes, then halt.
- * @return true if <code>run()</code> will return the next time it gains control
- */
- public boolean halt(boolean wait, boolean finishStream) {
- if (!halt) {
- halt = true;
- }
- if (wait) {
- while (!done) {
- synchronized (this) {
- notifyAll();
- }
- if (!done) {
- try {
- Thread.sleep(5l);
- } catch (InterruptedException e) {
- break;
- }
- }
- }
- }
- return halt;
- }
-
- /** @return the total number of bytes written */
- public long totalWritten() {
- return totalWritten;
- }
-
- /** @return any exception thrown when reading/writing */
- public Throwable getThrown() {
- return thrown;
- }
-
- /**
- * This is called when the pipe is completing. This implementation does nothing. Subclasses implement this to get notice.
- * Note that halt(true, true) might or might not have completed before this method is called.
- */
- protected void completing(long totalWritten, Throwable thrown) {
- }
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-/**
- * This class implements boolean that include a "maybe"
- */
-public abstract class FuzzyBoolean {
- public abstract boolean alwaysTrue();
- public abstract boolean alwaysFalse();
- public abstract boolean maybeTrue();
- public abstract boolean maybeFalse();
-
- public abstract FuzzyBoolean and(FuzzyBoolean other);
- public abstract FuzzyBoolean or(FuzzyBoolean other);
- public abstract FuzzyBoolean not();
-
- private static class YesFuzzyBoolean extends FuzzyBoolean {
- public boolean alwaysFalse() {
- return false;
- }
-
- public boolean alwaysTrue() {
- return true;
- }
-
- public boolean maybeFalse() {
- return false;
- }
-
- public boolean maybeTrue() {
- return true;
- }
-
- public FuzzyBoolean and(FuzzyBoolean other) {
- return other;
- }
-
- public FuzzyBoolean not() {
- return FuzzyBoolean.NO;
- }
-
- public FuzzyBoolean or(FuzzyBoolean other) {
- return this;
- }
-
- public String toString() {
- return "YES";
- }
- }
- private static class NoFuzzyBoolean extends FuzzyBoolean {
- public boolean alwaysFalse() {
- return true;
- }
-
- public boolean alwaysTrue() {
- return false;
- }
-
-
- public boolean maybeFalse() {
- return true;
- }
-
- public boolean maybeTrue() {
- return false;
- }
-
- public FuzzyBoolean and(FuzzyBoolean other) {
- return this;
- }
-
- public FuzzyBoolean not() {
- return FuzzyBoolean.YES;
- }
-
- public FuzzyBoolean or(FuzzyBoolean other) {
- return other;
- }
-
- public String toString() {
- return "NO";
- }
- }
- private static class NeverFuzzyBoolean extends FuzzyBoolean {
- public boolean alwaysFalse() {
- return true;
- }
-
- public boolean alwaysTrue() {
- return false;
- }
-
-
- public boolean maybeFalse() {
- return true;
- }
-
- public boolean maybeTrue() {
- return false;
- }
-
- public FuzzyBoolean and(FuzzyBoolean other) {
- return this;
- }
-
- public FuzzyBoolean not() {
- return this;
- }
-
- public FuzzyBoolean or(FuzzyBoolean other) {
- return this;
- }
-
- public String toString() {
- return "NEVER";
- }
- }
-
- private static class MaybeFuzzyBoolean extends FuzzyBoolean {
- public boolean alwaysFalse() {
- return false;
- }
-
- public boolean alwaysTrue() {
- return false;
- }
-
-
- public boolean maybeFalse() {
- return true;
- }
-
- public boolean maybeTrue() {
- return true;
- }
-
- public FuzzyBoolean and(FuzzyBoolean other) {
- return other.alwaysFalse() ? other : this;
- }
-
- public FuzzyBoolean not() {
- return this;
- }
-
- public FuzzyBoolean or(FuzzyBoolean other) {
- return other.alwaysTrue() ? other : this;
- }
-
- public String toString() {
- return "MAYBE";
- }
- }
-
- public static final FuzzyBoolean YES = new YesFuzzyBoolean();
- public static final FuzzyBoolean NO = new NoFuzzyBoolean();
- public static final FuzzyBoolean MAYBE = new MaybeFuzzyBoolean();
- public static final FuzzyBoolean NEVER = new NeverFuzzyBoolean();
-
- public static final FuzzyBoolean fromBoolean(boolean b) {
- return b ? YES : NO;
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * 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
- *
- * ******************************************************************/
-package org.aspectj.util;
-
-/**
- * Encapsulate generic signature parsing
- *
- * @author Adrian Colyer
- * @author Andy Clement
- */
-public class GenericSignature {
-
- /**
- * structure holding a parsed class signature
- */
- public static class ClassSignature {
- public FormalTypeParameter[] formalTypeParameters = FormalTypeParameter.NONE;
- public ClassTypeSignature superclassSignature;
- public ClassTypeSignature[] superInterfaceSignatures = ClassTypeSignature.NONE;
-
- public String toString() {
- StringBuffer ret = new StringBuffer();
- ret.append(formalTypeParameters.toString());
- ret.append(superclassSignature.toString());
- for (int i = 0; i < superInterfaceSignatures.length; i++) {
- ret.append(superInterfaceSignatures[i].toString());
- }
- return ret.toString();
- }
- }
-
- public static class MethodTypeSignature {
- public FormalTypeParameter[] formalTypeParameters = new FormalTypeParameter[0];
- public TypeSignature[] parameters = new TypeSignature[0];
- public TypeSignature returnType;
- public FieldTypeSignature[] throwsSignatures = new FieldTypeSignature[0];
-
- public MethodTypeSignature(FormalTypeParameter[] aFormalParameterList, TypeSignature[] aParameterList,
- TypeSignature aReturnType, FieldTypeSignature[] aThrowsSignatureList) {
- this.formalTypeParameters = aFormalParameterList;
- this.parameters = aParameterList;
- this.returnType = aReturnType;
- this.throwsSignatures = aThrowsSignatureList;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- if (formalTypeParameters.length > 0) {
- sb.append("<");
- for (int i = 0; i < formalTypeParameters.length; i++) {
- sb.append(formalTypeParameters[i].toString());
- }
- sb.append(">");
- }
- sb.append("(");
- for (int i = 0; i < parameters.length; i++) {
- sb.append(parameters[i].toString());
- }
- sb.append(")");
- sb.append(returnType.toString());
- for (int i = 0; i < throwsSignatures.length; i++) {
- sb.append("^");
- sb.append(throwsSignatures[i].toString());
- }
- return sb.toString();
- }
- }
-
- /**
- * structure capturing a FormalTypeParameter from the Signature grammar
- */
- public static class FormalTypeParameter {
- public static final FormalTypeParameter[] NONE = new FormalTypeParameter[0];
- public String identifier;
- public FieldTypeSignature classBound;
- public FieldTypeSignature[] interfaceBounds;
-
- public String toString() {
- StringBuffer ret = new StringBuffer();
- ret.append("T");
- ret.append(identifier);
- ret.append(":");
- ret.append(classBound.toString());
- for (int i = 0; i < interfaceBounds.length; i++) {
- ret.append(":");
- ret.append(interfaceBounds[i].toString());
- }
- return ret.toString();
- }
- }
-
- public static abstract class TypeSignature {
- public boolean isBaseType() {
- return false;
- }
- }
-
- public static class BaseTypeSignature extends TypeSignature {
- private final String sig;
-
- public BaseTypeSignature(String aPrimitiveType) {
- sig = aPrimitiveType;
- }
-
- public boolean isBaseType() {
- return true;
- }
-
- public String toString() {
- return sig;
- }
- }
-
- public static abstract class FieldTypeSignature extends TypeSignature {
- public boolean isClassTypeSignature() {
- return false;
- }
-
- public boolean isTypeVariableSignature() {
- return false;
- }
-
- public boolean isArrayTypeSignature() {
- return false;
- }
- }
-
- public static class ClassTypeSignature extends FieldTypeSignature {
-
- public static final ClassTypeSignature[] NONE = new ClassTypeSignature[0];
- public String classSignature;
- public SimpleClassTypeSignature outerType;
- public SimpleClassTypeSignature[] nestedTypes;
-
- public ClassTypeSignature(String sig, String identifier) {
- this.classSignature = sig;
- this.outerType = new SimpleClassTypeSignature(identifier);
- this.nestedTypes = new SimpleClassTypeSignature[0];
- }
-
- public ClassTypeSignature(String sig, SimpleClassTypeSignature outer, SimpleClassTypeSignature[] inners) {
- this.classSignature = sig;
- this.outerType = outer;
- this.nestedTypes = inners;
- }
-
- public boolean isClassTypeSignature() {
- return true;
- }
-
- public String toString() {
- return classSignature;
- }
- }
-
- public static class TypeVariableSignature extends FieldTypeSignature {
- public String typeVariableName;
-
- public TypeVariableSignature(String typeVarToken) {
- this.typeVariableName = typeVarToken.substring(1);
- }
-
- public boolean isTypeVariableSignature() {
- return true;
- }
-
- public String toString() {
- return "T" + typeVariableName + ";";
- }
- }
-
- public static class ArrayTypeSignature extends FieldTypeSignature {
- public TypeSignature typeSig;
-
- public ArrayTypeSignature(TypeSignature aTypeSig) {
- this.typeSig = aTypeSig;
- }
-
- public boolean isArrayTypeSignature() {
- return true;
- }
-
- public String toString() {
- return "[" + typeSig.toString();
- }
- }
-
- public static class SimpleClassTypeSignature {
- public String identifier;
- public TypeArgument[] typeArguments;
-
- public SimpleClassTypeSignature(String identifier) {
- this.identifier = identifier;
- this.typeArguments = new TypeArgument[0];
- }
-
- public SimpleClassTypeSignature(String identifier, TypeArgument[] args) {
- this.identifier = identifier;
- this.typeArguments = args;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(identifier);
- if (typeArguments.length > 0) {
- sb.append("<");
- for (int i = 0; i < typeArguments.length; i++) {
- sb.append(typeArguments[i].toString());
- }
- sb.append(">");
- }
- return sb.toString();
- }
- }
-
- public static class TypeArgument {
- public boolean isWildcard = false;
- public boolean isPlus = false;
- public boolean isMinus = false;
- public FieldTypeSignature signature; // null if isWildcard
-
- public TypeArgument() {
- isWildcard = true;
- }
-
- public TypeArgument(boolean plus, boolean minus, FieldTypeSignature aSig) {
- this.isPlus = plus;
- this.isMinus = minus;
- this.signature = aSig;
- }
-
- public String toString() {
- if (isWildcard)
- return "*";
- StringBuffer sb = new StringBuffer();
- if (isPlus)
- sb.append("+");
- if (isMinus)
- sb.append("-");
- sb.append(signature.toString());
- return sb.toString();
- }
- }
-}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005-2008 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
- *
- * ******************************************************************/
-package org.aspectj.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.aspectj.util.GenericSignature.ArrayTypeSignature;
-import org.aspectj.util.GenericSignature.BaseTypeSignature;
-import org.aspectj.util.GenericSignature.ClassTypeSignature;
-import org.aspectj.util.GenericSignature.FieldTypeSignature;
-import org.aspectj.util.GenericSignature.FormalTypeParameter;
-import org.aspectj.util.GenericSignature.MethodTypeSignature;
-import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
-import org.aspectj.util.GenericSignature.TypeArgument;
-import org.aspectj.util.GenericSignature.TypeSignature;
-import org.aspectj.util.GenericSignature.TypeVariableSignature;
-
-/**
- * Parses the generic signature attribute as defined in the JVM spec.
- *
- * @author Adrian Colyer
- * @author Andy Clement
- */
-public class GenericSignatureParser {
-
- private String inputString;
- private String[] tokenStream; // for parse in flight
- private int tokenIndex = 0;
-
- /**
- * AMC. Parse the signature string interpreting it as a ClassSignature according to the grammar defined in Section 4.4.4 of the
- * JVM specification.
- */
- public GenericSignature.ClassSignature parseAsClassSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- GenericSignature.ClassSignature classSig = new GenericSignature.ClassSignature();
- // FormalTypeParameters-opt
- if (maybeEat("<")) {
- List<FormalTypeParameter> formalTypeParametersList = new ArrayList<FormalTypeParameter>();
- do {
- formalTypeParametersList.add(parseFormalTypeParameter());
- } while (!maybeEat(">"));
- classSig.formalTypeParameters = new FormalTypeParameter[formalTypeParametersList.size()];
- formalTypeParametersList.toArray(classSig.formalTypeParameters);
- }
- classSig.superclassSignature = parseClassTypeSignature();
- List<ClassTypeSignature> superIntSigs = new ArrayList<ClassTypeSignature>();
- while (tokenIndex < tokenStream.length) {
- superIntSigs.add(parseClassTypeSignature());
- }
- classSig.superInterfaceSignatures = new ClassTypeSignature[superIntSigs.size()];
- superIntSigs.toArray(classSig.superInterfaceSignatures);
- return classSig;
- }
-
- /**
- * AMC. Parse the signature string interpreting it as a MethodTypeSignature according to the grammar defined in Section 4.4.4 of
- * the JVM specification.
- */
- public MethodTypeSignature parseAsMethodSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- FormalTypeParameter[] formals = new FormalTypeParameter[0];
- TypeSignature returnType = null;
- // FormalTypeParameters-opt
- if (maybeEat("<")) {
- List<FormalTypeParameter> formalTypeParametersList = new ArrayList<FormalTypeParameter>();
- do {
- formalTypeParametersList.add(parseFormalTypeParameter());
- } while (!maybeEat(">"));
- formals = new FormalTypeParameter[formalTypeParametersList.size()];
- formalTypeParametersList.toArray(formals);
- }
- // Parameters
- eat("(");
- List<TypeSignature> paramList = new ArrayList<TypeSignature>();
- while (!maybeEat(")")) {
- FieldTypeSignature fsig = parseFieldTypeSignature(true);
- if (fsig != null) {
- paramList.add(fsig);
- } else {
- paramList.add(new GenericSignature.BaseTypeSignature(eatIdentifier()));
- }
- }
- TypeSignature[] params = new TypeSignature[paramList.size()];
- paramList.toArray(params);
- // return type
- returnType = parseFieldTypeSignature(true);
- if (returnType == null)
- returnType = new GenericSignature.BaseTypeSignature(eatIdentifier());
- // throws
- List<FieldTypeSignature> throwsList = new ArrayList<FieldTypeSignature>();
- while (maybeEat("^")) {
- FieldTypeSignature fsig = parseFieldTypeSignature(false);
- throwsList.add(fsig);
- }
- FieldTypeSignature[] throwsSigs = new FieldTypeSignature[throwsList.size()];
- throwsList.toArray(throwsSigs);
- return new GenericSignature.MethodTypeSignature(formals, params, returnType, throwsSigs);
- }
-
- /**
- * AMC. Parse the signature string interpreting it as a FieldTypeSignature according to the grammar defined in Section 4.4.4 of
- * the JVM specification.
- */
- public FieldTypeSignature parseAsFieldSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- return parseFieldTypeSignature(false);
- }
-
- private FormalTypeParameter parseFormalTypeParameter() {
- FormalTypeParameter ftp = new FormalTypeParameter();
- // Identifier
- ftp.identifier = eatIdentifier();
- // ClassBound
- eat(":");
- ftp.classBound = parseFieldTypeSignature(true);
- if (ftp.classBound == null) {
- ftp.classBound = new ClassTypeSignature("Ljava/lang/Object;", "Ljava/lang/Object");
- }
- // Optional InterfaceBounds
- List<FieldTypeSignature> optionalBounds = new ArrayList<FieldTypeSignature>();
- while (maybeEat(":")) {
- optionalBounds.add(parseFieldTypeSignature(false));
- }
- ftp.interfaceBounds = new FieldTypeSignature[optionalBounds.size()];
- optionalBounds.toArray(ftp.interfaceBounds);
- return ftp;
- }
-
- private FieldTypeSignature parseFieldTypeSignature(boolean isOptional) {
- if (isOptional) {
- // anything other than 'L', 'T' or '[' and we're out of here
- if (!tokenStream[tokenIndex].startsWith("L") && !tokenStream[tokenIndex].startsWith("T")
- && !tokenStream[tokenIndex].startsWith("[")) {
- return null;
- }
- }
- if (maybeEat("[")) {
- return parseArrayTypeSignature();
- } else if (tokenStream[tokenIndex].startsWith("L")) {
- return parseClassTypeSignature();
- } else if (tokenStream[tokenIndex].startsWith("T")) {
- return parseTypeVariableSignature();
- } else {
- throw new IllegalStateException("Expecting [,L, or T, but found " + tokenStream[tokenIndex] + " while unpacking "
- + inputString);
- }
- }
-
- private ArrayTypeSignature parseArrayTypeSignature() {
- // opening [ already eaten
- FieldTypeSignature fieldType = parseFieldTypeSignature(true);
- if (fieldType != null) {
- return new ArrayTypeSignature(fieldType);
- } else {
- // must be BaseType array
- return new ArrayTypeSignature(new BaseTypeSignature(eatIdentifier()));
- }
- }
-
- // L PackageSpecifier* SimpleClassTypeSignature ClassTypeSignature* ;
- private ClassTypeSignature parseClassTypeSignature() {
- SimpleClassTypeSignature outerType = null;
- SimpleClassTypeSignature[] nestedTypes = new SimpleClassTypeSignature[0];
- StringBuffer ret = new StringBuffer();
- String identifier = eatIdentifier();
- ret.append(identifier);
- while (maybeEat("/")) {
- ret.append("/"); // dont forget this...
- ret.append(eatIdentifier());
- }
- identifier = ret.toString();
- // now we have either a "." indicating the start of a nested type,
- // or a "<" indication type arguments, or ";" and we are done.
- while (!maybeEat(";")) {
- if (tokenStream[tokenIndex].equals(".")) {
- // outer type completed
- outerType = new SimpleClassTypeSignature(identifier);
- nestedTypes = parseNestedTypesHelper(ret);
- } else if (tokenStream[tokenIndex].equals("<")) {
- ret.append("<");
- TypeArgument[] tArgs = maybeParseTypeArguments();
- for (int i = 0; i < tArgs.length; i++) {
- ret.append(tArgs[i].toString());
- }
- ret.append(">");
- outerType = new SimpleClassTypeSignature(identifier, tArgs);
- nestedTypes = parseNestedTypesHelper(ret);
- } else {
- throw new IllegalStateException("Expecting .,<, or ;, but found " + tokenStream[tokenIndex] + " while unpacking "
- + inputString);
- }
- }
- ret.append(";");
- if (outerType == null)
- outerType = new SimpleClassTypeSignature(ret.toString());
- return new ClassTypeSignature(ret.toString(), outerType, nestedTypes);
- }
-
- /**
- * Helper method to digest nested types, slightly more complex than necessary to cope with some android related
- * incorrect classes (see bug 406167)
- */
- private SimpleClassTypeSignature[] parseNestedTypesHelper(StringBuffer ret) {
- boolean brokenSignature = false;
- SimpleClassTypeSignature[] nestedTypes;
- List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
- while (maybeEat(".")) {
- ret.append(".");
- SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
- if (tokenStream[tokenIndex].equals("/")) {
- if (!brokenSignature) {
- System.err.println("[See bug 406167] Bad class file signature encountered, nested types appear package qualified, ignoring those incorrect pieces. Signature: "+inputString);
- }
- brokenSignature = true;
- // hit something like: Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;
- // and we are looking at the '/' after the com
- tokenIndex++; // pointing at the next identifier
- while (tokenStream[tokenIndex+1].equals("/")) {
- tokenIndex+=2; // jump over an 'identifier' '/' pair
- }
- // now tokenIndex is the final bit of the name (which we'll treat as the inner type name)
- sig = parseSimpleClassTypeSignature();
- }
- ret.append(sig.toString());
- nestedTypeList.add(sig);
- };
- nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
- nestedTypeList.toArray(nestedTypes);
- return nestedTypes;
- }
-
- private SimpleClassTypeSignature parseSimpleClassTypeSignature() {
- String identifier = eatIdentifier();
- TypeArgument[] tArgs = maybeParseTypeArguments();
- if (tArgs != null) {
- return new SimpleClassTypeSignature(identifier, tArgs);
- } else {
- return new SimpleClassTypeSignature(identifier);
- }
- }
-
- private TypeArgument parseTypeArgument() {
- boolean isPlus = false;
- boolean isMinus = false;
- if (maybeEat("*")) {
- return new TypeArgument();
- } else if (maybeEat("+")) {
- isPlus = true;
- } else if (maybeEat("-")) {
- isMinus = true;
- }
- FieldTypeSignature sig = parseFieldTypeSignature(false);
- return new TypeArgument(isPlus, isMinus, sig);
- }
-
- private TypeArgument[] maybeParseTypeArguments() {
- if (maybeEat("<")) {
- List<TypeArgument> typeArgs = new ArrayList<TypeArgument>();
- do {
- TypeArgument arg = parseTypeArgument();
- typeArgs.add(arg);
- } while (!maybeEat(">"));
- TypeArgument[] tArgs = new TypeArgument[typeArgs.size()];
- typeArgs.toArray(tArgs);
- return tArgs;
- } else {
- return null;
- }
- }
-
- private TypeVariableSignature parseTypeVariableSignature() {
- TypeVariableSignature tv = new TypeVariableSignature(eatIdentifier());
- eat(";");
- return tv;
- }
-
- private boolean maybeEat(String token) {
- if (tokenStream.length <= tokenIndex)
- return false;
- if (tokenStream[tokenIndex].equals(token)) {
- tokenIndex++;
- return true;
- }
- return false;
- }
-
- private void eat(String token) {
- if (!tokenStream[tokenIndex].equals(token)) {
- throw new IllegalStateException("Expecting " + token + " but found " + tokenStream[tokenIndex] + " while unpacking "
- + inputString);
- }
- tokenIndex++;
- }
-
- private String eatIdentifier() {
- return tokenStream[tokenIndex++];
- }
-
- /**
- * non-private for test visibility Splits a string containing a generic signature into tokens for consumption by the parser.
- */
- public String[] tokenize(String signatureString) {
- char[] chars = signatureString.toCharArray();
- int index = 0;
- List<String> tokens = new ArrayList<String>();
- StringBuffer identifier = new StringBuffer();
- boolean inParens = false;
- boolean inArray = false;
- boolean couldSeePrimitive = false;
- do {
- switch (chars[index]) {
- case '<':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("<");
- break;
- case '>':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(">");
- break;
- case ':':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(":");
- break;
- case '/':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("/");
- couldSeePrimitive = false;
- break;
- case ';':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(";");
- couldSeePrimitive = true;
- inArray = false;
- break;
- case '^':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("^");
- break;
- case '+':
- tokens.add("+");
- break;
- case '-':
- tokens.add("-");
- break;
- case '*':
- tokens.add("*");
- break;
- case '.':
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- identifier = new StringBuffer();
- couldSeePrimitive = false;
- tokens.add(".");
- break;
- case '(':
- tokens.add("(");
- inParens = true;
- couldSeePrimitive = true;
- break;
- case ')':
- tokens.add(")");
- inParens = false;
- break;
- case '[':
- tokens.add("[");
- couldSeePrimitive = true;
- inArray = true;
- break;
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'I':
- case 'J':
- case 'S':
- case 'V':
- case 'Z':
- if ((inParens || inArray) && couldSeePrimitive && identifier.length() == 0) {
- tokens.add(new String("" + chars[index]));
- } else {
- identifier.append(chars[index]);
- }
- inArray = false;
- break;
- case 'L':
- couldSeePrimitive = false;
- // deliberate fall-through
- default:
- identifier.append(chars[index]);
- }
- } while ((++index) < chars.length);
- if (identifier.length() > 0)
- tokens.add(identifier.toString());
- String[] tokenArray = new String[tokens.size()];
- tokens.toArray(tokenArray);
- return tokenArray;
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2008 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:
- * Andy Clement
- * ******************************************************************/
-package org.aspectj.util;
-
-/**
- * Abstraction of a structure model
- *
- * @author Andy Clement
- */
-public interface IStructureModel {
-
-}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 1999-2001 Xerox Corporation,
- * 2002 Palo Alto Research Center, Incorporated (PARC).
- * 2018 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
- * ******************************************************************/
-package org.aspectj.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.security.PrivilegedActionException;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-/**
- *
- */
-public class LangUtil {
-
- public static final String EOL;
-
- public static final String JRT_FS = "jrt-fs.jar";
-
- private static double vmVersion;
-
- /**
- * @return the vm version (1.1, 1.2, 1.3, 1.4, etc)
- */
- public static String getVmVersionString() {
- return Double.toString(vmVersion);
- }
-
- public static double getVmVersion() {
- return vmVersion;
- }
-
- static {
- StringWriter buf = new StringWriter();
- PrintWriter writer = new PrintWriter(buf);
- writer.println("");
- String eol = "\n";
- try {
- buf.close();
- StringBuffer sb = buf.getBuffer();
- if (sb != null) {
- eol = buf.toString();
- }
- } catch (Throwable t) {
- }
- EOL = eol;
- }
-
- static {
- // http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
- // http://openjdk.java.net/jeps/223 "New Version-String Scheme"
- try {
- String vm = System.getProperty("java.version"); // JLS 20.18.7
- if (vm == null) {
- vm = System.getProperty("java.runtime.version");
- }
- if (vm == null) {
- vm = System.getProperty("java.vm.version");
- }
- if (vm == null) {
- new RuntimeException(
- "System properties appear damaged, cannot find: java.version/java.runtime.version/java.vm.version")
- .printStackTrace(System.err);
- vmVersion = 1.5;
- } else {
- // Version: [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
- // Care about the first set of digits and second set if first digit is 1
- try {
- List<Integer> numbers = getFirstNumbers(vm);
- if (numbers.get(0) == 1) {
- // Old school for 1.0 > 1.8
- vmVersion = numbers.get(0)+(numbers.get(1)/10d);
- } else {
- // numbers.get(0) is the major version (9 and above)
- // Note here the number will be 9 (or 10), *not* 1.9 or 1.10
- vmVersion = numbers.get(0);
- }
- } catch (Throwable t) {
- // Give up
- vmVersion = 1.5;
- }
- }
- } catch (Throwable t) {
- new RuntimeException(
- "System properties appear damaged, cannot find: java.version/java.runtime.version/java.vm.version", t)
- .printStackTrace(System.err);
- vmVersion = 1.5;
- }
- }
-
- private static List<Integer> getFirstNumbers(String vm) {
- List<Integer> result = new ArrayList<Integer>();
- StringTokenizer st = new StringTokenizer(vm,".-_");
- try {
- result.add(Integer.parseInt(st.nextToken()));
- result.add(Integer.parseInt(st.nextToken()));
- } catch (Exception e) {
- // NoSuchElementException if no more tokens
- // NumberFormatException if not a number
- }
- return result;
- }
-
- public static boolean is13VMOrGreater() {
- return 1.3 <= vmVersion;
- }
-
- public static boolean is14VMOrGreater() {
- return 1.4 <= vmVersion;
- }
-
- public static boolean is15VMOrGreater() {
- return 1.5 <= vmVersion;
- }
-
- public static boolean is16VMOrGreater() {
- return 1.6 <= vmVersion;
- }
-
- public static boolean is17VMOrGreater() {
- return 1.7 <= vmVersion;
- }
-
- public static boolean is18VMOrGreater() {
- return 1.8 <= vmVersion;
- }
-
- public static boolean is19VMOrGreater() {
- return 9 <= vmVersion;
- }
-
- public static boolean is10VMOrGreater() {
- return 10 <= vmVersion;
- }
-
- public static boolean is11VMOrGreater() {
- return 11 <= vmVersion;
- }
-
- /**
- * Shorthand for "if null, throw IllegalArgumentException"
- *
- * @throws IllegalArgumentException "null {name}" if o is null
- */
- public static final void throwIaxIfNull(final Object o, final String name) {
- if (null == o) {
- String message = "null " + (null == name ? "input" : name);
- throw new IllegalArgumentException(message);
- }
- }
-
- /**
- * Shorthand for "if not null or not assignable, throw IllegalArgumentException"
- *
- * @param c the Class to check - use null to ignore type check
- * @throws IllegalArgumentException "null {name}" if o is null
- */
- public static final void throwIaxIfNotAssignable(final Object ra[], final Class<?> c, final String name) {
- throwIaxIfNull(ra, name);
- String label = (null == name ? "input" : name);
- for (int i = 0; i < ra.length; i++) {
- if (null == ra[i]) {
- String m = " null " + label + "[" + i + "]";
- throw new IllegalArgumentException(m);
- } else if (null != c) {
- Class<?> actualClass = ra[i].getClass();
- if (!c.isAssignableFrom(actualClass)) {
- String message = label + " not assignable to " + c.getName();
- throw new IllegalArgumentException(message);
- }
- }
- }
- }
-
- /**
- * Shorthand for "if not null or not assignable, throw IllegalArgumentException"
- *
- * @throws IllegalArgumentException "null {name}" if o is null
- */
- public static final void throwIaxIfNotAssignable(final Object o, final Class<?> c, final String name) {
- throwIaxIfNull(o, name);
- if (null != c) {
- Class<?> actualClass = o.getClass();
- if (!c.isAssignableFrom(actualClass)) {
- String message = name + " not assignable to " + c.getName();
- throw new IllegalArgumentException(message);
- }
- }
- }
-
- // /**
- // * Shorthand for
- // "if any not null or not assignable, throw IllegalArgumentException"
- // * @throws IllegalArgumentException "{name} is not assignable to {c}"
- // */
- // public static final void throwIaxIfNotAllAssignable(final Collection
- // collection,
- // final Class c, final String name) {
- // throwIaxIfNull(collection, name);
- // if (null != c) {
- // for (Iterator iter = collection.iterator(); iter.hasNext();) {
- // throwIaxIfNotAssignable(iter.next(), c, name);
- //
- // }
- // }
- // }
- /**
- * Shorthand for "if false, throw IllegalArgumentException"
- *
- * @throws IllegalArgumentException "{message}" if test is false
- */
- public static final void throwIaxIfFalse(final boolean test, final String message) {
- if (!test) {
- throw new IllegalArgumentException(message);
- }
- }
-
- // /** @return ((null == s) || (0 == s.trim().length())); */
- // public static boolean isEmptyTrimmed(String s) {
- // return ((null == s) || (0 == s.length())
- // || (0 == s.trim().length()));
- // }
-
- /** @return ((null == s) || (0 == s.length())); */
- public static boolean isEmpty(String s) {
- return ((null == s) || (0 == s.length()));
- }
-
- /** @return ((null == ra) || (0 == ra.length)) */
- public static boolean isEmpty(Object[] ra) {
- return ((null == ra) || (0 == ra.length));
- }
-
- /** @return ((null == ra) || (0 == ra.length)) */
- public static boolean isEmpty(byte[] ra) {
- return ((null == ra) || (0 == ra.length));
- }
-
- /** @return ((null == collection) || (0 == collection.size())) */
- public static boolean isEmpty(Collection<?> collection) {
- return ((null == collection) || (0 == collection.size()));
- }
-
- /** @return ((null == map) || (0 == map.size())) */
- public static boolean isEmpty(Map<?,?> map) {
- return ((null == map) || (0 == map.size()));
- }
-
- /**
- * Splits <code>text</code> at whitespace.
- *
- * @param text <code>String</code> to split.
- */
- public static String[] split(String text) {
- return strings(text).toArray(new String[0]);
- }
-
- /**
- * Splits <code>input</code> at commas, trimming any white space.
- *
- * @param input <code>String</code> to split.
- * @return List of String of elements.
- */
- public static List<String> commaSplit(String input) {
- return anySplit(input, ",");
- }
-
- /**
- * Split string as classpath, delimited at File.pathSeparator. Entries are not trimmed, but empty entries are ignored.
- *
- * @param classpath the String to split - may be null or empty
- * @return String[] of classpath entries
- */
- public static String[] splitClasspath(String classpath) {
- if (LangUtil.isEmpty(classpath)) {
- return new String[0];
- }
- StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator);
- ArrayList<String> result = new ArrayList<String>(st.countTokens());
- while (st.hasMoreTokens()) {
- String entry = st.nextToken();
- if (!LangUtil.isEmpty(entry)) {
- result.add(entry);
- }
- }
- return result.toArray(new String[0]);
- }
-
- /**
- * Get System property as boolean, but use default value where the system property is not set.
- *
- * @return true if value is set to true, false otherwise
- */
- public static boolean getBoolean(String propertyName, boolean defaultValue) {
- if (null != propertyName) {
- try {
- String value = System.getProperty(propertyName);
- if (null != value) {
- return Boolean.valueOf(value).booleanValue();
- }
- } catch (Throwable t) {
- // default below
- }
- }
- return defaultValue;
- }
-
- /**
- * Splits <code>input</code>, removing delimiter and trimming any white space. Returns an empty collection if the input is null.
- * If delimiter is null or empty or if the input contains no delimiters, the input itself is returned after trimming white
- * space.
- *
- * @param input <code>String</code> to split.
- * @param delim <code>String</code> separators for input.
- * @return List of String of elements.
- */
- public static List<String> anySplit(String input, String delim) {
- if (null == input) {
- return Collections.emptyList();
- }
- ArrayList<String> result = new ArrayList<String>();
-
- if (LangUtil.isEmpty(delim) || (-1 == input.indexOf(delim))) {
- result.add(input.trim());
- } else {
- StringTokenizer st = new StringTokenizer(input, delim);
- while (st.hasMoreTokens()) {
- result.add(st.nextToken().trim());
- }
- }
- return result;
- }
-
- /**
- * Splits strings into a <code>List</code> using a <code>StringTokenizer</code>.
- *
- * @param text <code>String</code> to split.
- */
- public static List<String> strings(String text) {
- if (LangUtil.isEmpty(text)) {
- return Collections.emptyList();
- }
- List<String> strings = new ArrayList<String>();
- StringTokenizer tok = new StringTokenizer(text);
- while (tok.hasMoreTokens()) {
- strings.add(tok.nextToken());
- }
- return strings;
- }
-
- /** @return a non-null unmodifiable List */
- public static <T> List<T> safeList(List<T> list) {
- return (null == list ? Collections.<T>emptyList() : Collections.unmodifiableList(list));
- }
-
- // /**
- // * 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]);
- // }
- //
- // /**
- // * 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]);
- // }
-
- /**
- * copy non-null two-dimensional String[][]
- *
- * @see extractOptions(String[], String[][])
- */
- public static String[][] copyStrings(String[][] in) {
- String[][] out = new String[in.length][];
- for (int i = 0; i < out.length; i++) {
- out[i] = new String[in[i].length];
- System.arraycopy(in[i], 0, out[i], 0, out[i].length);
- }
- return out;
- }
-
- /**
- * Extract options and arguments to input option list, returning remainder. The input options will be nullified if not found.
- * e.g.,
- *
- * <pre>
- * String[] options = new String[][] { new String[] { "-verbose" }, new String[] { "-classpath", null } };
- * String[] args = extractOptions(args, options);
- * boolean verbose = null != options[0][0];
- * boolean classpath = options[1][1];
- * </pre>
- *
- * @param args the String[] input options
- * @param options the String[][]options to find in the input args - not null for each String[] component the first subcomponent
- * is the option itself, and there is one String subcomponent for each additional argument.
- * @return String[] of args remaining after extracting options to extracted
- */
- public static String[] extractOptions(String[] args, String[][] options) {
- if (LangUtil.isEmpty(args) || LangUtil.isEmpty(options)) {
- return args;
- }
- BitSet foundSet = new BitSet();
- String[] result = new String[args.length];
- int resultIndex = 0;
- for (int j = 0; j < args.length; j++) {
- boolean found = false;
- for (int i = 0; !found && (i < options.length); i++) {
- String[] option = options[i];
- LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(option), "options");
- String sought = option[0];
- found = sought.equals(args[j]);
- if (found) {
- foundSet.set(i);
- int doMore = option.length - 1;
- if (0 < doMore) {
- final int MAX = j + doMore;
- if (MAX >= args.length) {
- String s = "expecting " + doMore + " args after ";
- throw new IllegalArgumentException(s + args[j]);
- }
- for (int k = 1; k < option.length; k++) {
- option[k] = args[++j];
- }
- }
- }
- }
- if (!found) {
- result[resultIndex++] = args[j];
- }
- }
-
- // unset any not found
- for (int i = 0; i < options.length; i++) {
- if (!foundSet.get(i)) {
- options[i][0] = null;
- }
- }
- // fixup remainder
- if (resultIndex < args.length) {
- String[] temp = new String[resultIndex];
- System.arraycopy(result, 0, temp, 0, resultIndex);
- args = temp;
- }
-
- return args;
- }
-
- //
- // /**
- // * Extract options and arguments to input parameter list, returning
- // remainder.
- // * @param args the String[] input options
- // * @param validOptions the String[] options to find in the input args -
- // not null
- // * @param optionArgs the int[] number of arguments for each option in
- // validOptions
- // * (if null, then no arguments for any option)
- // * @param extracted the List for the matched options
- // * @return String[] of args remaining after extracting options to
- // extracted
- // */
- // public static String[] extractOptions(String[] args, String[]
- // validOptions,
- // int[] optionArgs, List extracted) {
- // if (LangUtil.isEmpty(args)
- // || LangUtil.isEmpty(validOptions) ) {
- // return args;
- // }
- // if (null != optionArgs) {
- // if (optionArgs.length != validOptions.length) {
- // throw new IllegalArgumentException("args must match options");
- // }
- // }
- // String[] result = new String[args.length];
- // int resultIndex = 0;
- // for (int j = 0; j < args.length; j++) {
- // boolean found = false;
- // for (int i = 0; !found && (i < validOptions.length); i++) {
- // String sought = validOptions[i];
- // int doMore = (null == optionArgs ? 0 : optionArgs[i]);
- // if (LangUtil.isEmpty(sought)) {
- // continue;
- // }
- // found = sought.equals(args[j]);
- // if (found) {
- // if (null != extracted) {
- // extracted.add(sought);
- // }
- // if (0 < doMore) {
- // final int MAX = j + doMore;
- // if (MAX >= args.length) {
- // String s = "expecting " + doMore + " args after ";
- // throw new IllegalArgumentException(s + args[j]);
- // }
- // if (null != extracted) {
- // while (j < MAX) {
- // extracted.add(args[++j]);
- // }
- // } else {
- // j = MAX;
- // }
- // }
- // break;
- // }
- // }
- // if (!found) {
- // result[resultIndex++] = args[j];
- // }
- // }
- // if (resultIndex < args.length) {
- // String[] temp = new String[resultIndex];
- // System.arraycopy(result, 0, temp, 0, resultIndex);
- // args = temp;
- // }
- // return args;
- // }
-
- // /** @return String[] of entries in validOptions found in args */
- // public static String[] selectOptions(String[] args, String[]
- // validOptions) {
- // if (LangUtil.isEmpty(args) || LangUtil.isEmpty(validOptions)) {
- // return new String[0];
- // }
- // ArrayList result = new ArrayList();
- // for (int i = 0; i < validOptions.length; i++) {
- // String sought = validOptions[i];
- // if (LangUtil.isEmpty(sought)) {
- // continue;
- // }
- // for (int j = 0; j < args.length; j++) {
- // if (sought.equals(args[j])) {
- // result.add(sought);
- // break;
- // }
- // }
- // }
- // return (String[]) result.toArray(new String[0]);
- // }
-
- // /** @return String[] of entries in validOptions found in args */
- // public static String[] selectOptions(List args, String[] validOptions) {
- // if (LangUtil.isEmpty(args) || LangUtil.isEmpty(validOptions)) {
- // return new String[0];
- // }
- // ArrayList result = new ArrayList();
- // for (int i = 0; i < validOptions.length; i++) {
- // String sought = validOptions[i];
- // if (LangUtil.isEmpty(sought)) {
- // continue;
- // }
- // for (Iterator iter = args.iterator(); iter.hasNext();) {
- // String arg = (String) iter.next();
- // if (sought.equals(arg)) {
- // result.add(sought);
- // break;
- // }
- // }
- // }
- // return (String[]) result.toArray(new String[0]);
- // }
-
- // /**
- // * 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 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] = (String[]) 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;
- // }
-
- // /**
- // * 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;
- // }
-
- /**
- * Convert arrays safely. The number of elements in the result will be 1 smaller for each element that is null or not
- * assignable. This will use sink if it has exactly the right size. The result will always have the same component type as sink.
- *
- * @return an array with the same component type as sink containing any assignable elements in source (in the same order).
- * @throws IllegalArgumentException if either is null
- */
- public static Object[] safeCopy(Object[] source, Object[] sink) {
- final Class<?> sinkType = (null == sink ? Object.class : sink.getClass().getComponentType());
- final int sourceLength = (null == source ? 0 : source.length);
- final int sinkLength = (null == sink ? 0 : sink.length);
-
- final int resultSize;
- ArrayList<Object> result = null;
- if (0 == sourceLength) {
- resultSize = 0;
- } else {
- result = new ArrayList<Object>(sourceLength);
- for (int i = 0; i < sourceLength; i++) {
- if ((null != source[i]) && (sinkType.isAssignableFrom(source[i].getClass()))) {
- result.add(source[i]);
- }
- }
- resultSize = result.size();
- }
- if (resultSize != sinkLength) {
- sink = (Object[]) Array.newInstance(sinkType, result.size());
- }
- if (0 < resultSize) {
- sink = result.toArray(sink);
- }
- return sink;
- }
-
- /**
- * @return a String with the unqualified class name of the class (or "null")
- */
- public static String unqualifiedClassName(Class<?> c) {
- if (null == c) {
- return "null";
- }
- String name = c.getName();
- int loc = name.lastIndexOf(".");
- if (-1 != loc) {
- name = name.substring(1 + loc);
- }
- return name;
- }
-
- /**
- * @return a String with the unqualified class name of the object (or "null")
- */
- public static String unqualifiedClassName(Object o) {
- return LangUtil.unqualifiedClassName(null == o ? null : o.getClass());
- }
-
- /** inefficient way to replace all instances of sought with replace */
- public static String replace(String in, String sought, String replace) {
- if (LangUtil.isEmpty(in) || LangUtil.isEmpty(sought)) {
- return in;
- }
- StringBuffer result = new StringBuffer();
- final int len = sought.length();
- int start = 0;
- int loc;
- while (-1 != (loc = in.indexOf(sought, start))) {
- result.append(in.substring(start, loc));
- if (!LangUtil.isEmpty(replace)) {
- result.append(replace);
- }
- start = loc + len;
- }
- result.append(in.substring(start));
- return result.toString();
- }
-
- /** render i right-justified with a given width less than about 40 */
- public static String toSizedString(long i, int width) {
- String result = "" + i;
- int size = result.length();
- if (width > size) {
- final String pad = " ";
- final int padLength = pad.length();
- if (width > padLength) {
- width = padLength;
- }
- int topad = width - size;
- result = pad.substring(0, topad) + result;
- }
- return result;
- }
-
- // /** clip StringBuffer to maximum number of lines */
- // static String clipBuffer(StringBuffer buffer, int maxLines) {
- // if ((null == buffer) || (1 > buffer.length())) return "";
- // StringBuffer result = new StringBuffer();
- // int j = 0;
- // final int MAX = maxLines;
- // final int N = buffer.length();
- // for (int i = 0, srcBegin = 0; i < MAX; srcBegin += j) {
- // // todo: replace with String variant if/since getting char?
- // char[] chars = new char[128];
- // int srcEnd = srcBegin+chars.length;
- // if (srcEnd >= N) {
- // srcEnd = N-1;
- // }
- // if (srcBegin == srcEnd) break;
- // //log("srcBegin:" + srcBegin + ":srcEnd:" + srcEnd);
- // buffer.getChars(srcBegin, srcEnd, chars, 0);
- // for (j = 0; j < srcEnd-srcBegin/*chars.length*/; j++) {
- // char c = chars[j];
- // if (c == '\n') {
- // i++;
- // j++;
- // break;
- // }
- // }
- // try { result.append(chars, 0, j); }
- // catch (Throwable t) { }
- // }
- // return result.toString();
- // }
-
- /**
- * @return "({UnqualifiedExceptionClass}) {message}"
- */
- public static String renderExceptionShort(Throwable e) {
- if (null == e) {
- return "(Throwable) null";
- }
- return "(" + LangUtil.unqualifiedClassName(e) + ") " + e.getMessage();
- }
-
- /**
- * Renders exception <code>t</code> after unwrapping and eliding any test packages.
- *
- * @param t <code>Throwable</code> to print.
- * @see #maxStackTrace
- */
- public static String renderException(Throwable t) {
- return renderException(t, true);
- }
-
- /**
- * Renders exception <code>t</code>, unwrapping, optionally eliding and limiting total number of lines.
- *
- * @param t <code>Throwable</code> to print.
- * @param elide true to limit to 100 lines and elide test packages
- * @see StringChecker#TEST_PACKAGES
- */
- public static String renderException(Throwable t, boolean elide) {
- if (null == t) {
- return "null throwable";
- }
- t = unwrapException(t);
- StringBuffer stack = stackToString(t, false);
- if (elide) {
- elideEndingLines(StringChecker.TEST_PACKAGES, stack, 100);
- }
- return stack.toString();
- }
-
- /**
- * Trim ending lines from a StringBuffer, clipping to maxLines and further removing any number of trailing lines accepted by
- * checker.
- *
- * @param checker returns true if trailing line should be elided.
- * @param stack StringBuffer with lines to elide
- * @param maxLines int for maximum number of resulting lines
- */
- static void elideEndingLines(StringChecker checker, StringBuffer stack, int maxLines) {
- if (null == checker || (null == stack) || (0 == stack.length())) {
- return;
- }
- final LinkedList<String> lines = new LinkedList<String>();
- StringTokenizer st = new StringTokenizer(stack.toString(), "\n\r");
- while (st.hasMoreTokens() && (0 < --maxLines)) {
- lines.add(st.nextToken());
- }
- st = null;
-
- String line;
- int elided = 0;
- while (!lines.isEmpty()) {
- line = lines.getLast();
- if (!checker.acceptString(line)) {
- break;
- } else {
- elided++;
- lines.removeLast();
- }
- }
- if ((elided > 0) || (maxLines < 1)) {
- final int EOL_LEN = EOL.length();
- int totalLength = 0;
- while (!lines.isEmpty()) {
- totalLength += EOL_LEN + lines.getFirst().length();
- lines.removeFirst();
- }
- if (stack.length() > totalLength) {
- stack.setLength(totalLength);
- if (elided > 0) {
- stack.append(" (... " + elided + " lines...)");
- }
- }
- }
- }
-
- /** Dump message and stack to StringBuffer. */
- public static StringBuffer stackToString(Throwable throwable, boolean skipMessage) {
- if (null == throwable) {
- return new StringBuffer();
- }
- StringWriter buf = new StringWriter();
- PrintWriter writer = new PrintWriter(buf);
- if (!skipMessage) {
- writer.println(throwable.getMessage());
- }
- throwable.printStackTrace(writer);
- try {
- buf.close();
- } catch (IOException ioe) {
- } // ignored
- return buf.getBuffer();
- }
-
- /** @return Throwable input or tail of any wrapped exception chain */
- public static Throwable unwrapException(Throwable t) {
- Throwable current = t;
- Throwable next = null;
- while (current != null) {
- // Java 1.2 exceptions that carry exceptions
- if (current instanceof InvocationTargetException) {
- next = ((InvocationTargetException) current).getTargetException();
- } else if (current instanceof ClassNotFoundException) {
- next = ((ClassNotFoundException) current).getException();
- } else if (current instanceof ExceptionInInitializerError) {
- next = ((ExceptionInInitializerError) current).getException();
- } else if (current instanceof PrivilegedActionException) {
- next = ((PrivilegedActionException) current).getException();
- } else if (current instanceof SQLException) {
- next = ((SQLException) current).getNextException();
- }
- // ...getException():
- // javax.naming.event.NamingExceptionEvent
- // javax.naming.ldap.UnsolicitedNotification
- // javax.xml.parsers.FactoryConfigurationError
- // javax.xml.transform.TransformerFactoryConfigurationError
- // javax.xml.transform.TransformerException
- // org.xml.sax.SAXException
- // 1.4: Throwable.getCause
- // java.util.logging.LogRecord.getThrown()
- if (null == next) {
- break;
- } else {
- current = next;
- next = null;
- }
- }
- return current;
- }
-
- /**
- * Replacement for Arrays.asList(..) which gacks on null and returns a List in which remove is an unsupported operation.
- *
- * @param array the Object[] to convert (may be null)
- * @return the List corresponding to array (never null)
- */
- public static <T> List<T> arrayAsList(T[] array) {
- if ((null == array) || (1 > array.length)) {
- return Collections.emptyList();
- }
- ArrayList<T> list = new ArrayList<T>();
- list.addAll(Arrays.asList(array));
- return list;
- }
-
- /** check if input contains any packages to elide. */
- public static class StringChecker {
- static StringChecker TEST_PACKAGES = new StringChecker(new String[] { "org.aspectj.testing",
- "org.eclipse.jdt.internal.junit", "junit.framework.",
- "org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" });
-
- String[] infixes;
-
- /** @param infixes adopted */
- StringChecker(String[] infixes) {
- this.infixes = infixes;
- }
-
- /** @return true if input contains infixes */
- public boolean acceptString(String input) {
- boolean result = false;
- if (!LangUtil.isEmpty(input)) {
- for (int i = 0; !result && (i < infixes.length); i++) {
- result = (-1 != input.indexOf(infixes[i]));
- }
- }
- return result;
- }
- }
-
- /**
- * Gen classpath.
- *
- * @param bootclasspath
- * @param classpath
- * @param classesDir
- * @param outputJar
- * @return String combining classpath elements
- */
- public static String makeClasspath( // XXX dumb implementation
- String bootclasspath, String classpath, String classesDir, String outputJar) {
- StringBuffer sb = new StringBuffer();
- addIfNotEmpty(bootclasspath, sb, File.pathSeparator);
- addIfNotEmpty(classpath, sb, File.pathSeparator);
- if (!addIfNotEmpty(classesDir, sb, File.pathSeparator)) {
- addIfNotEmpty(outputJar, sb, File.pathSeparator);
- }
- return sb.toString();
- }
-
- /**
- * @param input ignored if null
- * @param sink the StringBuffer to add input to - return false if null
- * @param delimiter the String to append to input when added - ignored if empty
- * @return true if input + delimiter added to sink
- */
- private static boolean addIfNotEmpty(String input, StringBuffer sink, String delimiter) {
- if (LangUtil.isEmpty(input) || (null == sink)) {
- return false;
- }
- sink.append(input);
- if (!LangUtil.isEmpty(delimiter)) {
- sink.append(delimiter);
- }
- return true;
- }
-
- /**
- * Create or initialize a process controller to run a process in another VM asynchronously.
- *
- * @param controller the ProcessController to initialize, if not null
- * @param classpath
- * @param mainClass
- * @param args
- * @return initialized ProcessController
- */
- public static ProcessController makeProcess(ProcessController controller, String classpath, String mainClass, String[] args) {
- File java = LangUtil.getJavaExecutable();
- ArrayList<String> cmd = new ArrayList<String>();
- cmd.add(java.getAbsolutePath());
- cmd.add("-classpath");
- cmd.add(classpath);
- cmd.add(mainClass);
- if (!LangUtil.isEmpty(args)) {
- cmd.addAll(Arrays.asList(args));
- }
- String[] command = cmd.toArray(new String[0]);
- if (null == controller) {
- controller = new ProcessController();
- }
- controller.init(command, mainClass);
- return controller;
- }
-
- // /**
- // * Create a process to run asynchronously.
- // * @param controller if not null, initialize this one
- // * @param command the String[] command to run
- // * @param controller the ProcessControl for streams and results
- // */
- // public static ProcessController makeProcess( // not needed?
- // ProcessController controller,
- // String[] command,
- // String label) {
- // if (null == controller) {
- // controller = new ProcessController();
- // }
- // controller.init(command, label);
- // return controller;
- // }
-
- /**
- * Find java executable File path from java.home system property.
- *
- * @return File associated with the java command, or null if not found.
- */
- public static File getJavaExecutable() {
- String javaHome = null;
- File result = null;
- // java.home
- // java.class.path
- // java.ext.dirs
- try {
- javaHome = System.getProperty("java.home");
- } catch (Throwable t) {
- // ignore
- }
- if (null != javaHome) {
- File binDir = new File(javaHome, "bin");
- if (binDir.isDirectory() && binDir.canRead()) {
- String[] execs = new String[] { "java", "java.exe" };
- for (int i = 0; i < execs.length; i++) {
- result = new File(binDir, execs[i]);
- if (result.canRead()) {
- break;
- }
- }
- }
- }
- return result;
- }
-
- // /**
- // * Sleep for a particular period (in milliseconds).
- // *
- // * @param time the long time in milliseconds to sleep
- // * @return true if delay succeeded, false if interrupted 100 times
- // */
- // public static boolean sleep(long milliseconds) {
- // if (milliseconds == 0) {
- // return true;
- // } else if (milliseconds < 0) {
- // throw new IllegalArgumentException("negative: " + milliseconds);
- // }
- // return sleepUntil(milliseconds + System.currentTimeMillis());
- // }
-
- /**
- * Sleep until a particular time.
- *
- * @param time the long time in milliseconds to sleep until
- * @return true if delay succeeded, false if interrupted 100 times
- */
- public static boolean sleepUntil(long time) {
- if (time == 0) {
- return true;
- } else if (time < 0) {
- throw new IllegalArgumentException("negative: " + time);
- }
- // final Thread thread = Thread.currentThread();
- long curTime = System.currentTimeMillis();
- for (int i = 0; (i < 100) && (curTime < time); i++) {
- try {
- Thread.sleep(time - curTime);
- } catch (InterruptedException e) {
- // ignore
- }
- curTime = System.currentTimeMillis();
- }
- return (curTime >= time);
- }
-
- /**
- * Handle an external process asynchrously. <code>start()</code> launches a main thread to wait for the process and pipes
- * streams (in child threads) through to the corresponding streams (e.g., the process System.err to this System.err). This can
- * complete normally, by exception, or on demand by a client. Clients can implement <code>doCompleting(..)</code> to get notice
- * when the process completes.
- * <p>
- * The following sample code creates a process with a completion callback starts it, and some time later retries the process.
- *
- * <pre>
- * LangUtil.ProcessController controller = new LangUtil.ProcessController() {
- * protected void doCompleting(LangUtil.ProcessController.Thrown thrown, int result) {
- * // signal result
- * }
- * };
- * controller.init(new String[] { "java", "-version" }, "java version");
- * controller.start();
- * // some time later...
- * // retry...
- * if (!controller.completed()) {
- * controller.stop();
- * controller.reinit();
- * controller.start();
- * }
- * </pre>
- *
- * <u>warning</u>: Currently this does not close the input or output streams, since doing so prevents their use later.
- */
- public static class ProcessController {
- /*
- * XXX not verified thread-safe, but should be. Known problems: - user stops (completed = true) then exception thrown from
- * destroying process (stop() expects !completed) ...
- */
- private String[] command;
- private String[] envp;
- private String label;
-
- private boolean init;
- private boolean started;
- private boolean completed;
- /** if true, stopped by user when not completed */
- private boolean userStopped;
-
- private Process process;
- private FileUtil.Pipe errStream;
- private FileUtil.Pipe outStream;
- private FileUtil.Pipe inStream;
- private ByteArrayOutputStream errSnoop;
- private ByteArrayOutputStream outSnoop;
-
- private int result;
- private Thrown thrown;
-
- public ProcessController() {
- }
-
- /**
- * Permit re-running using the same command if this is not started or if completed. Can also call this when done with
- * results to release references associated with results (e.g., stack traces).
- */
- public final void reinit() {
- if (!init) {
- throw new IllegalStateException("must init(..) before reinit()");
- }
- if (started && !completed) {
- throw new IllegalStateException("not completed - do stop()");
- }
- // init everything but command and label
- started = false;
- completed = false;
- result = Integer.MIN_VALUE;
- thrown = null;
- process = null;
- errStream = null;
- outStream = null;
- inStream = null;
- }
-
- public final void init(String classpath, String mainClass, String[] args) {
- init(LangUtil.getJavaExecutable(), classpath, mainClass, args);
- }
-
- public final void init(File java, String classpath, String mainClass, String[] args) {
- LangUtil.throwIaxIfNull(java, "java");
- LangUtil.throwIaxIfNull(mainClass, "mainClass");
- LangUtil.throwIaxIfNull(args, "args");
- ArrayList<String> cmd = new ArrayList<String>();
- cmd.add(java.getAbsolutePath());
- cmd.add("-classpath");
- cmd.add(classpath);
- cmd.add(mainClass);
- if (!LangUtil.isEmpty(args)) {
- cmd.addAll(Arrays.asList(args));
- }
- init(cmd.toArray(new String[0]), mainClass);
- }
-
- public final void init(String[] command, String label) {
- this.command = (String[]) LangUtil.safeCopy(command, new String[0]);
- if (1 > this.command.length) {
- throw new IllegalArgumentException("empty command");
- }
- this.label = LangUtil.isEmpty(label) ? command[0] : label;
- init = true;
- reinit();
- }
-
- public final void setEnvp(String[] envp) {
- this.envp = (String[]) LangUtil.safeCopy(envp, new String[0]);
- if (1 > this.envp.length) {
- throw new IllegalArgumentException("empty envp");
- }
- }
-
- public final void setErrSnoop(ByteArrayOutputStream snoop) {
- errSnoop = snoop;
- if (null != errStream) {
- errStream.setSnoop(errSnoop);
- }
- }
-
- public final void setOutSnoop(ByteArrayOutputStream snoop) {
- outSnoop = snoop;
- if (null != outStream) {
- outStream.setSnoop(outSnoop);
- }
- }
-
- /**
- * Start running the process and pipes asynchronously.
- *
- * @return Thread started or null if unable to start thread (results available via <code>getThrown()</code>, etc.)
- */
- public final Thread start() {
- if (!init) {
- throw new IllegalStateException("not initialized");
- }
- synchronized (this) {
- if (started) {
- throw new IllegalStateException("already started");
- }
- started = true;
- }
- try {
- process = Runtime.getRuntime().exec(command);
- } catch (IOException e) {
- stop(e, Integer.MIN_VALUE);
- return null;
- }
- errStream = new FileUtil.Pipe(process.getErrorStream(), System.err);
- if (null != errSnoop) {
- errStream.setSnoop(errSnoop);
- }
- outStream = new FileUtil.Pipe(process.getInputStream(), System.out);
- if (null != outSnoop) {
- outStream.setSnoop(outSnoop);
- }
- inStream = new FileUtil.Pipe(System.in, process.getOutputStream());
- // start 4 threads, process & pipes for in, err, out
- Runnable processRunner = new Runnable() {
- @Override
- public void run() {
- Throwable thrown = null;
- int result = Integer.MIN_VALUE;
- try {
- // pipe threads are children
- new Thread(errStream).start();
- new Thread(outStream).start();
- new Thread(inStream).start();
- process.waitFor();
- result = process.exitValue();
- } catch (Throwable e) {
- thrown = e;
- } finally {
- stop(thrown, result);
- }
- }
- };
- Thread result = new Thread(processRunner, label);
- result.start();
- return result;
- }
-
- /**
- * Destroy any process, stop any pipes. This waits for the pipes to clear (reading until no more input is available), but
- * does not wait for the input stream for the pipe to close (i.e., not waiting for end-of-file on input stream).
- */
- public final synchronized void stop() {
- if (completed) {
- return;
- }
- userStopped = true;
- stop(null, Integer.MIN_VALUE);
- }
-
- public final String[] getCommand() {
- String[] toCopy = command;
- if (LangUtil.isEmpty(toCopy)) {
- return new String[0];
- }
- String[] result = new String[toCopy.length];
- System.arraycopy(toCopy, 0, result, 0, result.length);
- return result;
- }
-
- public final boolean completed() {
- return completed;
- }
-
- public final boolean started() {
- return started;
- }
-
- public final boolean userStopped() {
- return userStopped;
- }
-
- /**
- * Get any Throwable thrown. Note that the process can complete normally (with a valid return value), at the same time the
- * pipes throw exceptions, and that this may return some exceptions even if the process is not complete.
- *
- * @return null if not complete or Thrown containing exceptions thrown by the process and streams.
- */
- public final Thrown getThrown() { // cache this
- return makeThrown(null);
- }
-
- public final int getResult() {
- return result;
- }
-
- /**
- * Subclasses implement this to get synchronous notice of completion. All pipes and processes should be complete at this
- * time. To get the exceptions thrown for the pipes, use <code>getThrown()</code>. If there is an exception, the process
- * completed abruptly (including side-effects of the user halting the process). If <code>userStopped()</code> is true, then
- * some client asked that the process be destroyed using <code>stop()</code>. Otherwise, the result code should be the
- * result value returned by the process.
- *
- * @param thrown same as <code>getThrown().fromProcess</code>.
- * @param result same as <code>getResult()</code>
- * @see getThrown()
- * @see getResult()
- * @see stop()
- */
- protected void doCompleting(Thrown thrown, int result) {
- }
-
- /**
- * Handle termination (on-demand, abrupt, or normal) by destroying and/or halting process and pipes.
- *
- * @param thrown ignored if null
- * @param result ignored if Integer.MIN_VALUE
- */
- private final synchronized void stop(Throwable thrown, int result) {
- if (completed) {
- throw new IllegalStateException("already completed");
- } else if (null != this.thrown) {
- throw new IllegalStateException("already set thrown: " + thrown);
- }
- // assert null == this.thrown
- this.thrown = makeThrown(thrown);
- if (null != process) {
- process.destroy();
- }
- if (null != inStream) {
- inStream.halt(false, true); // this will block if waiting
- inStream = null;
- }
- if (null != outStream) {
- outStream.halt(true, true);
- outStream = null;
- }
- if (null != errStream) {
- errStream.halt(true, true);
- errStream = null;
- }
- if (Integer.MIN_VALUE != result) {
- this.result = result;
- }
- completed = true;
- doCompleting(this.thrown, result);
- }
-
- /**
- * Create snapshot of Throwable's thrown.
- *
- * @param thrown ignored if null or if this.thrown is not null
- */
- private final synchronized Thrown makeThrown(Throwable processThrown) {
- if (null != thrown) {
- return thrown;
- }
- return new Thrown(processThrown, (null == outStream ? null : outStream.getThrown()), (null == errStream ? null
- : errStream.getThrown()), (null == inStream ? null : inStream.getThrown()));
- }
-
- public static class Thrown {
- public final Throwable fromProcess;
- public final Throwable fromErrPipe;
- public final Throwable fromOutPipe;
- public final Throwable fromInPipe;
- /** true only if some Throwable is not null */
- public final boolean thrown;
-
- private Thrown(Throwable fromProcess, Throwable fromOutPipe, Throwable fromErrPipe, Throwable fromInPipe) {
- this.fromProcess = fromProcess;
- this.fromErrPipe = fromErrPipe;
- this.fromOutPipe = fromOutPipe;
- this.fromInPipe = fromInPipe;
- thrown = ((null != fromProcess) || (null != fromInPipe) || (null != fromOutPipe) || (null != fromErrPipe));
- }
-
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer();
- append(sb, fromProcess, "process");
- append(sb, fromOutPipe, " stdout");
- append(sb, fromErrPipe, " stderr");
- append(sb, fromInPipe, " stdin");
- if (0 == sb.length()) {
- return "Thrown (none)";
- } else {
- return sb.toString();
- }
- }
-
- private void append(StringBuffer sb, Throwable thrown, String label) {
- if (null != thrown) {
- sb.append("from " + label + ": ");
- sb.append(LangUtil.renderExceptionShort(thrown));
- sb.append(LangUtil.EOL);
- }
- }
- } // class Thrown
- }
-
- public static String getJrtFsFilePath() {
- return getJavaHome() + File.separator + "lib" + File.separator + JRT_FS;
- }
-
- public static String getJavaHome() {
- return System.getProperty("java.home");
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * This class implements a partial order
- *
- * It includes routines for doing a topo-sort
- */
-
-public class PartialOrder {
-
- /**
- * All classes that want to be part of a partial order must implement PartialOrder.PartialComparable.
- */
- public static interface PartialComparable {
- /**
- * @returns <ul>
- * <li>+1 if this is greater than other</li>
- * <li>-1 if this is less than other</li>
- * <li>0 if this is not comparable to other</li>
- * </ul>
- *
- * <b> Note: returning 0 from this method doesn't mean the same thing as returning 0 from
- * java.util.Comparable.compareTo()</b>
- */
- public int compareTo(Object other);
-
- /**
- * This method can provide a deterministic ordering for elements that are strictly not comparable. If you have no need for
- * this, this method can just return 0 whenever called.
- */
- public int fallbackCompareTo(Object other);
- }
-
- private static class SortObject<T extends PartialComparable> {
- T object;
- List<SortObject<T>> smallerObjects = new LinkedList<SortObject<T>>();
- List<SortObject<T>> biggerObjects = new LinkedList<SortObject<T>>();
-
- public SortObject(T o) {
- object = o;
- }
-
- boolean hasNoSmallerObjects() {
- return smallerObjects.size() == 0;
- }
-
- boolean removeSmallerObject(SortObject<T> o) {
- smallerObjects.remove(o);
- return hasNoSmallerObjects();
- }
-
- void addDirectedLinks(SortObject<T> other) {
- int cmp = object.compareTo(other.object);
- if (cmp == 0) {
- return;
- }
- if (cmp > 0) {
- this.smallerObjects.add(other);
- other.biggerObjects.add(this);
- } else {
- this.biggerObjects.add(other);
- other.smallerObjects.add(this);
- }
- }
-
- public String toString() {
- return object.toString(); // +smallerObjects+biggerObjects;
- }
- }
-
- private static <T extends PartialComparable> void addNewPartialComparable(List<SortObject<T>> graph, T o) {
- SortObject<T> so = new SortObject<T>(o);
- for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
- SortObject<T> other = i.next();
- so.addDirectedLinks(other);
- }
- graph.add(so);
- }
-
- private static <T extends PartialComparable> void removeFromGraph(List<SortObject<T>> graph, SortObject<T> o) {
- for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
- SortObject<T> other = i.next();
-
- if (o == other) {
- i.remove();
- }
- // ??? could use this to build up a new queue of objects with no
- // ??? smaller ones
- other.removeSmallerObject(o);
- }
- }
-
- /**
- * @param objects must all implement PartialComparable
- *
- * @returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
- *
- */
- public static <T extends PartialComparable> List<T> sort(List<T> objects) {
- // lists of size 0 or 1 don't need any sorting
- if (objects.size() < 2) {
- return objects;
- }
-
- // ??? we might want to optimize a few other cases of small size
-
- // ??? I don't like creating this data structure, but it does give good
- // ??? separation of concerns.
- List<SortObject<T>> sortList = new LinkedList<SortObject<T>>();
- for (Iterator<T> i = objects.iterator(); i.hasNext();) {
- addNewPartialComparable(sortList, i.next());
- }
-
- // System.out.println(sortList);
-
- // now we have built our directed graph
- // use a simple sort algorithm from here
- // can increase efficiency later
- // List ret = new ArrayList(objects.size());
- final int N = objects.size();
- for (int index = 0; index < N; index++) {
- // System.out.println(sortList);
- // System.out.println("-->" + ret);
-
- SortObject<T> leastWithNoSmallers = null;
-
- for (SortObject<T> so: sortList) {
- if (so.hasNoSmallerObjects()) {
- if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {
- leastWithNoSmallers = so;
- }
- }
- }
-
- if (leastWithNoSmallers == null) {
- return null;
- }
-
- removeFromGraph(sortList, leastWithNoSmallers);
- objects.set(index, leastWithNoSmallers.object);
- }
-
- return objects;
- }
-
- /***********************************************************************************
- * /* a minimal testing harness
- ***********************************************************************************/
- static class Token implements PartialComparable {
- private String s;
-
- Token(String s) {
- this.s = s;
- }
-
- public int compareTo(Object other) {
- Token t = (Token) other;
-
- int cmp = s.charAt(0) - t.s.charAt(0);
- if (cmp == 1) {
- return 1;
- }
- if (cmp == -1) {
- return -1;
- }
- return 0;
- }
-
- public int fallbackCompareTo(Object other) {
- return -s.compareTo(((Token) other).s);
- }
-
- public String toString() {
- return s;
- }
- }
-
- public static void main(String[] args) {
- List<Token> l = new ArrayList<Token>();
- l.add(new Token("a1"));
- l.add(new Token("c2"));
- l.add(new Token("b3"));
- l.add(new Token("f4"));
- l.add(new Token("e5"));
- l.add(new Token("d6"));
- l.add(new Token("c7"));
- l.add(new Token("b8"));
-
- l.add(new Token("z"));
- l.add(new Token("x"));
-
- l.add(new Token("f9"));
- l.add(new Token("e10"));
- l.add(new Token("a11"));
- l.add(new Token("d12"));
- l.add(new Token("b13"));
- l.add(new Token("c14"));
-
- System.out.println(l);
-
- sort(l);
-
- System.out.println(l);
- }
-}
+++ /dev/null
-/* *******************************************************************
- * 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
- * ******************************************************************/
-
-
-package org.aspectj.util;
-
-import java.io.File;
-import java.lang.reflect.*;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.ArrayList;
-//import java.util.StringTokenizer;
-
-public class Reflection {
- public static final Class<?>[] MAIN_PARM_TYPES = new Class[] {String[].class};
-
- private Reflection() {
- }
-
- public static Object invokestaticN(Class<?> class_, String name, Object[] args) {
- return invokeN(class_, name, null, args);
- }
-
- public static Object invoke(Class<?> class_, Object target, String name, Object arg1, Object arg2) {
- return invokeN(class_, name, target, new Object[] { arg1, arg2 });
- }
-
- public static Object invoke(Class<?> class_, Object target, String name, Object arg1, Object arg2, Object arg3) {
- return invokeN(class_, name, target, new Object[] { arg1, arg2, arg3 });
- }
-
-
- public static Object invokeN(Class<?> class_, String name, Object target, Object[] args) {
- Method meth = getMatchingMethod(class_, name, args);
- try {
- return meth.invoke(target, args);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e.toString());
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- if (t instanceof Error) throw (Error)t;
- if (t instanceof RuntimeException) throw (RuntimeException)t;
- t.printStackTrace();
- throw new RuntimeException(t.toString());
- }
- }
-
-
- public static Method getMatchingMethod(Class<?> class_, String name, Object[] args) {
- Method[] meths = class_.getMethods();
- for (int i=0; i < meths.length; i++) {
- Method meth = meths[i];
- if (meth.getName().equals(name) && isCompatible(meth, args)) {
- return meth;
- }
- }
- return null;
- }
-
- private static boolean isCompatible(Method meth, Object[] args) {
- // ignore methods with overloading other than lengths
- return meth.getParameterTypes().length == args.length;
- }
-
-
-
-
- public static Object getStaticField(Class<?> class_, String name) {
- try {
- return class_.getField(name).get(null);
- } catch (IllegalAccessException e) {
- throw new RuntimeException("unimplemented");
- } catch (NoSuchFieldException e) {
- throw new RuntimeException("unimplemented");
- }
- }
-
- public static void runMainInSameVM(
- String classpath,
- String className,
- String[] args)
- throws SecurityException, NoSuchMethodException,
- IllegalArgumentException, IllegalAccessException,
- InvocationTargetException, ClassNotFoundException {
- LangUtil.throwIaxIfNull(className, "class name");
- if (LangUtil.isEmpty(classpath)) {
- Class<?> mainClass = Class.forName(className);
- runMainInSameVM(mainClass, args);
- return;
- }
- ArrayList<File> dirs = new ArrayList<File>();
- ArrayList<File> libs = new ArrayList<File>();
- ArrayList<URL> urls = new ArrayList<URL>();
- String[] entries = LangUtil.splitClasspath(classpath);
- for (int i = 0; i < entries.length; i++) {
- String entry = entries[i];
- URL url = makeURL(entry);
- if (null != url) {
- urls.add(url);
- }
- File file = new File(entries[i]);
-// tolerate bad entries b/c bootclasspath sometimes has them
-// if (!file.canRead()) {
-// throw new IllegalArgumentException("cannot read " + file);
-// }
- if (FileUtil.isZipFile(file)) {
- libs.add(file);
- } else if (file.isDirectory()) {
- dirs.add(file);
- } else {
- // not URL, zip, or dir - unsure what to do
- }
- }
- File[] dirRa = (File[]) dirs.toArray(new File[0]);
- File[] libRa = (File[]) libs.toArray(new File[0]);
- URL[] urlRa = (URL[]) urls.toArray(new URL[0]);
- runMainInSameVM(urlRa, libRa, dirRa, className, args);
- }
-
- public static void runMainInSameVM(
- URL[] urls,
- File[] libs,
- File[] dirs,
- String className,
- String[] args)
- throws SecurityException, NoSuchMethodException,
- IllegalArgumentException, IllegalAccessException,
- InvocationTargetException, ClassNotFoundException {
- LangUtil.throwIaxIfNull(className, "class name");
- LangUtil.throwIaxIfNotAssignable(libs, File.class, "jars");
- LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs");
- URL[] libUrls = FileUtil.getFileURLs(libs);
- if (!LangUtil.isEmpty(libUrls)) {
- if (!LangUtil.isEmpty(urls)) {
- URL[] temp = new URL[libUrls.length + urls.length];
- System.arraycopy(urls, 0, temp, 0, urls.length);
- System.arraycopy(urls, 0, temp, libUrls.length, urls.length);
- urls = temp;
- } else {
- urls = libUrls;
- }
- }
- UtilClassLoader loader = new UtilClassLoader(urls, dirs);
- Class<?> targetClass = null;
- try {
- targetClass = loader.loadClass(className);
- } catch (ClassNotFoundException e) {
- String s = "unable to load class " + className
- + " using class loader " + loader;
- throw new ClassNotFoundException(s);
- }
- Method main = targetClass.getMethod("main", MAIN_PARM_TYPES);
- main.invoke(null, new Object[] { args });
- }
-
- public static void runMainInSameVM(Class<?> mainClass, String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- LangUtil.throwIaxIfNull(mainClass, "main class");
- Method main = mainClass.getMethod("main", MAIN_PARM_TYPES);
- main.invoke(null, new Object[] { args });
- }
-
- /** @return URL if the input is valid as such */
- private static URL makeURL(String s) {
- try {
- return new URL(s);
- } catch (Throwable t) {
- return null;
- }
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2017 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
- * ******************************************************************/package org.aspectj.util;
-
-import java.lang.ref.*;
-import java.util.*;
-
-public class SoftHashMap<K,V> extends AbstractMap<K,V> {
- private Map<K, SpecialValue> map;
- private ReferenceQueue<? super V> rq = new ReferenceQueue();
-
- public SoftHashMap() {
- this.map = new HashMap<K,SpecialValue>();
- }
-
- class SpecialValue extends SoftReference<V> {
- private final K key;
-
- SpecialValue(K k, V v) {
- super(v, rq);
- this.key = k;
- }
- }
-
- @SuppressWarnings("unchecked")
- private void processQueue() {
- SpecialValue sv = null;
- while ((sv = (SpecialValue)rq.poll()) != null) {
- map.remove(sv.key);
- }
- }
-
- @Override
- public V get(Object key) {
- SpecialValue ref = map.get(key);
- if (ref == null) {
- map.remove(key);
- return null;
- }
- V value = ref.get();
- if (value == null) {
- map.remove(ref.key);
- return null;
- }
- return value;
- }
-
- @Override
- public V put(K k, V v) {
- processQueue();
- SpecialValue sv = new SpecialValue(k, v);
- SpecialValue result = map.put(k, sv);
- return (result == null ? null : result.get());
- }
-
- @Override
- public java.util.Set<Map.Entry<K,V>> entrySet() {
- if (map.isEmpty()) { return Collections.<K,V>emptyMap().entrySet(); }
- Map<K,V> currentContents = new HashMap<K,V>();
- for (Map.Entry<K,SpecialValue> entry: map.entrySet()) {
- V currentValueForEntry = entry.getValue().get();
- if (currentValueForEntry != null) {
- currentContents.put(entry.getKey(), currentValueForEntry);
- }
- }
- return currentContents.entrySet();
- }
-
- @Override
- public void clear() {
- processQueue();
- map.clear();
- }
-
- @Override
- public int size() {
- processQueue();
- return map.size();
- }
-
- @Override
- public V remove(Object k) {
- processQueue();
- SpecialValue ref = map.remove(k);
- if (ref == null) {
- return null;
- }
- return ref.get();
- }
-}
+++ /dev/null
-/* *******************************************************************
- * 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
- * ******************************************************************/
-
-package org.aspectj.util;
-
-import java.io.*;
-
-public class TypeSafeEnum {
- private byte key;
- private String name;
-
- public TypeSafeEnum(String name, int key) {
- this.name = name;
- if (key > Byte.MAX_VALUE || key < Byte.MIN_VALUE) {
- throw new IllegalArgumentException("key doesn't fit into a byte: " + key);
- }
- this.key = (byte) key;
- }
-
- public String toString() {
- return name;
- }
-
- public String getName() {
- return name;
- }
-
- public byte getKey() {
- return key;
- }
-
- public void write(DataOutputStream s) throws IOException {
- s.writeByte(key);
- }
-}
+++ /dev/null
-/* *******************************************************************
- * 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:
- * Isberg initial implementation
- * ******************************************************************/
-
-package org.aspectj.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Load classes as File from File[] dirs or URL[] jars.
- */
-public class UtilClassLoader extends URLClassLoader {
-
- /** seek classes in dirs first */
- List<File> dirs;
-
- /** save URL[] only for toString */
- private URL[] urlsForDebugString;
-
- public UtilClassLoader(URL[] urls, File[] dirs) {
- super(urls);
- LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs");
- this.urlsForDebugString = urls;
- ArrayList<File> dcopy = new ArrayList<File>();
-
- if (!LangUtil.isEmpty(dirs)) {
- dcopy.addAll(Arrays.asList(dirs));
- }
- this.dirs = Collections.unmodifiableList(dcopy);
- }
-
-
- public URL getResource(String name) {
- return ClassLoader.getSystemResource(name);
- }
-
- public InputStream getResourceAsStream(String name) {
- return ClassLoader.getSystemResourceAsStream(name);
- }
-
- public synchronized Class<?> loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- // search the cache, our dirs (if maybe test),
- // the system, the superclass (URL[]),
- // and our dirs again (if not maybe test)
- ClassNotFoundException thrown = null;
- Class<?> result = findLoadedClass(name);
- if (null != result) {
- resolve = false;
- } else {
- try {
- result = findSystemClass(name);
- } catch (ClassNotFoundException e) {
- thrown = e;
- }
- }
- if (null == result) {
- try {
- result = super.loadClass(name, resolve);
- } catch (ClassNotFoundException e) {
- thrown = e;
- }
- if (null != result) { // resolved by superclass
- return result;
- }
- }
- if (null == result) {
- byte[] data = readClass(name);
- if (data != null) {
- result = defineClass(name, data, 0, data.length);
- } // handle ClassFormatError?
- }
-
- if (null == result) {
- throw (null != thrown ? thrown : new ClassNotFoundException(name));
- }
- if (resolve) {
- resolveClass(result);
- }
- return result;
- }
-
- /** @return null if class not found or byte[] of class otherwise */
- private byte[] readClass(String className) throws ClassNotFoundException {
- final String fileName = className.replace('.', '/')+".class";
- for (Iterator<File> iter = dirs.iterator(); iter.hasNext();) {
- File file = new File(iter.next(), fileName);
- if (file.canRead()) {
- return getClassData(file);
- }
- }
- return null;
- }
-
- private byte[] getClassData(File f) {
- try {
- FileInputStream stream= new FileInputStream(f);
- ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
- byte[] b= new byte[4096];
- int n;
- while ((n= stream.read(b)) != -1) {
- out.write(b, 0, n);
- }
- stream.close();
- out.close();
- return out.toByteArray();
- } catch (IOException e) {
- }
- return null;
- }
-
- /** @return String with debug info: urls and classes used */
- public String toString() {
- return "UtilClassLoader(urls="
- + Arrays.asList(urlsForDebugString)
- + ", dirs="
- + dirs
- + ")";
- }
-}
-
--- /dev/null
+/* *******************************************************************
+ * 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.util;
+
+//import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.StringBufferInputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import junit.textui.TestRunner;
+
+/**
+ *
+ */
+public class FileUtilTest extends TestCase {
+ public static final String[] NONE = new String[0];
+ public static boolean log = false;
+
+ public static void main(String[] args) {
+ TestRunner.main(new String[] { "org.aspectj.util.FileUtilTest" });
+ }
+
+ public static void assertSame(String prefix, String[] lhs, String[] rhs) { // XXX cheap diff
+ String srcPaths = LangUtil.arrayAsList(lhs).toString();
+ String destPaths = LangUtil.arrayAsList(rhs).toString();
+ if (!srcPaths.equals(destPaths)) {
+ log("expected: " + srcPaths);
+ log(" actual: " + destPaths);
+ assertTrue(prefix + " expected=" + srcPaths + " != actual=" + destPaths, false);
+ }
+ }
+
+ /**
+ * Verify that dir contains files with names, and return the names of other files in dir.
+ *
+ * @return the contents of dir after excluding files or NONE if none
+ * @throws AssertionFailedError if any names are not in dir
+ */
+ public static String[] dirContains(File dir, final String[] filenames) {
+ final ArrayList<String> sought = new ArrayList<>(LangUtil.arrayAsList(filenames));
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File d, String name) {
+ return !sought.remove(name);
+ }
+ };
+ // remove any found from sought and return remainder
+ String[] found = dir.list(filter);
+ if (0 < sought.size()) {
+ assertTrue("found " + LangUtil.arrayAsList(dir.list()).toString() + " expected " + sought, false);
+ }
+ return (found.length == 0 ? NONE : found);
+ }
+
+ /** @return sorted String[] of all paths to all files/dirs under dir */
+ public static String[] dirPaths(File dir) {
+ return dirPaths(dir, new String[0]);
+ }
+
+ /**
+ * Get a sorted String[] of all paths to all files/dirs under dir. Files with names starting with "." are ignored, as are
+ * directory paths containing "CVS". The directory prefix of the path is stripped. Thus, given directory:
+ *
+ * <pre>
+ * path/to
+ * .cvsignore
+ * CVS/
+ * Root
+ * Repository
+ * Base.java
+ * com/
+ * parc/
+ * messages.properties
+ * org/
+ * aspectj/
+ * Version.java
+ * </pre>
+ *
+ * a call
+ *
+ * <pre>
+ * dirPaths(new File("path/to"), new String[0]);
+ * </pre>
+ *
+ * returns
+ *
+ * <pre>
+ * { "Base.java", "com/parc/messages.properties", "org/aspectj/Version.java" }
+ * </pre>
+ *
+ * while the call
+ *
+ * <pre>
+ * dirPaths(new File("path/to"), new String[] { ".java" });
+ * </pre>
+ *
+ * returns
+ *
+ * <pre>
+ * { "Base.java", "org/aspectj/Version.java" }
+ * </pre>
+ *
+ * @param dir the File path to the directory to inspect
+ * @param suffixes if not empty, require files returned to have this suffix
+ * @return sorted String[] of all paths to all files under dir ending with one of the listed suffixes but not starting with "."
+ */
+ public static String[] dirPaths(File dir, String[] suffixes) {
+ ArrayList<String> result = new ArrayList<String>();
+ doDirPaths(dir, result);
+ // if suffixes required, remove those without suffixes
+ if (!LangUtil.isEmpty(suffixes)) {
+ for (ListIterator<String> iter = result.listIterator(); iter.hasNext();) {
+ String path = iter.next().toString();
+ boolean hasSuffix = false;
+ for (int i = 0; !hasSuffix && (i < suffixes.length); i++) {
+ hasSuffix = path.endsWith(suffixes[i]);
+ }
+ if (!hasSuffix) {
+ iter.remove();
+ }
+ }
+ }
+ Collections.sort(result);
+ // trim prefix
+ final String prefix = dir.getPath();
+ final int len = prefix.length() + 1; // plus directory separator
+ String[] ra = (String[]) result.toArray(new String[0]);
+ for (int i = 0; i < ra.length; i++) {
+ // assertTrue(ra[i].startsWith(prefix));
+ assertTrue(ra[i], ra[i].length() > len);
+ ra[i] = ra[i].substring(len);
+ }
+ return ra;
+ }
+
+ /**
+ * @param dir the File to read - ignored if null, not a directory, or has "CVS" in its path
+ * @param useSuffix if true, then use dir as suffix to path
+ */
+ private static void doDirPaths(File dir, ArrayList<String> paths) {
+ if ((null == dir) || !dir.canRead() || (-1 != dir.getPath().indexOf("CVS"))) {
+ return;
+ }
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ String path = files[i].getPath();
+ if (!files[i].getName().startsWith(".")) {
+ if (files[i].isFile()) {
+ paths.add(path);
+ } else if (files[i].isDirectory()) {
+ doDirPaths(files[i], paths);
+ } else {
+ log("not file or dir: " + dir + "/" + path);
+ }
+ }
+ }
+ }
+
+ /** Print s if logging is enabled */
+ private static void log(String s) {
+ if (log) {
+ System.err.println(s);
+ }
+ }
+
+ /** List of File files or directories to delete when exiting */
+ final ArrayList<File> tempFiles;
+
+ public FileUtilTest(String s) {
+ super(s);
+ tempFiles = new ArrayList<File>();
+ }
+
+ public void tearDown() {
+ for (ListIterator<File> iter = tempFiles.listIterator(); iter.hasNext();) {
+ File dir = (File) iter.next();
+ log("removing " + dir);
+ FileUtil.deleteContents(dir);
+ dir.delete();
+ iter.remove();
+ }
+ }
+
+ public void testNotIsFileIsDirectory() {
+ File noSuchFile = new File("foo");
+ assertTrue(!noSuchFile.isFile());
+ assertTrue(!noSuchFile.isDirectory());
+ }
+
+ public void testGetBestFile() {
+ assertNull(FileUtil.getBestFile((String[]) null));
+ assertNull(FileUtil.getBestFile(new String[0]));
+ assertNull(FileUtil.getBestFile(new String[] { "!" }));
+ File f = FileUtil.getBestFile(new String[] { "." });
+ assertNotNull(f);
+ f = FileUtil.getBestFile(new String[] { "!", "." });
+ assertNotNull(f);
+ assertTrue(f.canRead());
+ boolean setProperty = false;
+ try {
+ System.setProperty("bestfile", ".");
+ setProperty = true;
+ } catch (Throwable t) {
+ // ignore Security, etc.
+ }
+ if (setProperty) {
+ f = FileUtil.getBestFile(new String[] { "sp:bestfile" });
+ assertNotNull(f);
+ assertTrue(f.canRead());
+ }
+ }
+
+ public void testCopyFiles() {
+ // bad input
+ Class<?> iaxClass = IllegalArgumentException.class;
+
+ checkCopyFiles(null, null, iaxClass, false);
+
+ File noSuchFile = new File("foo");
+ checkCopyFiles(noSuchFile, null, iaxClass, false);
+ checkCopyFiles(noSuchFile, noSuchFile, iaxClass, false);
+
+ File tempDir = FileUtil.getTempDir("testCopyFiles");
+ tempFiles.add(tempDir);
+ File fromFile = new File(tempDir, "fromFile");
+ String err = FileUtil.writeAsString(fromFile, "contents of from file");
+ assertTrue(err, null == err);
+ checkCopyFiles(fromFile, null, iaxClass, false);
+ checkCopyFiles(fromFile, fromFile, iaxClass, false);
+
+ // file-file
+ File toFile = new File(tempDir, "toFile");
+ checkCopyFiles(fromFile, toFile, null, true);
+
+ // file-dir
+ File toDir = new File(tempDir, "toDir");
+ assertTrue(toDir.mkdirs());
+ checkCopyFiles(fromFile, toDir, null, true);
+
+ // dir-dir
+ File fromDir = new File(tempDir, "fromDir");
+ assertTrue(fromDir.mkdirs());
+ checkCopyFiles(fromFile, fromDir, null, false);
+ File toFile2 = new File(fromDir, "toFile2");
+ checkCopyFiles(fromFile, toFile2, null, false);
+ checkCopyFiles(fromDir, toDir, null, true);
+ }
+
+ void checkCopyFiles(File from, File to, Class exceptionClass, boolean clean) {
+ try {
+ FileUtil.copyFile(from, to);
+ assertTrue(null == exceptionClass);
+ if (to.isFile()) {
+ assertTrue(from.length() == to.length()); // XXX cheap test
+ } else if (!from.isDirectory()) {
+ File toFile = new File(to, from.getName());
+ assertTrue(from.length() == toFile.length());
+ } else {
+ // from is a dir and to is a dir, toDir should be created, and have the
+ // same contents as fromDir.
+ assertTrue(to.exists());
+ assertTrue(from.listFiles().length == to.listFiles().length);
+ }
+ } catch (Throwable t) {
+ assertTrue(null != exceptionClass);
+ assertTrue(exceptionClass.isAssignableFrom(t.getClass()));
+ } finally {
+ if (clean && (null != to) && (to.exists())) {
+ if (to.isDirectory()) {
+ FileUtil.deleteContents(to);
+ }
+ to.delete();
+ }
+ }
+ }
+
+ public void testDirCopySubdirs() throws IOException {
+ File srcDir = new File("src");
+ File destDir = FileUtil.getTempDir("testDirCopySubdirs");
+ tempFiles.add(destDir);
+ FileUtil.copyDir(srcDir, destDir);
+ assertSame("testDirCopySubdirs", dirPaths(srcDir), dirPaths(destDir));
+ }
+
+ public void testDirCopySubdirsSuffix() throws IOException {
+ File srcDir = new File("src");
+ File destDir = FileUtil.getTempDir("testDirCopySubdirsSuffix");
+ tempFiles.add(destDir);
+ FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
+
+ String[] sources = dirPaths(srcDir, new String[] { ".java" });
+ for (int i = 0; i < sources.length; i++) {
+ sources[i] = sources[i].substring(0, sources[i].length() - 4);
+ }
+ String[] sinks = dirPaths(destDir, new String[] { ".aj" });
+ for (int i = 0; i < sinks.length; i++) {
+ sinks[i] = sinks[i].substring(0, sinks[i].length() - 2);
+ }
+ assertSame("testDirCopySubdirs", sources, sinks);
+ }
+
+ public void testGetURL() {
+ String[] args = new String[] { ".", "../util/testdata", "../lib/test/aspectjrt.jar" };
+ for (int i = 0; i < args.length; i++) {
+ checkGetURL(args[i]);
+ }
+ }
+
+ /**
+ * Method checkGetURL.
+ *
+ * @param string
+ * @param uRL
+ */
+ private void checkGetURL(String arg) {
+ assertTrue(null != arg);
+ File f = new File(arg);
+ URL url = FileUtil.getFileURL(f);
+ assertTrue(null != url);
+ log("url " + url);
+ if (!f.exists()) {
+ log("not exist " + f);
+ } else if (f.isDirectory()) {
+ log("directory " + f);
+ } else {
+ log(" file " + f);
+ InputStream in = null;
+ try {
+ in = url.openStream();
+ } catch (IOException e) {
+ assertTrue("IOException: " + e, false);
+ } finally {
+ if (null != in) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ }
+
+ public void testGetTempDir() {
+ boolean pass = true;
+ boolean delete = true;
+ checkGetTempDir("parent", null, pass, delete);
+ checkGetTempDir(null, "child", pass, delete);
+ tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
+ tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
+ tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
+ }
+
+ File checkGetTempDir(String parent, String child, boolean ok, boolean delete) {
+ File parentDir = FileUtil.getTempDir(parent);
+ assertTrue("unable to create " + parent, null != parentDir);
+ File dir = FileUtil.makeNewChildDir(parentDir, child);
+ log("parent=" + parent + " child=" + child + " -> " + dir);
+ assertTrue("dir: " + dir, ok == (dir.canWrite() && dir.isDirectory()));
+ if (delete) {
+ dir.delete();
+ parentDir.delete();
+ }
+ return dir;
+ }
+
+ public void testRandomFileString() {
+ ArrayList<String> results = new ArrayList<>();
+ for (int i = 0; i < 1000; i++) {
+ String s = FileUtil.randomFileString();
+ if (results.contains(s)) {
+ log("warning: got duplicate at iteration " + i);
+ }
+ results.add(s);
+ // System.err.print(" " + s);
+ // if (0 == (i % 5)) {
+ // System.err.println("");
+ // }
+ }
+ }
+
+ public void testNormalizedPath() {
+ File tempFile = null;
+ try {
+ tempFile = File.createTempFile("FileUtilTest_testNormalizedPath", "tmp");
+ tempFiles.add(tempFile);
+ } catch (IOException e) {
+ log("aborting test - unable to create temp file");
+ return;
+ }
+ File parentDir = tempFile.getParentFile();
+ String tempFilePath = FileUtil.normalizedPath(tempFile, parentDir);
+ assertEquals(tempFile.getName(), tempFilePath);
+ }
+
+ public void testFileToClassName() {
+
+ File basedir = new File("/base/dir"); // never created
+ File classFile = new File(basedir, "foo/Bar.class");
+ assertEquals("foo.Bar", FileUtil.fileToClassName(basedir, classFile));
+
+ classFile = new File(basedir, "foo\\Bar.class");
+ assertEquals("foo.Bar", FileUtil.fileToClassName(basedir, classFile));
+
+ assertEquals("Bar", FileUtil.fileToClassName(null, classFile));
+
+ classFile = new File("/home/classes/org/aspectj/lang/JoinPoint.class");
+ assertEquals("org.aspectj.lang.JoinPoint", FileUtil.fileToClassName(null, classFile));
+
+ classFile = new File("/home/classes/com/sun/tools/Javac.class");
+ assertEquals("com.sun.tools.Javac", FileUtil.fileToClassName(null, classFile));
+ }
+
+ public void testDeleteContents() {
+ File tempDir = FileUtil.getTempDir("testDeleteContents");
+ tempFiles.add(tempDir);
+ File f = new File(tempDir, "foo");
+ f.mkdirs();
+ File g = new File(f, "bar");
+ g.mkdirs();
+ File h = new File(g, "bash");
+ h.mkdirs();
+ int d = FileUtil.deleteContents(f);
+ assertTrue(0 == d);
+ assertTrue(0 == f.list().length);
+ f.delete();
+ assertTrue(!f.exists());
+ }
+
+ public void testLineSeek() {
+ File tempDir = FileUtil.getTempDir("testLineSeek");
+ tempFiles.add(tempDir);
+ File file = new File(tempDir, "testLineSeek");
+ String path = file.getPath();
+ String contents = "0123456789" + LangUtil.EOL;
+ contents += contents;
+ FileUtil.writeAsString(file, contents);
+ tempFiles.add(file);
+ List<String> sourceList = new ArrayList<String>();
+ sourceList.add(file.getPath());
+
+ final ArrayList<String> errors = new ArrayList<String>();
+ final PrintStream errorSink = new PrintStream(System.err, true) {
+ public void println(String error) {
+ errors.add(error);
+ }
+ };
+ for (int i = 0; i < 10; i++) {
+ List<String> result = FileUtil.lineSeek("" + i, sourceList, true, errorSink);
+ assertEquals(2, result.size());
+ assertEquals(path + ":1:" + i, result.get(0));
+ assertEquals(path + ":2:" + i, result.get(1));
+ if (!LangUtil.isEmpty(errors)) { // XXX prefer fast-fail?
+ assertTrue("errors: " + errors, false);
+ }
+ }
+
+ }
+
+ public void testLineSeekMore() {
+ final int MAX = 3; // 1..10
+ File tempDir = FileUtil.getTempDir("testLineSeekMore");
+ tempFiles.add(tempDir);
+ final String prefix = new File(tempDir, "testLineSeek").getPath();
+ // setup files 0..MAX with 2*MAX lines
+ String[] sources = new String[MAX];
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < sources.length; i++) {
+ sources[i] = new File(prefix + i).getPath();
+ sb.append("not matched");
+ sb.append(LangUtil.EOL);
+ sb.append("0123456789");
+ sb.append(LangUtil.EOL);
+ }
+ final String contents = sb.toString();
+ for (int i = 0; i < sources.length; i++) {
+ File file = new File(sources[i]);
+ FileUtil.writeAsString(file, contents);
+ tempFiles.add(file);
+ }
+ // now test
+ final ArrayList<String> errors = new ArrayList<>();
+ final PrintStream errorSink = new PrintStream(System.err, true) {
+ public void println(String error) {
+ errors.add(error);
+ }
+ };
+ List<String> sourceList = new ArrayList<>();
+ sourceList.addAll(Arrays.asList(sources));
+ sourceList = Collections.unmodifiableList(sourceList);
+ for (int k = 0; k < sources.length; k++) {
+ List<String> result = FileUtil.lineSeek("" + k, sourceList, true, errorSink);
+ // number k found in every other line of every file at index k
+ Iterator<String> iter = result.iterator();
+ for (int i = 0; i < MAX; i++) { // for each file
+ for (int j = 1; j < (MAX + 1); j++) { // for every other line
+ assertTrue(iter.hasNext());
+ assertEquals(prefix + i + ":" + 2 * j + ":" + k, iter.next());
+ }
+ }
+ if (!LangUtil.isEmpty(errors)) { // XXX prefer fast-fail?
+ assertTrue("errors: " + errors, false);
+ }
+ }
+ }
+
+ public void testDirCopyNoSubdirs() throws IOException {
+ String[] srcFiles = new String[] { "one.java", "two.java", "three.java" };
+ String[] destFiles = new String[] { "three.java", "four.java", "five.java" };
+ String[] allFiles = new String[] { "one.java", "two.java", "three.java", "four.java", "five.java" };
+ File srcDir = makeTempDir("FileUtilUT_srcDir", srcFiles);
+ File destDir = makeTempDir("FileUtilUT_destDir", destFiles);
+ assertTrue(null != srcDir);
+ assertTrue(null != destDir);
+ assertTrue(NONE == dirContains(srcDir, srcFiles));
+ assertTrue(NONE == dirContains(destDir, destFiles));
+
+ FileUtil.copyDir(srcDir, destDir);
+ String[] resultOne = dirContains(destDir, allFiles);
+ FileUtil.copyDir(srcDir, destDir);
+ String[] resultTwo = dirContains(destDir, allFiles);
+
+ assertTrue(NONE == resultOne);
+ assertTrue(NONE == resultTwo);
+ }
+
+ public void testDirCopyNoSubdirsWithSuffixes() throws IOException {
+ String[] srcFiles = new String[] { "one.java", "two.java", "three.java" };
+ String[] destFiles = new String[] { "three.java", "four.java", "five.java" };
+ String[] allFiles = new String[] { "one.aj", "two.aj", "three.aj", "three.java", "four.java", "five.java" };
+ File srcDir = makeTempDir("FileUtilUT_srcDir", srcFiles);
+ File destDir = makeTempDir("FileUtilUT_destDir", destFiles);
+ assertTrue(null != srcDir);
+ assertTrue(null != destDir);
+ assertTrue(NONE == dirContains(srcDir, srcFiles));
+ assertTrue(NONE == dirContains(destDir, destFiles));
+
+ FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
+ FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
+
+ assertTrue(NONE == dirContains(destDir, allFiles));
+ assertTrue(NONE == dirContains(destDir, allFiles));
+ }
+
+ public void testDirCopySubdirsSuffixRoundTrip() throws IOException {
+ final File srcDir = new File("src");
+ final File one = FileUtil.getTempDir("testDirCopySubdirsSuffixRoundTrip_1");
+ final File two = FileUtil.getTempDir("testDirCopySubdirsSuffixRoundTrip_2");
+ FileUtil.copyDir(srcDir, one); // no selection
+ FileUtil.copyDir(two, one, ".java", ".aj"); // only .java files
+ FileUtil.copyDir(one, two, ".aj", ".java");
+
+ FileUtil.deleteContents(one);
+ one.delete();
+ FileUtil.deleteContents(two);
+ two.delete();
+ }
+
+ /**
+ * Create temp dir at loc containing temp files files. Result is registered for deletion on cleanup.
+ */
+ File makeTempDir(String loc, String[] filenames) throws IOException {
+ File d = new File(loc);
+ d.mkdirs();
+ assertTrue(d.exists());
+ tempFiles.add(d);
+ assertTrue(d.canWrite());
+ for (int i = 0; i < filenames.length; i++) {
+ File f = new File(d, filenames[i]);
+ assertTrue(filenames[i], f.createNewFile());
+ }
+ return d;
+ }
+
+ public void testPipeEmpty() {
+ checkPipe("");
+ }
+
+ public void testPipeMin() {
+ checkPipe("0");
+ }
+
+ public void testPipe() {
+ String str = "The quick brown fox jumped over the lazy dog";
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < 4096; i++) {
+ sb.append(str);
+ }
+ checkPipe(sb.toString());
+ }
+
+ void checkPipe(String data) {
+ StringBufferInputStream in = new StringBufferInputStream(data);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true);
+ pipe.run();
+ assertTrue(data.equals(out.toString()));
+ assertTrue(null == pipe.getThrown());
+ assertEquals("totalWritten", data.length(), pipe.totalWritten());
+ }
+
+ public void testPipeThrown() {
+ final String data = "The quick brown fox jumped over the lazy dog";
+ final IOException thrown = new IOException("test");
+ StringBufferInputStream in = new StringBufferInputStream(data);
+ OutputStream out = new OutputStream() {
+ public void write(int b) throws IOException {
+ throw thrown;
+ }
+ };
+
+ FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true);
+ pipe.run();
+ assertEquals("totalWritten", 0, pipe.totalWritten());
+ assertTrue(thrown == pipe.getThrown());
+ }
+
+ public void xtestPipeHalt() { // this test periodically fails on the build machine -
+ // disabling till we have time to figure out why
+ final long MAX = 1000000;
+ InputStream in = new InputStream() {
+ long max = 0;
+
+ public int read() throws IOException {
+ if (max++ > MAX) {
+ throw new IOException("test failed");
+ }
+ return 1;
+ }
+
+ };
+ final int minWritten = 20;
+ class Flag {
+ boolean hit;
+ }
+ final Flag flag = new Flag();
+ OutputStream out = new OutputStream() {
+ long max = 0;
+
+ public void write(int b) throws IOException {
+ if (max++ > MAX) {
+ throw new IOException("test failed");
+ } else if (max > minWritten) {
+ if (!flag.hit) {
+ flag.hit = true;
+ }
+ }
+ }
+ };
+ class Result {
+ long totalWritten;
+ Throwable thrown;
+ boolean set;
+ }
+ final Result result = new Result();
+ FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true) {
+ protected void completing(long totalWritten, Throwable thrown) {
+ result.totalWritten = totalWritten;
+ result.thrown = thrown;
+ result.set = true;
+ }
+ };
+ // start it up
+ new Thread(pipe).start();
+ // wait for minWritten input
+ while (!flag.hit) {
+ try {
+ Thread.sleep(5l);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ // halt
+ assertTrue(pipe.halt(true, true));
+ assertTrue(result.set);
+ assertTrue("Expected null but result.thrown = " + result.thrown, null == result.thrown);
+ assertTrue(null == pipe.getThrown());
+ assertEquals("total written", result.totalWritten, pipe.totalWritten());
+ if (minWritten > pipe.totalWritten()) {
+ assertTrue("written: " + pipe.totalWritten(), false);
+ }
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2005-2008 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
+ *
+ * ******************************************************************/
+
+package org.aspectj.util;
+
+import junit.framework.TestCase;
+
+import org.aspectj.util.GenericSignature.ClassSignature;
+import org.aspectj.util.GenericSignature.ClassTypeSignature;
+import org.aspectj.util.GenericSignature.FieldTypeSignature;
+import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
+
+/**
+ * @author Adrian Colyer
+ * @author Andy Clement
+ */
+public class GenericSignatureParserTest extends TestCase {
+
+ GenericSignatureParser parser;
+
+ public void testSimpleTokenize() {
+ String[] tokens = parser.tokenize("Ljava/lang/String;");
+ assertEquals(new String[] { "Ljava", "/", "lang", "/", "String", ";" }, tokens);
+ }
+
+ public void testTokenizeWithWildTypeArguments() {
+ String[] tokens = parser.tokenize("Ljava/lang/String<*>;");
+ assertEquals(new String[] { "Ljava", "/", "lang", "/", "String", "<", "*", ">", ";" }, tokens);
+ }
+
+ public void testTokenizeWithExtendsTypeArguments() {
+ String[] tokens = parser.tokenize("Ljava/util/List<+TE>;");
+ assertEquals(new String[] { "Ljava", "/", "util", "/", "List", "<", "+", "TE", ">", ";" }, tokens);
+ }
+
+ public void testTokenizeWithSuperTypeArguments() {
+ String[] tokens = parser.tokenize("Ljava/util/List<-TE>;");
+ assertEquals(new String[] { "Ljava", "/", "util", "/", "List", "<", "-", "TE", ">", ";" }, tokens);
+ }
+
+ public void testTokenizeArrayType() {
+ String[] tokens = parser.tokenize("[Ljava/lang/String;");
+ assertEquals(new String[] { "[", "Ljava", "/", "lang", "/", "String", ";" }, tokens);
+ }
+
+ public void testTokenizeFormalTypeParameters() {
+ String[] tokens = parser.tokenize("<T:Ljava/lang/String;:Ljava/util/Comparable;>");
+ assertEquals(new String[] { "<", "T", ":", "Ljava", "/", "lang", "/", "String", ";", ":", "Ljava", "/", "util", "/",
+ "Comparable", ";", ">" }, tokens);
+ }
+
+ public void testParseClassSignatureSimple() {
+ ClassSignature sig = parser.parseAsClassSignature("Ljava/lang/String;");
+ assertEquals("No type parameters", 0, sig.formalTypeParameters.length);
+ assertEquals("No superinterfaces", 0, sig.superInterfaceSignatures.length);
+ assertEquals("Ljava/lang/String;", sig.superclassSignature.classSignature);
+ SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
+ assertEquals("Ljava/lang/String;", outerType.identifier);
+ assertEquals("No type args", 0, outerType.typeArguments.length);
+ }
+
+ public void testParseClassSignatureTypeArgs() {
+ ClassSignature sig = parser.parseAsClassSignature("Ljava/util/List<+Ljava/lang/String;>;");
+ assertEquals("No type parameters", 0, sig.formalTypeParameters.length);
+ assertEquals("No superinterfaces", 0, sig.superInterfaceSignatures.length);
+ assertEquals("Ljava/util/List<+Ljava/lang/String;>;", sig.superclassSignature.classSignature);
+ SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
+ assertEquals("Ljava/util/List", outerType.identifier);
+ assertEquals("One type arg", 1, outerType.typeArguments.length);
+ assertTrue(outerType.typeArguments[0].isPlus);
+ assertEquals("+Ljava/lang/String;", outerType.typeArguments[0].toString());
+ }
+
+ public void testParseClassSignatureTheFullMonty() {
+ ClassSignature sig = parser
+ .parseAsClassSignature("<E:Ljava/lang/String;:Ljava/lang/Number<TE;>;>Ljava/util/List<TE;>;Ljava/util/Comparable<-TE;>;");
+ assertEquals("1 formal parameter", 1, sig.formalTypeParameters.length);
+ assertEquals("E", sig.formalTypeParameters[0].identifier);
+ ClassTypeSignature fsig = (ClassTypeSignature) sig.formalTypeParameters[0].classBound;
+ assertEquals("Ljava/lang/String;", fsig.classSignature);
+ assertEquals("1 interface bound", 1, sig.formalTypeParameters[0].interfaceBounds.length);
+ ClassTypeSignature isig = (ClassTypeSignature) sig.formalTypeParameters[0].interfaceBounds[0];
+ assertEquals("Ljava/lang/Number<TE;>;", isig.classSignature);
+ assertEquals("Ljava/util/List<TE;>;", sig.superclassSignature.classSignature);
+ assertEquals("1 type argument", 1, sig.superclassSignature.outerType.typeArguments.length);
+ assertEquals("TE;", sig.superclassSignature.outerType.typeArguments[0].toString());
+ assertEquals("1 super interface", 1, sig.superInterfaceSignatures.length);
+ assertEquals("Ljava/util/Comparable<-TE;>;", sig.superInterfaceSignatures[0].toString());
+ }
+
+ public void testFunky_406167() {
+ ClassSignature sig = parser
+ .parseAsClassSignature("Lcom/google/android/gms/internal/hb<TT;>.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
+ // Note the package prefix on the nested types has been dropped
+ assertEquals("Lcom/google/android/gms/internal/hb<TT;>.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
+ sig = parser
+ .parseAsClassSignature("Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
+ // Note the package prefix on the nested types has been dropped
+ assertEquals("Lcom/a/a/b/t<TK;TV;>.af.ag;",sig.superclassSignature.toString());
+ assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
+ sig = parser.parseAsClassSignature("Lcom/google/android/gms/internal/hb.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
+ // Note the package prefix on the nested types has been dropped
+ assertEquals("Lcom/google/android/gms/internal/hb.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
+ sig = parser
+ .parseAsClassSignature("Lcom/a/a/b/t.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
+ // Note the package prefix on the nested types has been dropped
+ assertEquals("Lcom/a/a/b/t.af.ag;",sig.superclassSignature.toString());
+ assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
+ }
+
+
+ public void testFieldSignatureParsingClassType() {
+ FieldTypeSignature fsig = parser.parseAsFieldSignature("Ljava/lang/String;");
+ assertTrue("ClassTypeSignature", fsig instanceof ClassTypeSignature);
+ assertEquals("Ljava/lang/String;", fsig.toString());
+ }
+
+ public void testFieldSignatureParsingArrayType() {
+ FieldTypeSignature fsig = parser.parseAsFieldSignature("[Ljava/lang/String;");
+ assertTrue("ArrayTypeSignature", fsig instanceof GenericSignature.ArrayTypeSignature);
+ assertEquals("[Ljava/lang/String;", fsig.toString());
+ }
+
+ public void testFieldSignatureParsingTypeVariable() {
+ FieldTypeSignature fsig = parser.parseAsFieldSignature("TT;");
+ assertTrue("TypeVariableSignature", fsig instanceof GenericSignature.TypeVariableSignature);
+ assertEquals("TT;", fsig.toString());
+ }
+
+ public void testSimpleMethodSignatureParsing() {
+ GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("()V");
+ assertEquals("No type parameters", 0, mSig.formalTypeParameters.length);
+ assertEquals("No parameters", 0, mSig.parameters.length);
+ assertEquals("Void return type", "V", mSig.returnType.toString());
+ assertEquals("No throws", 0, mSig.throwsSignatures.length);
+ }
+
+ public void testMethodSignatureTypeParams() {
+ GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>(TT;)V");
+ assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
+ assertEquals("T", mSig.formalTypeParameters[0].identifier);
+ assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
+ assertEquals("One parameter", 1, mSig.parameters.length);
+ assertEquals("TT;", mSig.parameters[0].toString());
+ assertEquals("Void return type", "V", mSig.returnType.toString());
+ assertEquals("No throws", 0, mSig.throwsSignatures.length);
+ }
+
+ public void testMethodSignatureGenericReturn() {
+ GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>()TT;");
+ assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
+ assertEquals("T", mSig.formalTypeParameters[0].identifier);
+ assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
+ assertEquals("No parameters", 0, mSig.parameters.length);
+ assertEquals("'T' return type", "TT;", mSig.returnType.toString());
+ assertEquals("No throws", 0, mSig.throwsSignatures.length);
+ }
+
+ public void testMethodSignatureThrows() {
+ GenericSignature.MethodTypeSignature mSig = parser
+ .parseAsMethodSignature("<T:>(TT;)V^Ljava/lang/Exception;^Ljava/lang/RuntimeException;");
+ assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
+ assertEquals("T", mSig.formalTypeParameters[0].identifier);
+ assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
+ assertEquals("One parameter", 1, mSig.parameters.length);
+ assertEquals("TT;", mSig.parameters[0].toString());
+ assertEquals("Void return type", "V", mSig.returnType.toString());
+ assertEquals("2 throws", 2, mSig.throwsSignatures.length);
+ assertEquals("Ljava/lang/Exception;", mSig.throwsSignatures[0].toString());
+ assertEquals("Ljava/lang/RuntimeException;", mSig.throwsSignatures[1].toString());
+ }
+
+ public void testMethodSignaturePrimitiveParams() {
+ GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("(ILjava/lang/Object;)V");
+ assertEquals("2 parameters", 2, mSig.parameters.length);
+ assertEquals("I", mSig.parameters[0].toString());
+ assertEquals("Ljava/lang/Object;", mSig.parameters[1].toString());
+ }
+
+ public void testFullyQualifiedSuperclassAfterTypeParams() {
+ try {
+ GenericSignature.FieldTypeSignature cSig = parser.parseAsFieldSignature("Ljava/util/List</;");
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().indexOf("Ljava/util/List</;") != -1);
+ }
+ }
+
+ public void testPr107784() {
+ parser
+ .parseAsMethodSignature("(Lcom/cibc/responders/mapping/CommonDataBeanScenario;Ljava/lang/Object;)Lcom/cibc/responders/response/Formatter<[BLjava/lang/Object;>;");
+ parser.parseAsClassSignature("<Parent:Ljava/lang/Object;Child:Ljava/lang/Object;>Ljava/lang/Object;");
+ }
+
+ private void assertEquals(String[] expected, String[] actual) {
+ if (actual.length != expected.length) {
+ int shorter = Math.min(expected.length, actual.length);
+ for (int i = 0; i < shorter; i++) {
+ if (!actual[i].equals(expected[i])) {
+ fail("Expected " + expected[i] + " at position " + i + " but found " + actual[i]);
+ }
+ }
+ fail("Expected " + expected.length + " tokens but got " + actual.length + tokensToString(actual));
+ }
+ for (int i = 0; i < actual.length; i++) {
+ if (!actual[i].equals(expected[i])) {
+ fail("Expected " + expected[i] + " at position " + i + " but found " + actual[i]);
+ }
+ }
+ }
+
+ private String tokensToString(String[] tokens) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(tokens[0]);
+ for (int i = 1; i < tokens.length; i++) {
+ sb.append(",");
+ sb.append(tokens[i]);
+ }
+ return sb.toString();
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ parser = new GenericSignatureParser();
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * 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.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ */
+public class LangUtilTest extends TestCase {
+
+ public LangUtilTest(String name) {
+ super(name);
+ }
+
+ // /** @see LangUtil.extractOptions(String[], String[], int[], List) */
+ // public void testExtractOptions() {
+ // ArrayList extracted = new ArrayList();
+ // String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
+ // String[] validOptions = new String[] { "-classpath", "-d", "-verbose", "-help" };
+ // int[] optionArgs = new int[] { 1, 1, 0, 0 };
+ // String[] result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // String resultString = "" + Arrays.asList(result);
+ // String EXP = "[Bar.java]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // EXP = "[-d, classes, -classpath, foo.jar, -verbose]";
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ //
+ // // no input, no output
+ // extracted.clear();
+ // args = new String[] {};
+ // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // resultString = "" + Arrays.asList(result);
+ // EXP = "[]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ //
+ // // one input, nothing extracted
+ // extracted.clear();
+ // args = new String[] {"Bar.java"};
+ // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // resultString = "" + Arrays.asList(result);
+ // EXP = "[Bar.java]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // EXP = "[]";
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ //
+ // // one input, extracted
+ // extracted.clear();
+ // args = new String[] {"-verbose"};
+ // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // resultString = "" + Arrays.asList(result);
+ // EXP = "[]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // EXP = "[-verbose]";
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ //
+ // // ------- booleans
+ // validOptions = new String[] { "-help", "-verbose" };
+ // optionArgs = null;
+ //
+ // // one input, extracted
+ // extracted.clear();
+ // args = new String[] {"-verbose"};
+ // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // resultString = "" + Arrays.asList(result);
+ // EXP = "[]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // EXP = "[-verbose]";
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ //
+ // // one input, not extracted
+ // extracted.clear();
+ // args = new String[] {"Bar.java"};
+ // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
+ // resultString = "" + Arrays.asList(result);
+ // EXP = "[Bar.java]";
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // EXP = "[]";
+ // resultString = "" + extracted;
+ // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ // }
+
+ public void testVersion() {
+ assertTrue(LangUtil.is13VMOrGreater()); // min vm now - floor may change
+ if (LangUtil.is15VMOrGreater()) {
+ assertTrue(LangUtil.is14VMOrGreater());
+ }
+ }
+
+ /** @see LangUtil.extractOptions(String[], String[][]) */
+ public void testExtractOptionsArrayCollector() {
+ String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
+ String[][] OPTIONS = new String[][] { new String[] { "-classpath", null }, new String[] { "-d", null },
+ new String[] { "-verbose" }, new String[] { "-help" } };
+
+ String[][] options = LangUtil.copyStrings(OPTIONS);
+
+ String[] result = LangUtil.extractOptions(args, options);
+ String resultString = "" + Arrays.asList(result);
+ String EXP = "[Bar.java]";
+ assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ assertTrue("-verbose".equals(options[2][0]));
+ assertTrue("foo.jar".equals(options[0][1]));
+ assertTrue("classes".equals(options[1][1]));
+ assertTrue("-classpath".equals(options[0][0]));
+ assertTrue("-d".equals(options[1][0]));
+ assertTrue(null == options[3][0]);
+
+ // get args back, no options set
+ args = new String[] { "Bar.java" };
+ options = LangUtil.copyStrings(OPTIONS);
+
+ result = LangUtil.extractOptions(args, options);
+ resultString = "" + Arrays.asList(result);
+ EXP = "[Bar.java]";
+ assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
+ assertTrue(null == options[0][0]);
+ assertTrue(null == options[1][0]);
+ assertTrue(null == options[2][0]);
+ assertTrue(null == options[3][0]);
+ }
+
+ // public void testOptionVariants() {
+ // String[] NONE = new String[0];
+ // String[] one = new String[] {"-1"};
+ // String[] two = new String[] {"-2"};
+ // String[] three= new String[] {"-3"};
+ // String[] both = new String[] {"-1", "-2" };
+ // String[] oneB = new String[] {"-1-"};
+ // String[] bothB = new String[] {"-1-", "-2-" };
+ // String[] onetwoB = new String[] {"-1", "-2-" };
+ // String[] oneBtwo = new String[] {"-1-", "-2" };
+ // String[] threeB = new String[] {"-1-", "-2-", "-3-"};
+ // String[] athreeB = new String[] {"a", "-1-", "-2-", "-3-"};
+ // String[] threeaB = new String[] {"-1-", "a", "-2-", "-3-"};
+ //
+ // checkOptionVariants(NONE, new String[][] { NONE });
+ // checkOptionVariants(one, new String[][] { one });
+ // checkOptionVariants(both, new String[][] { both });
+ // checkOptionVariants(oneB, new String[][] { NONE, one });
+ // checkOptionVariants(bothB, new String[][] { NONE, one, new String[] {"-2"}, both });
+ // checkOptionVariants(onetwoB, new String[][] { one, new String[] {"-1", "-2"}});
+ // checkOptionVariants(oneBtwo, new String[][] { two, new String[] {"-1", "-2"}});
+ // checkOptionVariants(threeB, new String[][]
+ // {
+ // NONE,
+ // one,
+ // two,
+ // new String[] {"-1", "-2"},
+ // three,
+ // new String[] {"-1", "-3"},
+ // new String[] {"-2", "-3"},
+ // new String[] {"-1", "-2", "-3"}
+ // });
+ // checkOptionVariants(athreeB, new String[][]
+ // {
+ // new String[] {"a"},
+ // new String[] {"a", "-1"},
+ // new String[] {"a", "-2"},
+ // new String[] {"a", "-1", "-2"},
+ // new String[] {"a", "-3"},
+ // new String[] {"a", "-1", "-3"},
+ // new String[] {"a", "-2", "-3"},
+ // new String[] {"a", "-1", "-2", "-3"}
+ // });
+ // checkOptionVariants(threeaB, new String[][]
+ // {
+ // new String[] {"a"},
+ // new String[] {"-1", "a"},
+ // new String[] {"a", "-2"},
+ // new String[] {"-1", "a", "-2"},
+ // new String[] {"a", "-3"},
+ // new String[] {"-1", "a", "-3"},
+ // new String[] {"a", "-2", "-3"},
+ // new String[] {"-1", "a", "-2", "-3"}
+ // });
+ // }
+
+ // void checkOptionVariants(String[] options, String[][] expected) {
+ // String[][] result = LangUtil.optionVariants(options);
+ // if (expected.length != result.length) {
+ // assertTrue("exp=" + expected.length + " actual=" + result.length, false);
+ // }
+ // for (int i = 0; i < expected.length; i++) {
+ // assertEquals(""+i,
+ // "" + Arrays.asList(expected[i]),
+ // "" + Arrays.asList(result[i]));
+ // }
+ // }
+
+ /** @see XMLWriterTest#testUnflattenList() */
+ public void testCommaSplit() {
+ checkCommaSplit("", new String[] { "" });
+ checkCommaSplit("1", new String[] { "1" });
+ checkCommaSplit(" 1 2 ", new String[] { "1 2" });
+ checkCommaSplit(" 1 , 2 ", new String[] { "1", "2" });
+ checkCommaSplit("1,2,3,4", new String[] { "1", "2", "3", "4" });
+ }
+
+ void checkCommaSplit(String input, String[] expected) {
+ List actual = LangUtil.commaSplit(input);
+ String a = "" + actual;
+ String e = "" + Arrays.asList(expected);
+ assertTrue(e + "==" + a, e.equals(a));
+ }
+
+ public void testElideEndingLines() {
+ StringBuffer stackBuffer = LangUtil.stackToString(new RuntimeException(""), true);
+ LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 10);
+ String result = stackBuffer.toString();
+
+ if (-1 == result.indexOf("(... ")) {
+ // brittle - will fail under different top-level drivers
+ String m = "when running under eclipse or Ant, expecting (... in trace: ";
+ assertTrue(m + result, false);
+ }
+
+ stackBuffer = new StringBuffer(
+ "java.lang.RuntimeException: unimplemented"
+ + "\n at org.aspectj.ajdt.internal.core.builder.EclipseUnwovenClassFile.writeWovenBytes(EclipseUnwovenClassFile.java:59)"
+ + "\n at org.aspectj.weaver.bcel.BcelWeaver.dump(BcelWeaver.java:271)"
+ + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:233)"
+ + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:198)"
+ + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.weaveAndGenerateClassFiles(AjBuildanager.java:230)"
+ + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:50)"
+ + "\n at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:42)"
+ + "\n at org.aspectj.testing.harness.bridge.CompilerRun.run(CompilerRun.java:222)"
+ + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
+ + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
+ + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
+ + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
+ + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
+ + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
+ + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
+ + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
+ + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
+ + "\n at org.aspectj.testing.run.Runner.run(Runner.java:114)"
+ + "\n at org.aspectj.testing.run.Runner.run(Runner.java:105)"
+ + "\n at org.aspectj.testing.run.Runner.runIterator(Runner.java:228)"
+ + "\n at org.aspectj.testing.drivers.Harness.run(Harness.java:254)"
+ + "\n at org.aspectj.testing.drivers.Harness.runMain(Harness.java:217)"
+ + "\n at org.aspectj.testing.drivers.Harness.main(Harness.java:99)"
+ + "\n at org.aspectj.testing.Harness.main(Harness.java:37)" + "\n clip me");
+
+ LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 25);
+ result = stackBuffer.toString();
+ assertTrue(result, -1 != result.indexOf("(... "));
+ assertTrue(result, -1 == result.indexOf("org.aspectj.testing"));
+ }
+}
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-//import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.StringBufferInputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-import junit.textui.TestRunner;
-
-/**
- *
- */
-public class FileUtilTest extends TestCase {
- public static final String[] NONE = new String[0];
- public static boolean log = false;
-
- public static void main(String[] args) {
- TestRunner.main(new String[] { "org.aspectj.util.FileUtilTest" });
- }
-
- public static void assertSame(String prefix, String[] lhs, String[] rhs) { // XXX cheap diff
- String srcPaths = LangUtil.arrayAsList(lhs).toString();
- String destPaths = LangUtil.arrayAsList(rhs).toString();
- if (!srcPaths.equals(destPaths)) {
- log("expected: " + srcPaths);
- log(" actual: " + destPaths);
- assertTrue(prefix + " expected=" + srcPaths + " != actual=" + destPaths, false);
- }
- }
-
- /**
- * Verify that dir contains files with names, and return the names of other files in dir.
- *
- * @return the contents of dir after excluding files or NONE if none
- * @throws AssertionFailedError if any names are not in dir
- */
- public static String[] dirContains(File dir, final String[] filenames) {
- final ArrayList<String> sought = new ArrayList<>(LangUtil.arrayAsList(filenames));
- FilenameFilter filter = new FilenameFilter() {
- public boolean accept(File d, String name) {
- return !sought.remove(name);
- }
- };
- // remove any found from sought and return remainder
- String[] found = dir.list(filter);
- if (0 < sought.size()) {
- assertTrue("found " + LangUtil.arrayAsList(dir.list()).toString() + " expected " + sought, false);
- }
- return (found.length == 0 ? NONE : found);
- }
-
- /** @return sorted String[] of all paths to all files/dirs under dir */
- public static String[] dirPaths(File dir) {
- return dirPaths(dir, new String[0]);
- }
-
- /**
- * Get a sorted String[] of all paths to all files/dirs under dir. Files with names starting with "." are ignored, as are
- * directory paths containing "CVS". The directory prefix of the path is stripped. Thus, given directory:
- *
- * <pre>
- * path/to
- * .cvsignore
- * CVS/
- * Root
- * Repository
- * Base.java
- * com/
- * parc/
- * messages.properties
- * org/
- * aspectj/
- * Version.java
- * </pre>
- *
- * a call
- *
- * <pre>
- * dirPaths(new File("path/to"), new String[0]);
- * </pre>
- *
- * returns
- *
- * <pre>
- * { "Base.java", "com/parc/messages.properties", "org/aspectj/Version.java" }
- * </pre>
- *
- * while the call
- *
- * <pre>
- * dirPaths(new File("path/to"), new String[] { ".java" });
- * </pre>
- *
- * returns
- *
- * <pre>
- * { "Base.java", "org/aspectj/Version.java" }
- * </pre>
- *
- * @param dir the File path to the directory to inspect
- * @param suffixes if not empty, require files returned to have this suffix
- * @return sorted String[] of all paths to all files under dir ending with one of the listed suffixes but not starting with "."
- */
- public static String[] dirPaths(File dir, String[] suffixes) {
- ArrayList<String> result = new ArrayList<String>();
- doDirPaths(dir, result);
- // if suffixes required, remove those without suffixes
- if (!LangUtil.isEmpty(suffixes)) {
- for (ListIterator<String> iter = result.listIterator(); iter.hasNext();) {
- String path = iter.next().toString();
- boolean hasSuffix = false;
- for (int i = 0; !hasSuffix && (i < suffixes.length); i++) {
- hasSuffix = path.endsWith(suffixes[i]);
- }
- if (!hasSuffix) {
- iter.remove();
- }
- }
- }
- Collections.sort(result);
- // trim prefix
- final String prefix = dir.getPath();
- final int len = prefix.length() + 1; // plus directory separator
- String[] ra = (String[]) result.toArray(new String[0]);
- for (int i = 0; i < ra.length; i++) {
- // assertTrue(ra[i].startsWith(prefix));
- assertTrue(ra[i], ra[i].length() > len);
- ra[i] = ra[i].substring(len);
- }
- return ra;
- }
-
- /**
- * @param dir the File to read - ignored if null, not a directory, or has "CVS" in its path
- * @param useSuffix if true, then use dir as suffix to path
- */
- private static void doDirPaths(File dir, ArrayList<String> paths) {
- if ((null == dir) || !dir.canRead() || (-1 != dir.getPath().indexOf("CVS"))) {
- return;
- }
- File[] files = dir.listFiles();
- for (int i = 0; i < files.length; i++) {
- String path = files[i].getPath();
- if (!files[i].getName().startsWith(".")) {
- if (files[i].isFile()) {
- paths.add(path);
- } else if (files[i].isDirectory()) {
- doDirPaths(files[i], paths);
- } else {
- log("not file or dir: " + dir + "/" + path);
- }
- }
- }
- }
-
- /** Print s if logging is enabled */
- private static void log(String s) {
- if (log) {
- System.err.println(s);
- }
- }
-
- /** List of File files or directories to delete when exiting */
- final ArrayList<File> tempFiles;
-
- public FileUtilTest(String s) {
- super(s);
- tempFiles = new ArrayList<File>();
- }
-
- public void tearDown() {
- for (ListIterator<File> iter = tempFiles.listIterator(); iter.hasNext();) {
- File dir = (File) iter.next();
- log("removing " + dir);
- FileUtil.deleteContents(dir);
- dir.delete();
- iter.remove();
- }
- }
-
- public void testNotIsFileIsDirectory() {
- File noSuchFile = new File("foo");
- assertTrue(!noSuchFile.isFile());
- assertTrue(!noSuchFile.isDirectory());
- }
-
- public void testGetBestFile() {
- assertNull(FileUtil.getBestFile((String[]) null));
- assertNull(FileUtil.getBestFile(new String[0]));
- assertNull(FileUtil.getBestFile(new String[] { "!" }));
- File f = FileUtil.getBestFile(new String[] { "." });
- assertNotNull(f);
- f = FileUtil.getBestFile(new String[] { "!", "." });
- assertNotNull(f);
- assertTrue(f.canRead());
- boolean setProperty = false;
- try {
- System.setProperty("bestfile", ".");
- setProperty = true;
- } catch (Throwable t) {
- // ignore Security, etc.
- }
- if (setProperty) {
- f = FileUtil.getBestFile(new String[] { "sp:bestfile" });
- assertNotNull(f);
- assertTrue(f.canRead());
- }
- }
-
- public void testCopyFiles() {
- // bad input
- Class<?> iaxClass = IllegalArgumentException.class;
-
- checkCopyFiles(null, null, iaxClass, false);
-
- File noSuchFile = new File("foo");
- checkCopyFiles(noSuchFile, null, iaxClass, false);
- checkCopyFiles(noSuchFile, noSuchFile, iaxClass, false);
-
- File tempDir = FileUtil.getTempDir("testCopyFiles");
- tempFiles.add(tempDir);
- File fromFile = new File(tempDir, "fromFile");
- String err = FileUtil.writeAsString(fromFile, "contents of from file");
- assertTrue(err, null == err);
- checkCopyFiles(fromFile, null, iaxClass, false);
- checkCopyFiles(fromFile, fromFile, iaxClass, false);
-
- // file-file
- File toFile = new File(tempDir, "toFile");
- checkCopyFiles(fromFile, toFile, null, true);
-
- // file-dir
- File toDir = new File(tempDir, "toDir");
- assertTrue(toDir.mkdirs());
- checkCopyFiles(fromFile, toDir, null, true);
-
- // dir-dir
- File fromDir = new File(tempDir, "fromDir");
- assertTrue(fromDir.mkdirs());
- checkCopyFiles(fromFile, fromDir, null, false);
- File toFile2 = new File(fromDir, "toFile2");
- checkCopyFiles(fromFile, toFile2, null, false);
- checkCopyFiles(fromDir, toDir, null, true);
- }
-
- void checkCopyFiles(File from, File to, Class exceptionClass, boolean clean) {
- try {
- FileUtil.copyFile(from, to);
- assertTrue(null == exceptionClass);
- if (to.isFile()) {
- assertTrue(from.length() == to.length()); // XXX cheap test
- } else if (!from.isDirectory()) {
- File toFile = new File(to, from.getName());
- assertTrue(from.length() == toFile.length());
- } else {
- // from is a dir and to is a dir, toDir should be created, and have the
- // same contents as fromDir.
- assertTrue(to.exists());
- assertTrue(from.listFiles().length == to.listFiles().length);
- }
- } catch (Throwable t) {
- assertTrue(null != exceptionClass);
- assertTrue(exceptionClass.isAssignableFrom(t.getClass()));
- } finally {
- if (clean && (null != to) && (to.exists())) {
- if (to.isDirectory()) {
- FileUtil.deleteContents(to);
- }
- to.delete();
- }
- }
- }
-
- public void testDirCopySubdirs() throws IOException {
- File srcDir = new File("src");
- File destDir = FileUtil.getTempDir("testDirCopySubdirs");
- tempFiles.add(destDir);
- FileUtil.copyDir(srcDir, destDir);
- assertSame("testDirCopySubdirs", dirPaths(srcDir), dirPaths(destDir));
- }
-
- public void testDirCopySubdirsSuffix() throws IOException {
- File srcDir = new File("src");
- File destDir = FileUtil.getTempDir("testDirCopySubdirsSuffix");
- tempFiles.add(destDir);
- FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
-
- String[] sources = dirPaths(srcDir, new String[] { ".java" });
- for (int i = 0; i < sources.length; i++) {
- sources[i] = sources[i].substring(0, sources[i].length() - 4);
- }
- String[] sinks = dirPaths(destDir, new String[] { ".aj" });
- for (int i = 0; i < sinks.length; i++) {
- sinks[i] = sinks[i].substring(0, sinks[i].length() - 2);
- }
- assertSame("testDirCopySubdirs", sources, sinks);
- }
-
- public void testGetURL() {
- String[] args = new String[] { ".", "../util/testdata", "../lib/test/aspectjrt.jar" };
- for (int i = 0; i < args.length; i++) {
- checkGetURL(args[i]);
- }
- }
-
- /**
- * Method checkGetURL.
- *
- * @param string
- * @param uRL
- */
- private void checkGetURL(String arg) {
- assertTrue(null != arg);
- File f = new File(arg);
- URL url = FileUtil.getFileURL(f);
- assertTrue(null != url);
- log("url " + url);
- if (!f.exists()) {
- log("not exist " + f);
- } else if (f.isDirectory()) {
- log("directory " + f);
- } else {
- log(" file " + f);
- InputStream in = null;
- try {
- in = url.openStream();
- } catch (IOException e) {
- assertTrue("IOException: " + e, false);
- } finally {
- if (null != in) {
- try {
- in.close();
- } catch (IOException e) {
- }
- }
- }
- }
- }
-
- public void testGetTempDir() {
- boolean pass = true;
- boolean delete = true;
- checkGetTempDir("parent", null, pass, delete);
- checkGetTempDir(null, "child", pass, delete);
- tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
- tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
- tempFiles.add(checkGetTempDir("parent", "child", pass, !delete).getParentFile());
- }
-
- File checkGetTempDir(String parent, String child, boolean ok, boolean delete) {
- File parentDir = FileUtil.getTempDir(parent);
- assertTrue("unable to create " + parent, null != parentDir);
- File dir = FileUtil.makeNewChildDir(parentDir, child);
- log("parent=" + parent + " child=" + child + " -> " + dir);
- assertTrue("dir: " + dir, ok == (dir.canWrite() && dir.isDirectory()));
- if (delete) {
- dir.delete();
- parentDir.delete();
- }
- return dir;
- }
-
- public void testRandomFileString() {
- ArrayList<String> results = new ArrayList<>();
- for (int i = 0; i < 1000; i++) {
- String s = FileUtil.randomFileString();
- if (results.contains(s)) {
- log("warning: got duplicate at iteration " + i);
- }
- results.add(s);
- // System.err.print(" " + s);
- // if (0 == (i % 5)) {
- // System.err.println("");
- // }
- }
- }
-
- public void testNormalizedPath() {
- File tempFile = null;
- try {
- tempFile = File.createTempFile("FileUtilTest_testNormalizedPath", "tmp");
- tempFiles.add(tempFile);
- } catch (IOException e) {
- log("aborting test - unable to create temp file");
- return;
- }
- File parentDir = tempFile.getParentFile();
- String tempFilePath = FileUtil.normalizedPath(tempFile, parentDir);
- assertEquals(tempFile.getName(), tempFilePath);
- }
-
- public void testFileToClassName() {
-
- File basedir = new File("/base/dir"); // never created
- File classFile = new File(basedir, "foo/Bar.class");
- assertEquals("foo.Bar", FileUtil.fileToClassName(basedir, classFile));
-
- classFile = new File(basedir, "foo\\Bar.class");
- assertEquals("foo.Bar", FileUtil.fileToClassName(basedir, classFile));
-
- assertEquals("Bar", FileUtil.fileToClassName(null, classFile));
-
- classFile = new File("/home/classes/org/aspectj/lang/JoinPoint.class");
- assertEquals("org.aspectj.lang.JoinPoint", FileUtil.fileToClassName(null, classFile));
-
- classFile = new File("/home/classes/com/sun/tools/Javac.class");
- assertEquals("com.sun.tools.Javac", FileUtil.fileToClassName(null, classFile));
- }
-
- public void testDeleteContents() {
- File tempDir = FileUtil.getTempDir("testDeleteContents");
- tempFiles.add(tempDir);
- File f = new File(tempDir, "foo");
- f.mkdirs();
- File g = new File(f, "bar");
- g.mkdirs();
- File h = new File(g, "bash");
- h.mkdirs();
- int d = FileUtil.deleteContents(f);
- assertTrue(0 == d);
- assertTrue(0 == f.list().length);
- f.delete();
- assertTrue(!f.exists());
- }
-
- public void testLineSeek() {
- File tempDir = FileUtil.getTempDir("testLineSeek");
- tempFiles.add(tempDir);
- File file = new File(tempDir, "testLineSeek");
- String path = file.getPath();
- String contents = "0123456789" + LangUtil.EOL;
- contents += contents;
- FileUtil.writeAsString(file, contents);
- tempFiles.add(file);
- List<String> sourceList = new ArrayList<String>();
- sourceList.add(file.getPath());
-
- final ArrayList<String> errors = new ArrayList<String>();
- final PrintStream errorSink = new PrintStream(System.err, true) {
- public void println(String error) {
- errors.add(error);
- }
- };
- for (int i = 0; i < 10; i++) {
- List<String> result = FileUtil.lineSeek("" + i, sourceList, true, errorSink);
- assertEquals(2, result.size());
- assertEquals(path + ":1:" + i, result.get(0));
- assertEquals(path + ":2:" + i, result.get(1));
- if (!LangUtil.isEmpty(errors)) { // XXX prefer fast-fail?
- assertTrue("errors: " + errors, false);
- }
- }
-
- }
-
- public void testLineSeekMore() {
- final int MAX = 3; // 1..10
- File tempDir = FileUtil.getTempDir("testLineSeekMore");
- tempFiles.add(tempDir);
- final String prefix = new File(tempDir, "testLineSeek").getPath();
- // setup files 0..MAX with 2*MAX lines
- String[] sources = new String[MAX];
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < sources.length; i++) {
- sources[i] = new File(prefix + i).getPath();
- sb.append("not matched");
- sb.append(LangUtil.EOL);
- sb.append("0123456789");
- sb.append(LangUtil.EOL);
- }
- final String contents = sb.toString();
- for (int i = 0; i < sources.length; i++) {
- File file = new File(sources[i]);
- FileUtil.writeAsString(file, contents);
- tempFiles.add(file);
- }
- // now test
- final ArrayList<String> errors = new ArrayList<>();
- final PrintStream errorSink = new PrintStream(System.err, true) {
- public void println(String error) {
- errors.add(error);
- }
- };
- List<String> sourceList = new ArrayList<>();
- sourceList.addAll(Arrays.asList(sources));
- sourceList = Collections.unmodifiableList(sourceList);
- for (int k = 0; k < sources.length; k++) {
- List<String> result = FileUtil.lineSeek("" + k, sourceList, true, errorSink);
- // number k found in every other line of every file at index k
- Iterator<String> iter = result.iterator();
- for (int i = 0; i < MAX; i++) { // for each file
- for (int j = 1; j < (MAX + 1); j++) { // for every other line
- assertTrue(iter.hasNext());
- assertEquals(prefix + i + ":" + 2 * j + ":" + k, iter.next());
- }
- }
- if (!LangUtil.isEmpty(errors)) { // XXX prefer fast-fail?
- assertTrue("errors: " + errors, false);
- }
- }
- }
-
- public void testDirCopyNoSubdirs() throws IOException {
- String[] srcFiles = new String[] { "one.java", "two.java", "three.java" };
- String[] destFiles = new String[] { "three.java", "four.java", "five.java" };
- String[] allFiles = new String[] { "one.java", "two.java", "three.java", "four.java", "five.java" };
- File srcDir = makeTempDir("FileUtilUT_srcDir", srcFiles);
- File destDir = makeTempDir("FileUtilUT_destDir", destFiles);
- assertTrue(null != srcDir);
- assertTrue(null != destDir);
- assertTrue(NONE == dirContains(srcDir, srcFiles));
- assertTrue(NONE == dirContains(destDir, destFiles));
-
- FileUtil.copyDir(srcDir, destDir);
- String[] resultOne = dirContains(destDir, allFiles);
- FileUtil.copyDir(srcDir, destDir);
- String[] resultTwo = dirContains(destDir, allFiles);
-
- assertTrue(NONE == resultOne);
- assertTrue(NONE == resultTwo);
- }
-
- public void testDirCopyNoSubdirsWithSuffixes() throws IOException {
- String[] srcFiles = new String[] { "one.java", "two.java", "three.java" };
- String[] destFiles = new String[] { "three.java", "four.java", "five.java" };
- String[] allFiles = new String[] { "one.aj", "two.aj", "three.aj", "three.java", "four.java", "five.java" };
- File srcDir = makeTempDir("FileUtilUT_srcDir", srcFiles);
- File destDir = makeTempDir("FileUtilUT_destDir", destFiles);
- assertTrue(null != srcDir);
- assertTrue(null != destDir);
- assertTrue(NONE == dirContains(srcDir, srcFiles));
- assertTrue(NONE == dirContains(destDir, destFiles));
-
- FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
- FileUtil.copyDir(srcDir, destDir, ".java", ".aj");
-
- assertTrue(NONE == dirContains(destDir, allFiles));
- assertTrue(NONE == dirContains(destDir, allFiles));
- }
-
- public void testDirCopySubdirsSuffixRoundTrip() throws IOException {
- final File srcDir = new File("src");
- final File one = FileUtil.getTempDir("testDirCopySubdirsSuffixRoundTrip_1");
- final File two = FileUtil.getTempDir("testDirCopySubdirsSuffixRoundTrip_2");
- FileUtil.copyDir(srcDir, one); // no selection
- FileUtil.copyDir(two, one, ".java", ".aj"); // only .java files
- FileUtil.copyDir(one, two, ".aj", ".java");
-
- FileUtil.deleteContents(one);
- one.delete();
- FileUtil.deleteContents(two);
- two.delete();
- }
-
- /**
- * Create temp dir at loc containing temp files files. Result is registered for deletion on cleanup.
- */
- File makeTempDir(String loc, String[] filenames) throws IOException {
- File d = new File(loc);
- d.mkdirs();
- assertTrue(d.exists());
- tempFiles.add(d);
- assertTrue(d.canWrite());
- for (int i = 0; i < filenames.length; i++) {
- File f = new File(d, filenames[i]);
- assertTrue(filenames[i], f.createNewFile());
- }
- return d;
- }
-
- public void testPipeEmpty() {
- checkPipe("");
- }
-
- public void testPipeMin() {
- checkPipe("0");
- }
-
- public void testPipe() {
- String str = "The quick brown fox jumped over the lazy dog";
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < 4096; i++) {
- sb.append(str);
- }
- checkPipe(sb.toString());
- }
-
- void checkPipe(String data) {
- StringBufferInputStream in = new StringBufferInputStream(data);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true);
- pipe.run();
- assertTrue(data.equals(out.toString()));
- assertTrue(null == pipe.getThrown());
- assertEquals("totalWritten", data.length(), pipe.totalWritten());
- }
-
- public void testPipeThrown() {
- final String data = "The quick brown fox jumped over the lazy dog";
- final IOException thrown = new IOException("test");
- StringBufferInputStream in = new StringBufferInputStream(data);
- OutputStream out = new OutputStream() {
- public void write(int b) throws IOException {
- throw thrown;
- }
- };
-
- FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true);
- pipe.run();
- assertEquals("totalWritten", 0, pipe.totalWritten());
- assertTrue(thrown == pipe.getThrown());
- }
-
- public void xtestPipeHalt() { // this test periodically fails on the build machine -
- // disabling till we have time to figure out why
- final long MAX = 1000000;
- InputStream in = new InputStream() {
- long max = 0;
-
- public int read() throws IOException {
- if (max++ > MAX) {
- throw new IOException("test failed");
- }
- return 1;
- }
-
- };
- final int minWritten = 20;
- class Flag {
- boolean hit;
- }
- final Flag flag = new Flag();
- OutputStream out = new OutputStream() {
- long max = 0;
-
- public void write(int b) throws IOException {
- if (max++ > MAX) {
- throw new IOException("test failed");
- } else if (max > minWritten) {
- if (!flag.hit) {
- flag.hit = true;
- }
- }
- }
- };
- class Result {
- long totalWritten;
- Throwable thrown;
- boolean set;
- }
- final Result result = new Result();
- FileUtil.Pipe pipe = new FileUtil.Pipe(in, out, 100l, true, true) {
- protected void completing(long totalWritten, Throwable thrown) {
- result.totalWritten = totalWritten;
- result.thrown = thrown;
- result.set = true;
- }
- };
- // start it up
- new Thread(pipe).start();
- // wait for minWritten input
- while (!flag.hit) {
- try {
- Thread.sleep(5l);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- // halt
- assertTrue(pipe.halt(true, true));
- assertTrue(result.set);
- assertTrue("Expected null but result.thrown = " + result.thrown, null == result.thrown);
- assertTrue(null == pipe.getThrown());
- assertEquals("total written", result.totalWritten, pipe.totalWritten());
- if (minWritten > pipe.totalWritten()) {
- assertTrue("written: " + pipe.totalWritten(), false);
- }
- }
-
-}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005-2008 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
- *
- * ******************************************************************/
-
-package org.aspectj.util;
-
-import junit.framework.TestCase;
-
-import org.aspectj.util.GenericSignature.ClassSignature;
-import org.aspectj.util.GenericSignature.ClassTypeSignature;
-import org.aspectj.util.GenericSignature.FieldTypeSignature;
-import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
-
-/**
- * @author Adrian Colyer
- * @author Andy Clement
- */
-public class GenericSignatureParserTest extends TestCase {
-
- GenericSignatureParser parser;
-
- public void testSimpleTokenize() {
- String[] tokens = parser.tokenize("Ljava/lang/String;");
- assertEquals(new String[] { "Ljava", "/", "lang", "/", "String", ";" }, tokens);
- }
-
- public void testTokenizeWithWildTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/lang/String<*>;");
- assertEquals(new String[] { "Ljava", "/", "lang", "/", "String", "<", "*", ">", ";" }, tokens);
- }
-
- public void testTokenizeWithExtendsTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/util/List<+TE>;");
- assertEquals(new String[] { "Ljava", "/", "util", "/", "List", "<", "+", "TE", ">", ";" }, tokens);
- }
-
- public void testTokenizeWithSuperTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/util/List<-TE>;");
- assertEquals(new String[] { "Ljava", "/", "util", "/", "List", "<", "-", "TE", ">", ";" }, tokens);
- }
-
- public void testTokenizeArrayType() {
- String[] tokens = parser.tokenize("[Ljava/lang/String;");
- assertEquals(new String[] { "[", "Ljava", "/", "lang", "/", "String", ";" }, tokens);
- }
-
- public void testTokenizeFormalTypeParameters() {
- String[] tokens = parser.tokenize("<T:Ljava/lang/String;:Ljava/util/Comparable;>");
- assertEquals(new String[] { "<", "T", ":", "Ljava", "/", "lang", "/", "String", ";", ":", "Ljava", "/", "util", "/",
- "Comparable", ";", ">" }, tokens);
- }
-
- public void testParseClassSignatureSimple() {
- ClassSignature sig = parser.parseAsClassSignature("Ljava/lang/String;");
- assertEquals("No type parameters", 0, sig.formalTypeParameters.length);
- assertEquals("No superinterfaces", 0, sig.superInterfaceSignatures.length);
- assertEquals("Ljava/lang/String;", sig.superclassSignature.classSignature);
- SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
- assertEquals("Ljava/lang/String;", outerType.identifier);
- assertEquals("No type args", 0, outerType.typeArguments.length);
- }
-
- public void testParseClassSignatureTypeArgs() {
- ClassSignature sig = parser.parseAsClassSignature("Ljava/util/List<+Ljava/lang/String;>;");
- assertEquals("No type parameters", 0, sig.formalTypeParameters.length);
- assertEquals("No superinterfaces", 0, sig.superInterfaceSignatures.length);
- assertEquals("Ljava/util/List<+Ljava/lang/String;>;", sig.superclassSignature.classSignature);
- SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
- assertEquals("Ljava/util/List", outerType.identifier);
- assertEquals("One type arg", 1, outerType.typeArguments.length);
- assertTrue(outerType.typeArguments[0].isPlus);
- assertEquals("+Ljava/lang/String;", outerType.typeArguments[0].toString());
- }
-
- public void testParseClassSignatureTheFullMonty() {
- ClassSignature sig = parser
- .parseAsClassSignature("<E:Ljava/lang/String;:Ljava/lang/Number<TE;>;>Ljava/util/List<TE;>;Ljava/util/Comparable<-TE;>;");
- assertEquals("1 formal parameter", 1, sig.formalTypeParameters.length);
- assertEquals("E", sig.formalTypeParameters[0].identifier);
- ClassTypeSignature fsig = (ClassTypeSignature) sig.formalTypeParameters[0].classBound;
- assertEquals("Ljava/lang/String;", fsig.classSignature);
- assertEquals("1 interface bound", 1, sig.formalTypeParameters[0].interfaceBounds.length);
- ClassTypeSignature isig = (ClassTypeSignature) sig.formalTypeParameters[0].interfaceBounds[0];
- assertEquals("Ljava/lang/Number<TE;>;", isig.classSignature);
- assertEquals("Ljava/util/List<TE;>;", sig.superclassSignature.classSignature);
- assertEquals("1 type argument", 1, sig.superclassSignature.outerType.typeArguments.length);
- assertEquals("TE;", sig.superclassSignature.outerType.typeArguments[0].toString());
- assertEquals("1 super interface", 1, sig.superInterfaceSignatures.length);
- assertEquals("Ljava/util/Comparable<-TE;>;", sig.superInterfaceSignatures[0].toString());
- }
-
- public void testFunky_406167() {
- ClassSignature sig = parser
- .parseAsClassSignature("Lcom/google/android/gms/internal/hb<TT;>.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
- // Note the package prefix on the nested types has been dropped
- assertEquals("Lcom/google/android/gms/internal/hb<TT;>.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
- sig = parser
- .parseAsClassSignature("Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
- // Note the package prefix on the nested types has been dropped
- assertEquals("Lcom/a/a/b/t<TK;TV;>.af.ag;",sig.superclassSignature.toString());
- assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
- sig = parser.parseAsClassSignature("Lcom/google/android/gms/internal/hb.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
- // Note the package prefix on the nested types has been dropped
- assertEquals("Lcom/google/android/gms/internal/hb.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
- sig = parser
- .parseAsClassSignature("Lcom/a/a/b/t.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
- // Note the package prefix on the nested types has been dropped
- assertEquals("Lcom/a/a/b/t.af.ag;",sig.superclassSignature.toString());
- assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
- }
-
-
- public void testFieldSignatureParsingClassType() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("Ljava/lang/String;");
- assertTrue("ClassTypeSignature", fsig instanceof ClassTypeSignature);
- assertEquals("Ljava/lang/String;", fsig.toString());
- }
-
- public void testFieldSignatureParsingArrayType() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("[Ljava/lang/String;");
- assertTrue("ArrayTypeSignature", fsig instanceof GenericSignature.ArrayTypeSignature);
- assertEquals("[Ljava/lang/String;", fsig.toString());
- }
-
- public void testFieldSignatureParsingTypeVariable() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("TT;");
- assertTrue("TypeVariableSignature", fsig instanceof GenericSignature.TypeVariableSignature);
- assertEquals("TT;", fsig.toString());
- }
-
- public void testSimpleMethodSignatureParsing() {
- GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("()V");
- assertEquals("No type parameters", 0, mSig.formalTypeParameters.length);
- assertEquals("No parameters", 0, mSig.parameters.length);
- assertEquals("Void return type", "V", mSig.returnType.toString());
- assertEquals("No throws", 0, mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureTypeParams() {
- GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>(TT;)V");
- assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
- assertEquals("T", mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("One parameter", 1, mSig.parameters.length);
- assertEquals("TT;", mSig.parameters[0].toString());
- assertEquals("Void return type", "V", mSig.returnType.toString());
- assertEquals("No throws", 0, mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureGenericReturn() {
- GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>()TT;");
- assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
- assertEquals("T", mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("No parameters", 0, mSig.parameters.length);
- assertEquals("'T' return type", "TT;", mSig.returnType.toString());
- assertEquals("No throws", 0, mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureThrows() {
- GenericSignature.MethodTypeSignature mSig = parser
- .parseAsMethodSignature("<T:>(TT;)V^Ljava/lang/Exception;^Ljava/lang/RuntimeException;");
- assertEquals("One type parameter", 1, mSig.formalTypeParameters.length);
- assertEquals("T", mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;", mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("One parameter", 1, mSig.parameters.length);
- assertEquals("TT;", mSig.parameters[0].toString());
- assertEquals("Void return type", "V", mSig.returnType.toString());
- assertEquals("2 throws", 2, mSig.throwsSignatures.length);
- assertEquals("Ljava/lang/Exception;", mSig.throwsSignatures[0].toString());
- assertEquals("Ljava/lang/RuntimeException;", mSig.throwsSignatures[1].toString());
- }
-
- public void testMethodSignaturePrimitiveParams() {
- GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("(ILjava/lang/Object;)V");
- assertEquals("2 parameters", 2, mSig.parameters.length);
- assertEquals("I", mSig.parameters[0].toString());
- assertEquals("Ljava/lang/Object;", mSig.parameters[1].toString());
- }
-
- public void testFullyQualifiedSuperclassAfterTypeParams() {
- try {
- GenericSignature.FieldTypeSignature cSig = parser.parseAsFieldSignature("Ljava/util/List</;");
- fail("Expected IllegalStateException");
- } catch (IllegalStateException ex) {
- assertTrue(ex.getMessage().indexOf("Ljava/util/List</;") != -1);
- }
- }
-
- public void testPr107784() {
- parser
- .parseAsMethodSignature("(Lcom/cibc/responders/mapping/CommonDataBeanScenario;Ljava/lang/Object;)Lcom/cibc/responders/response/Formatter<[BLjava/lang/Object;>;");
- parser.parseAsClassSignature("<Parent:Ljava/lang/Object;Child:Ljava/lang/Object;>Ljava/lang/Object;");
- }
-
- private void assertEquals(String[] expected, String[] actual) {
- if (actual.length != expected.length) {
- int shorter = Math.min(expected.length, actual.length);
- for (int i = 0; i < shorter; i++) {
- if (!actual[i].equals(expected[i])) {
- fail("Expected " + expected[i] + " at position " + i + " but found " + actual[i]);
- }
- }
- fail("Expected " + expected.length + " tokens but got " + actual.length + tokensToString(actual));
- }
- for (int i = 0; i < actual.length; i++) {
- if (!actual[i].equals(expected[i])) {
- fail("Expected " + expected[i] + " at position " + i + " but found " + actual[i]);
- }
- }
- }
-
- private String tokensToString(String[] tokens) {
- StringBuffer sb = new StringBuffer();
- sb.append(tokens[0]);
- for (int i = 1; i < tokens.length; i++) {
- sb.append(",");
- sb.append(tokens[i]);
- }
- return sb.toString();
- }
-
- protected void setUp() throws Exception {
- super.setUp();
- parser = new GenericSignatureParser();
- }
-}
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-import java.util.Arrays;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-/**
- *
- */
-public class LangUtilTest extends TestCase {
-
- public LangUtilTest(String name) {
- super(name);
- }
-
- // /** @see LangUtil.extractOptions(String[], String[], int[], List) */
- // public void testExtractOptions() {
- // ArrayList extracted = new ArrayList();
- // String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
- // String[] validOptions = new String[] { "-classpath", "-d", "-verbose", "-help" };
- // int[] optionArgs = new int[] { 1, 1, 0, 0 };
- // String[] result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // String resultString = "" + Arrays.asList(result);
- // String EXP = "[Bar.java]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // EXP = "[-d, classes, -classpath, foo.jar, -verbose]";
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- //
- // // no input, no output
- // extracted.clear();
- // args = new String[] {};
- // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // resultString = "" + Arrays.asList(result);
- // EXP = "[]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- //
- // // one input, nothing extracted
- // extracted.clear();
- // args = new String[] {"Bar.java"};
- // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // resultString = "" + Arrays.asList(result);
- // EXP = "[Bar.java]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // EXP = "[]";
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- //
- // // one input, extracted
- // extracted.clear();
- // args = new String[] {"-verbose"};
- // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // resultString = "" + Arrays.asList(result);
- // EXP = "[]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // EXP = "[-verbose]";
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- //
- // // ------- booleans
- // validOptions = new String[] { "-help", "-verbose" };
- // optionArgs = null;
- //
- // // one input, extracted
- // extracted.clear();
- // args = new String[] {"-verbose"};
- // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // resultString = "" + Arrays.asList(result);
- // EXP = "[]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // EXP = "[-verbose]";
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- //
- // // one input, not extracted
- // extracted.clear();
- // args = new String[] {"Bar.java"};
- // result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
- // resultString = "" + Arrays.asList(result);
- // EXP = "[Bar.java]";
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // EXP = "[]";
- // resultString = "" + extracted;
- // assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- // }
-
- public void testVersion() {
- assertTrue(LangUtil.is13VMOrGreater()); // min vm now - floor may change
- if (LangUtil.is15VMOrGreater()) {
- assertTrue(LangUtil.is14VMOrGreater());
- }
- }
-
- /** @see LangUtil.extractOptions(String[], String[][]) */
- public void testExtractOptionsArrayCollector() {
- String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
- String[][] OPTIONS = new String[][] { new String[] { "-classpath", null }, new String[] { "-d", null },
- new String[] { "-verbose" }, new String[] { "-help" } };
-
- String[][] options = LangUtil.copyStrings(OPTIONS);
-
- String[] result = LangUtil.extractOptions(args, options);
- String resultString = "" + Arrays.asList(result);
- String EXP = "[Bar.java]";
- assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- assertTrue("-verbose".equals(options[2][0]));
- assertTrue("foo.jar".equals(options[0][1]));
- assertTrue("classes".equals(options[1][1]));
- assertTrue("-classpath".equals(options[0][0]));
- assertTrue("-d".equals(options[1][0]));
- assertTrue(null == options[3][0]);
-
- // get args back, no options set
- args = new String[] { "Bar.java" };
- options = LangUtil.copyStrings(OPTIONS);
-
- result = LangUtil.extractOptions(args, options);
- resultString = "" + Arrays.asList(result);
- EXP = "[Bar.java]";
- assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
- assertTrue(null == options[0][0]);
- assertTrue(null == options[1][0]);
- assertTrue(null == options[2][0]);
- assertTrue(null == options[3][0]);
- }
-
- // public void testOptionVariants() {
- // String[] NONE = new String[0];
- // String[] one = new String[] {"-1"};
- // String[] two = new String[] {"-2"};
- // String[] three= new String[] {"-3"};
- // String[] both = new String[] {"-1", "-2" };
- // String[] oneB = new String[] {"-1-"};
- // String[] bothB = new String[] {"-1-", "-2-" };
- // String[] onetwoB = new String[] {"-1", "-2-" };
- // String[] oneBtwo = new String[] {"-1-", "-2" };
- // String[] threeB = new String[] {"-1-", "-2-", "-3-"};
- // String[] athreeB = new String[] {"a", "-1-", "-2-", "-3-"};
- // String[] threeaB = new String[] {"-1-", "a", "-2-", "-3-"};
- //
- // checkOptionVariants(NONE, new String[][] { NONE });
- // checkOptionVariants(one, new String[][] { one });
- // checkOptionVariants(both, new String[][] { both });
- // checkOptionVariants(oneB, new String[][] { NONE, one });
- // checkOptionVariants(bothB, new String[][] { NONE, one, new String[] {"-2"}, both });
- // checkOptionVariants(onetwoB, new String[][] { one, new String[] {"-1", "-2"}});
- // checkOptionVariants(oneBtwo, new String[][] { two, new String[] {"-1", "-2"}});
- // checkOptionVariants(threeB, new String[][]
- // {
- // NONE,
- // one,
- // two,
- // new String[] {"-1", "-2"},
- // three,
- // new String[] {"-1", "-3"},
- // new String[] {"-2", "-3"},
- // new String[] {"-1", "-2", "-3"}
- // });
- // checkOptionVariants(athreeB, new String[][]
- // {
- // new String[] {"a"},
- // new String[] {"a", "-1"},
- // new String[] {"a", "-2"},
- // new String[] {"a", "-1", "-2"},
- // new String[] {"a", "-3"},
- // new String[] {"a", "-1", "-3"},
- // new String[] {"a", "-2", "-3"},
- // new String[] {"a", "-1", "-2", "-3"}
- // });
- // checkOptionVariants(threeaB, new String[][]
- // {
- // new String[] {"a"},
- // new String[] {"-1", "a"},
- // new String[] {"a", "-2"},
- // new String[] {"-1", "a", "-2"},
- // new String[] {"a", "-3"},
- // new String[] {"-1", "a", "-3"},
- // new String[] {"a", "-2", "-3"},
- // new String[] {"-1", "a", "-2", "-3"}
- // });
- // }
-
- // void checkOptionVariants(String[] options, String[][] expected) {
- // String[][] result = LangUtil.optionVariants(options);
- // if (expected.length != result.length) {
- // assertTrue("exp=" + expected.length + " actual=" + result.length, false);
- // }
- // for (int i = 0; i < expected.length; i++) {
- // assertEquals(""+i,
- // "" + Arrays.asList(expected[i]),
- // "" + Arrays.asList(result[i]));
- // }
- // }
-
- /** @see XMLWriterTest#testUnflattenList() */
- public void testCommaSplit() {
- checkCommaSplit("", new String[] { "" });
- checkCommaSplit("1", new String[] { "1" });
- checkCommaSplit(" 1 2 ", new String[] { "1 2" });
- checkCommaSplit(" 1 , 2 ", new String[] { "1", "2" });
- checkCommaSplit("1,2,3,4", new String[] { "1", "2", "3", "4" });
- }
-
- void checkCommaSplit(String input, String[] expected) {
- List actual = LangUtil.commaSplit(input);
- String a = "" + actual;
- String e = "" + Arrays.asList(expected);
- assertTrue(e + "==" + a, e.equals(a));
- }
-
- public void testElideEndingLines() {
- StringBuffer stackBuffer = LangUtil.stackToString(new RuntimeException(""), true);
- LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 10);
- String result = stackBuffer.toString();
-
- if (-1 == result.indexOf("(... ")) {
- // brittle - will fail under different top-level drivers
- String m = "when running under eclipse or Ant, expecting (... in trace: ";
- assertTrue(m + result, false);
- }
-
- stackBuffer = new StringBuffer(
- "java.lang.RuntimeException: unimplemented"
- + "\n at org.aspectj.ajdt.internal.core.builder.EclipseUnwovenClassFile.writeWovenBytes(EclipseUnwovenClassFile.java:59)"
- + "\n at org.aspectj.weaver.bcel.BcelWeaver.dump(BcelWeaver.java:271)"
- + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:233)"
- + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:198)"
- + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.weaveAndGenerateClassFiles(AjBuildanager.java:230)"
- + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:50)"
- + "\n at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:42)"
- + "\n at org.aspectj.testing.harness.bridge.CompilerRun.run(CompilerRun.java:222)"
- + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
- + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
- + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
- + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
- + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
- + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
- + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
- + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
- + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
- + "\n at org.aspectj.testing.run.Runner.run(Runner.java:114)"
- + "\n at org.aspectj.testing.run.Runner.run(Runner.java:105)"
- + "\n at org.aspectj.testing.run.Runner.runIterator(Runner.java:228)"
- + "\n at org.aspectj.testing.drivers.Harness.run(Harness.java:254)"
- + "\n at org.aspectj.testing.drivers.Harness.runMain(Harness.java:217)"
- + "\n at org.aspectj.testing.drivers.Harness.main(Harness.java:99)"
- + "\n at org.aspectj.testing.Harness.main(Harness.java:37)" + "\n clip me");
-
- LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 25);
- result = stackBuffer.toString();
- assertTrue(result, -1 != result.indexOf("(... "));
- assertTrue(result, -1 == result.indexOf("org.aspectj.testing"));
- }
-}
+++ /dev/null
-package org.aspectj.util;
-/* *******************************************************************
- * 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
- * ******************************************************************/
-
-
-// default package
-
-import junit.framework.*;
-import junit.framework.Test;
-
-public class UtilModuleTests extends TestCase {
-
- public static Test suite() {
- TestSuite suite = new TestSuite(UtilModuleTests.class.getName());
- suite.addTest(org.aspectj.util.UtilTests.suite());
- return suite;
- }
-
- public UtilModuleTests(String name) { super(name); }
-
-}
+++ /dev/null
-/* *******************************************************************
- * 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.util;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class UtilTests extends TestCase {
-
- public static Test suite() {
- TestSuite suite = new TestSuite(UtilTests.class.getName());
- // $JUnit-BEGIN$
- suite.addTestSuite(FileUtilTest.class);
- suite.addTestSuite(LangUtilTest.class);
- suite.addTestSuite(GenericSignatureParserTest.class);
- // $JUnit-END$
- return suite;
- }
-
- public UtilTests(String name) {
- super(name);
- }
-
-}