12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247 |
- /* *******************************************************************
- * Copyright (c) 1999-2000 Xerox Corporation.
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * Xerox/PARC initial implementation
- * ******************************************************************/
-
-
- package org.aspectj.testing.util;
-
- import org.aspectj.bridge.AbortException;
- import org.aspectj.bridge.IMessage;
-
- import java.io.File;
- import java.io.FileFilter;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Modifier;
- import java.security.AccessController;
- import java.security.PrivilegedActionException;
- import java.security.PrivilegedExceptionAction;
- import java.util.ArrayList;
- import java.util.BitSet;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Properties;
- import java.util.StringTokenizer;
-
-
- /**
- * misc lang utilities
- */
- public class LangUtil {
-
- /** Delimiter used by split(String) (and ArrayList.toString()?) */
- public static final String SPLIT_DELIM = ", ";
-
- /** prefix used by split(String) (and ArrayList.toString()?) */
- public static final String SPLIT_START = "[";
-
- /** suffix used by split(String) (and ArrayList.toString()?) */
- public static final String SPLIT_END = "]";
-
- /** system-dependent classpath separator */
- public static final String CLASSPATH_SEP;
-
- private static final String[] NONE = new String[0];
-
- /** bad: hard-wired unix, windows, mac path separators */
- private static final char[] SEPS = new char[] { '/', '\\', ':' };
-
- static {
- // XXX this has to be the wrong way to get system-dependent classpath separator
- String ps = ";";
- try {
- ps = System.getProperty("path.separator");
- if (null == ps) {
- ps = ";";
- String cp = System.getProperty("java.class.path");
- if (null != cp) {
- if (-1 != cp.indexOf(";")) {
- ps = ";";
- } else if (-1 != cp.indexOf(":")) {
- ps = ":";
- }
- // else warn?
- }
- }
- } catch (Throwable t) { // ignore
- } finally {
- CLASSPATH_SEP = ps;
- }
- }
-
- /**
- * @return input if any are empty or no target in input,
- * or input with escape prefixing all original target
- */
- public static String escape(String input, String target, String escape) {
- if (isEmpty(input) || isEmpty(target) || isEmpty(escape)) {
- return input;
- }
- StringBuffer sink = new StringBuffer();
- escape(input, target, escape, sink);
- return sink.toString();
- }
-
-
- /**
- * Append escaped input to sink.
- * Cheap form of arbitrary escaping does not escape the escape String
- * itself, but unflatten treats it as significant only before the target.
- * (so this fails with input that ends with target).
- */
- public static void escape(String input, String target, String escape, StringBuffer sink) {
- if ((null == sink) || isEmpty(input) || isEmpty(target) || isEmpty(escape)) {
- return;
- } else if (-1 == input.indexOf(target)) { // avoid StringTokenizer construction
- sink.append(input);
- return;
- }
- throw new Error("unimplemented");
- }
-
- /** flatten list per spec to sink */
- public static void flatten(List list, FlattenSpec spec, StringBuffer sink) {
- throwIaxIfNull(spec, "spec");
- final FlattenSpec s = spec;
- flatten(list, s.prefix, s.nullFlattened, s.escape, s.delim, s.suffix, sink);
- }
-
- /**
- * Flatten a List to String by first converting to String[]
- * (using toString() if the elements are not already String)
- * and calling flatten(String[]...).
- */
- public static void flatten(
- List list,
- String prefix,
- String nullFlattened,
- String escape,
- String delim,
- String suffix,
- StringBuffer sink) {
- throwIaxIfNull(list, "list");
- Object[] ra = list.toArray();
- String[] result;
- if (String.class == ra.getClass().getComponentType()) {
- result = (String[]) ra;
- } else {
- result = new String[ra.length];
- for (int i = 0; i < result.length; i++) {
- if (null != ra[i]) {
- result[i] = ra[i].toString();
- }
- }
- }
- flatten(result, prefix, nullFlattened, escape, delim, suffix, sink);
- }
-
-
-
-
- /** flatten String[] per spec to sink */
- public static void flatten(String[] input, FlattenSpec spec, StringBuffer sink) {
- throwIaxIfNull(spec, "spec");
- final FlattenSpec s = spec;
- flatten(input, s.prefix, s.nullFlattened, s.escape, s.delim,s.suffix, sink);
- }
-
-
-
-
- /**
- * Flatten a String[] to String by writing strings to sink,
- * prefixing with leader (if not null),
- * using nullRendering for null entries (skipped if null),
- * escaping any delim in entry by prefixing with escape (if not null),
- * separating entries with delim (if not null),
- * and suffixing with trailer (if not null).
- * Note that nullFlattened is not processed for internal delim,
- * and strings is not copied before processing.
- * @param strings the String[] input - not null
- * @param prefix the output starts with this if not null
- * @param nullFlattened the output of a null entry - entry is skipped (no delim) if null
- * @param escape any delim in an item will be prefixed by escape if not null
- * @param delim two items in the output will be separated by delim if not null
- * @param suffix the output ends with this if not null
- * @param sink the StringBuffer to use for output
- * @return null if sink is not null (results added to sink) or rendering otherwise
- */
- public static void flatten(
- String[] strings,
- String prefix,
- String nullFlattened,
- String escape,
- String delim,
- String suffix,
- StringBuffer sink) {
- throwIaxIfNull(strings, "strings");
- if (null == sink) {
- return;
- }
- final boolean haveDelim = (!isEmpty(delim));
- final boolean haveNullFlattened = (null != nullFlattened);
- final boolean escaping = (haveDelim && (null != escape));
- final int numStrings = (null == strings ? 0 : strings.length);
- if (null != prefix) {
- sink.append(prefix);
- }
- for (int i = 0; i < numStrings; i++) {
- String s = strings[i];
- if (null == s) {
- if (!haveNullFlattened) {
- continue;
- }
- if (haveDelim && (i > 0)) {
- sink.append(delim);
- }
- sink.append(nullFlattened);
- } else {
- if (haveDelim && (i > 0)) {
- sink.append(delim);
- }
-
- if (escaping) {
- escape(s, delim, escape, sink);
- } else {
- sink.append(s);
- }
- }
- }
- if (null != suffix) {
- sink.append(suffix);
- }
- }
-
- /**
- * Get indexes of any invalid entries in array.
- * @param ra the Object[] entries to check
- * (if null, this returns new int[] { -1 })
- * @param superType the Class, if any, to verify that
- * any entries are assignable.
- * @return null if all entries are non-null, assignable to superType
- * or comma-delimited error String, with components
- * <code>"[#] {null || not {superType}"</code>,
- * e.g., "[3] null, [5] not String"
- */
- public static String invalidComponents(Object[] ra, Class superType) {
- if (null == ra) {
- return "null input array";
- } else if (0 == ra.length) {
- return null;
- }
- StringBuffer result = new StringBuffer();
- final String cname = LangUtil.unqualifiedClassName(superType);
- int index = 0;
- for (int i = 0; i < ra.length; i++) {
- if (null == ra[i]) {
- result.append(", [" + i + "] null");
- } else if ((null != superType)
- && !superType.isAssignableFrom(ra[i].getClass())) {
- result.append(", [" + i + "] not " + cname);
- }
- }
- if (0 == result.length()) {
- return null;
- } else {
- return result.toString().substring(2);
- }
- }
-
- /** @return ((null == ra) || (0 == ra.length)) */
- public static boolean isEmpty(Object[] ra) {
- return ((null == ra) || (0 == ra.length));
- }
-
- /** @return ((null == s) || (0 == s.length())); */
- public static boolean isEmpty(String s) {
- return ((null == s) || (0 == s.length()));
- }
-
-
-
- /**
- * Throw IllegalArgumentException if any component in input array
- * is null or (if superType is not null) not assignable to superType.
- * The exception message takes the form
- * <code>{name} invalid entries: {invalidEntriesResult}</code>
- * @throws IllegalArgumentException if any components bad
- * @see #invalidComponents(Object[], Class)
- */
- public static final void throwIaxIfComponentsBad(
- final Object[] input,
- final String name,
- final Class superType) {
- String errs = invalidComponents(input, superType);
- if (null != errs) {
- String err = name + " invalid entries: " + errs;
- throw new IllegalArgumentException(err);
- }
- }
- /**
- * 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);
- }
- }
-
- /**
- * 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);
- }
- }
-
- public static ArrayList unflatten(String input, FlattenSpec spec) {
- throwIaxIfNull(spec, "spec");
- final FlattenSpec s = spec;
- return unflatten(input,s.prefix, s.nullFlattened, s.escape, s.delim, s.suffix, s.emptyUnflattened);
- }
-
- /**
- * Unflatten a String to String[] by separating elements at delim,
- * handling prefixes, suffixes, escapes, etc.
- * Any prefix or suffix is stripped from the input
- * (or, if not found, an IllegalArgumentException is thrown).
- * If delim is null or empty or input contains no delim,
- * then return new String[] {stripped input}.
- *
- * XXX fix comments
- * prefixing with leader (if not null),
- * using nullRendering for null entries (skipped if null),
- * escaping any delim in entry by prefixing with escape (if not null),
- * separating entries with delim (if not null),
- * and suffixing with trailer (if not null).
- * Note that nullRendering is not processed for internal delim,
- * and strings is not copied before processing.
- * @param strings the String[] input - not null
- * @param prefix the output starts with this if not null
- * @param nullRendering the output of a null entry - entry is skipped (no delim) if null
- * @param escape any delim in an item will be prefixed by escape if not null
- * @param delim two items in the output will be separated by delim if not null
- * @param suffix the output ends with this if not null
- * @param sink the StringBuffer to use for output
- * @return null if sink is not null (results added to sink) or rendering otherwise
- * @throws IllegalArgumentException if input is null
- * or if any prefix does not start the input
- * or if any suffix does not end the input
- */
- public static ArrayList unflatten(
- String input,
- String prefix,
- String nullFlattened,
- String escape,
- String delim,
- String suffix,
- String emptyUnflattened) {
- throwIaxIfNull(input, "input");
- final boolean haveDelim = (!isEmpty(delim));
- final boolean haveNullFlattened = (null != nullFlattened);
- final boolean escaping = (haveDelim && (null != escape));
- if (!isEmpty(prefix)) {
- if (input.startsWith(prefix)) {
- input = input.substring(prefix.length());
- } else {
- String s = "expecting \"" + prefix + "\" at start of " + input + "\"";
- throw new IllegalArgumentException(s);
- }
- }
- if (!isEmpty(suffix)) {
- if (input.endsWith(suffix)) {
- input = input.substring(0, input.length() - suffix.length());
- } else {
- String s = "expecting \"" + suffix + "\" at end of " + input + "\"";
- throw new IllegalArgumentException(s);
- }
- }
-
- final ArrayList result = new ArrayList();
- if (isEmpty(input)) {
- return result;
- }
- if ((!haveDelim) || (-1 == input.indexOf(delim))) {
- result.add(input);
- return result;
- }
-
- StringTokenizer st = new StringTokenizer(input, delim, true);
- StringBuffer cur = new StringBuffer();
- boolean lastEndedWithEscape = false;
- boolean lastWasDelim = false;
- while (st.hasMoreTokens()) {
- String token = st.nextToken();
- System.out.println("reading " + token);
- if (delim.equals(token)) {
- } else {
- result.add(token);
- }
- }
- return result;
- }
-
- /** combine two string arrays, removing null and duplicates
- * @return concatenation of both arrays, less null in either or dups in two
- * @see Util#combine(Object[], Object[])
- */
- public static String[] combine(String[] one, String[] two) {
- ArrayList twoList = new ArrayList();
- twoList.addAll(org.aspectj.util.LangUtil.arrayAsList(two));
- ArrayList result = new ArrayList();
- if (null != one) {
- for (int i = 0; i < one.length; i++) {
- if (null != one[i]) {
- twoList.remove(one[i]);
- result.add(one[i]);
- }
- }
- }
- for (Iterator iterator = twoList.iterator(); iterator.hasNext(); ) {
- String element = (String) iterator.next();
- if (null != element) {
- result.add(element);
- }
- }
- return (String[]) result.toArray(NONE);
- }
-
- public static Properties combine(Properties dest, Properties add, boolean respectExisting) { // XXX
- if (null == add) return dest;
- if (null == dest) return add;
- for (Iterator iterator = add.keySet().iterator(); iterator.hasNext(); ) {
- String key = (String) iterator.next();
- if (null == key) {
- continue;
- }
- String value = add.getProperty(key);
- if (null == value) {
- continue;
- }
- if (! respectExisting || (null == dest.getProperty(key))) {
- dest.setProperty(key, value);
- }
- }
- return dest;
- }
-
- public static List arrayAsList(Object[] ra) {
- return org.aspectj.util.LangUtil.arrayAsList(ra);
- }
-
- /**
- * return the fully-qualified class names
- * inferred from the file names in dir
- * assuming dir is the root of the source tree
- * and class files end with ".class".
- * @throws Error if dir is not properly named as prefix
- * of class files found in dir.
- */
- public static String[] classesIn(File dir) {
- boolean alwaysTrue = true;
- FileFilter filter = ValidFileFilter.CLASS_FILE;
- CollectorFileFilter collector = new CollectorFileFilter(filter, alwaysTrue);
- FileUtil.descendFileTree(dir, collector);
- List list = collector.getFiles();
- String[] result = new String[list.size()];
- Iterator it = list.iterator();
- String dirPrefix = dir.getPath();
- for (int i = 0; i < result.length; i++) {
- if (!it.hasNext()) {
- throw new Error("unexpected end of list at " + i);
- }
- result[i] = fileToClassname((File) it.next(), dirPrefix);
- }
- return result;
- }
-
- /**
- * Convert String[] to String by using conventions for
- * split. Will ignore any entries containing SPLIT_DELIM
- * (and write as such to errs if not null).
- * @param input the String[] to convert
- * @param errs the StringBuffer for error messages (if any)
- */
- public static String unsplit(String[] input, StringBuffer errs) {
- StringBuffer sb = new StringBuffer();
- sb.append(SPLIT_START);
- for (int i = 0; i < input.length; i++) {
- if (-1 != input[i].indexOf(SPLIT_DELIM)) {
- if (null != errs) {
- errs.append("\nLangUtil.unsplit(..) - item " + i + ": \"" + input[i]
- + " contains \"" + SPLIT_DELIM + "\"");
- }
- } else {
- sb.append(input[i]);
- if (1+i < input.length) {
- sb.append(SPLIT_DELIM);
- }
- }
- }
- sb.append(SPLIT_END);
- return sb.toString();
-
- }
-
- /**
- * Split input into substrings on the assumption that it is
- * either only one string or it was generated using List.toString(),
- * with tokens
- * <pre>SPLIT_START {string} { SPLIT_DELIM {string}} SPLIT_END<pre>
- * (e.g., <code>"[one, two, three]"</code>).
- */
- public static String[] split(String s) {
- if (null == s) {
- return null;
- }
- if ((!s.startsWith(SPLIT_START)) || (!s.endsWith(SPLIT_END))) {
- return new String[] { s };
- }
- s = s.substring(SPLIT_START.length(),s.length()-SPLIT_END.length());
- final int LEN = s.length();
- int start = 0;
- final ArrayList result = new ArrayList();
- final String DELIM = ", ";
- int loc = s.indexOf(SPLIT_DELIM, start);
- while ((start < LEN) && (-1 != loc)) {
- result.add(s.substring(start, loc));
- start = DELIM.length() + loc;
- loc = s.indexOf(SPLIT_DELIM, start);
- }
- result.add(s.substring(start));
- return (String[]) result.toArray(new String[0]);
- }
-
- public static String[] strip(String[] src, String[] toStrip) {
- if (null == toStrip) {
- return strip(src, NONE);
- } else if (null == src) {
- return strip(NONE, toStrip);
- }
- List slist = org.aspectj.util.LangUtil.arrayAsList(src);
- List tlist = org.aspectj.util.LangUtil.arrayAsList(toStrip);
- slist.removeAll(tlist);
- return (String[]) slist.toArray(NONE);
- }
-
- /**
- * Load all classes specified by args, logging success to out
- * and fail to err.
- */
- public static void loadClasses(String[] args, StringBuffer out,
- StringBuffer err) {
- if (null != args) {
- for (int i = 0; i < args.length; i++) {
- try {
- Class c = Class.forName(args[i]);
- if (null != out) {
- out.append("\n");
- out.append(args[i]);
- out.append(": ");
- out.append(c.getName());
- }
- } catch (Throwable t) {
- if (null != err) {
- err.append("\n");
- FileUtil.render(t, err);
- }
- }
- }
-
- }
- }
-
- private static String fileToClassname(File f, String prefix) {
- // this can safely assume file exists, starts at base, ends with .class
- // this WILL FAIL if full path with drive letter on windows
- String path = f.getPath();
- if (!path.startsWith(prefix)) {
- String err = "!\"" + path + "\".startsWith(\"" + prefix + "\")";
- throw new IllegalArgumentException(err);
- }
- int length = path.length() - ".class".length();
- path = path.substring(prefix.length()+1, length);
- for (int i = 0; i < SEPS.length; i++) {
- path = path.replace(SEPS[i], '.');
- }
- return path;
- }
-
- public static void main (String[] args) { // todo remove as testing
- StringBuffer err = new StringBuffer();
- StringBuffer out = new StringBuffer();
- for (int i = 0; i < args.length; i++) {
- String[] names = classesIn(new File(args[i]));
- System.err.println(args[i] + " -> " + render(names));
- loadClasses(names, out, err);
- }
- if (0 < err.length()) {
- System.err.println(err.toString());
- }
- if (0 < out.length()) {
- System.out.println(out.toString());
- }
- }
-
- public static String render (String[] args) { // todo move as testing
- if ((null == args) || (1 > args.length)) {
- return "[]";
- }
- boolean longFormat = (args.length < 10);
- String sep = (longFormat ? ", " : "\n\t");
- StringBuffer sb = new StringBuffer();
- if (!longFormat) sb.append("[");
- for (int i = 0; i < args.length; i++) {
- if (0 < i) sb.append(sep);
- sb.append(args[i]);
- }
- sb.append(longFormat ? "\n" : "]");
- return sb.toString();
- }
-
-
- /**
- * @param thrown the Throwable to render
- */
- public static String debugStr(Throwable thrown) {
- if (null == thrown) {
- return "((Throwable) null)";
- } else if (thrown instanceof InvocationTargetException) {
- return debugStr(((InvocationTargetException)thrown).getTargetException());
- } else if (thrown instanceof AbortException) {
- IMessage m = ((AbortException) thrown).getIMessage();
- if (null != m) {
- return "" + m;
- }
- }
- StringWriter buf = new StringWriter();
- PrintWriter writer = new PrintWriter(buf);
- writer.println(thrown.getMessage());
- thrown.printStackTrace(writer);
- try { buf.close(); }
- catch (IOException ioe) {}
- return buf.toString();
- }
-
- /**
- * <code>debugStr(o, false);</code>
- * @param source the Object to render
- */
- public static String debugStr(Object o) {
- return debugStr(o, false);
- }
-
- /**
- * Render standard debug string for an object in normal, default form.
- * @param source the Object to render
- * @param recurse if true, then recurse on all non-primitives unless rendered
- */
- public static String debugStr(Object o, boolean recurse) {
- if (null == o) {
- return "null";
- } else if (recurse) {
- ArrayList rendering = new ArrayList();
- rendering.add(o);
- return debugStr(o, rendering);
- } else {
- Class c = o.getClass();
- Field[] fields = c.getDeclaredFields();
- Object[] values = new Object[fields.length];
- String[] names = new String[fields.length];
- for (int i = 0; i < fields.length; i++) {
- Field field = fields[i];
- names[i] = field.getName();
- try {
- values[i] = field.get(o);
- if (field.getType().isArray()) {
- List list = org.aspectj.util.LangUtil.arrayAsList((Object[]) values[i]);
- values[i] = list.toString();
- }
- } catch (IllegalAccessException e) {
- values[i] = "<IllegalAccessException>";
- }
- }
- return debugStr(c, names, values);
- }
- }
-
- /**
- * recursive variant avoids cycles.
- * o added to rendering before call.
- */
- private static String debugStr(Object o, ArrayList rendering) {
- if (null == o) {
- return "null";
- } else if (!rendering.contains(o)) {
- throw new Error("o not in rendering");
- }
- Class c = o.getClass();
- if (c.isArray()) {
- Object[] ra = (Object[]) o;
- StringBuffer sb = new StringBuffer();
- sb.append("[");
- for (int i = 0; i < ra.length; i++) {
- if (i > 0) {
- sb.append(", ");
- }
- rendering.add(ra[i]);
- sb.append(debugStr(ra[i], rendering));
- }
- sb.append("]");
- return sb.toString();
- }
- Field[] fields = nonStaticFields(c.getFields());
- Object[] values = new Object[fields.length];
- String[] names = new String[fields.length];
- for (int i = 0; i < fields.length; i++) {
- Field field = fields[i];
- names[i] = field.getName();
- // collapse to String
- Object value = privilegedGetField(field,o);
- if (null == value) {
- values[i] = "null";
- } else if (rendering.contains(value)) {
- values[i] = "<recursion>";
- } else {
- rendering.add(value);
- values[i] = debugStr(value, rendering);
- }
- }
- return debugStr(c, names, values);
- }
-
- /** incomplete - need protection domain */
- private static Object privilegedGetField(final Field field, final Object o) {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction() {
- public Object run() {
- try {
- return field.get(o);
- } catch(IllegalAccessException e) {
- return "<IllegalAccessException>";
- }
- }
- });
- } catch (PrivilegedActionException e) {
- return "<IllegalAccessException>";
- }
- }
-
- private static Field[] nonStaticFields(Field[] fields) {
- if (null == fields) {
- return new Field[0];
- }
- int to = 0;
- int from = 0;
- while (from < fields.length) {
- if (!Modifier.isStatic(fields[from].getModifiers())) {
- if (to != from) {
- fields[to] = fields[from];
- }
- to++;
- }
- from++;
- }
- if (to < from) {
- Field[] result = new Field[to];
- if (to > 0) {
- System.arraycopy(fields, 0, result, 0, to);
- }
- fields = result;
- }
- return fields;
- }
-
- /** <code> debugStr(source, names, items, null, null, null, null)<code> */
- public static String debugStr(Class source, String[] names, Object[] items) {
- return debugStr(source, null, names, null, items, null, null);
- }
-
- /**
- * Render standard debug string for an object.
- * This is the normal form and an example with the default values:<pre>
- * {className}{prefix}{{name}{infix}{value}{delimiter}}..{suffix}
- * Structure[head=root, tail=leaf]</pre>
- * Passing null for the formatting entries provokes the default values,
- * so to print nothing, you should pass "". Default values:<pre>
- * prefix: "[" SPLIT_START
- * infix: "="
- * delimiter: ", " SPLIT_DELIM
- * suffix: "]" SPLIT_END
- * @param source the Class prefix to render unqualified - omitted if null
- * @param names the String[] (field) names of the items - omitted if null
- * @param items the Object[] (field) values
- * @param prefix the String to separate classname and start of name/values
- * @param delimiter the String to separate name/value instances
- * @param infix the String to separate name and value
- * used only if both name and value exist
- * @param suffix the String to delimit the end of the name/value instances
- * used only if classname exists
- */
- public static String debugStr(Class source, String prefix, String[] names,
- String infix, Object[] items, String delimiter, String suffix) {
-
- if (null == delimiter) {
- delimiter = SPLIT_DELIM;
- }
- if (null == prefix) {
- prefix = SPLIT_START;
- }
- if (null == infix) {
- infix = "=";
- }
- if (null == suffix) {
- suffix = SPLIT_END;
- }
- StringBuffer sb = new StringBuffer();
- if (null != source) {
- sb.append(org.aspectj.util.LangUtil.unqualifiedClassName(source));
- }
- sb.append(prefix);
- if (null == names) {
- names = NONE;
- }
- if (null == items) {
- items = NONE;
- }
- final int MAX
- = (names.length > items.length ? names.length : items.length);
- for (int i = 0; i < MAX; i++) {
- if (i > 0) {
- sb.append(delimiter);
- }
- if (i < names.length) {
- sb.append(names[i]);
- }
- if (i < items.length) {
- if (i < names.length) {
- sb.append(infix);
- }
- sb.append(items[i] + "");
- }
- }
- sb.append(suffix);
- return sb.toString();
- }
-
- /**
- * @return a String with the unqualified class name of the object (or "null")
- */
- public static String unqualifiedClassName(Object o) {
- return unqualifiedClassName(null == o ? null : o.getClass());
- }
-
- /**
- * @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;
- }
-
- /**
- * Calculate exact diffs and report missing and extra items.
- * This assumes the input List are not modified concurrently.
- * @param expectedListIn the List of expected results - treated as empty if null
- * @param actualListIn the List of actual results - treated as empty if null
- * @param extraListOut the List for any actual results not expected - ignored if null
- * @param missingListOut the List for any expected results not found - ignored if null
- * */
- public static void makeDiffs(
- List expectedListIn,
- List actualListIn,
- List missingListOut,
- List extraListOut) {
- if ((null == missingListOut) && (null == extraListOut)) {
- return;
- }
- if (null == expectedListIn) {
- expectedListIn = Collections.EMPTY_LIST;
- }
- if (null == actualListIn) {
- actualListIn = Collections.EMPTY_LIST;
- }
- if ((0 == actualListIn.size()) && (0 == expectedListIn.size()) ) {
- return;
- }
- BitSet actualExpected = new BitSet();
- for (int i = 0; i < expectedListIn.size(); i++) {
- Object expect = expectedListIn.get(i);
- int loc = actualListIn.indexOf(expect);
- if (-1 == loc) {
- if (null != missingListOut) {
- missingListOut.add(expect);
- }
- } else {
- actualExpected.set(loc);
- }
- }
- if (null != extraListOut) {
- for (int i = 0; i < actualListIn.size(); i++) {
- if (!actualExpected.get(i)) {
- extraListOut.add(actualListIn.get(i));
- }
- }
- }
- }
- // XXX unit test for makeSoftDiffs
- /**
- * Calculate potentially "soft" diffs using
- * Comparator.compare(expected, actual).
- * This shallow-copies and sorts the input Lists.
- * @param expectedListIn the List of expected results - treated as empty if null
- * @param actualListIn the List of actual results - treated as empty if null
- * @param extraListOut the List for any actual results not expected - ignored if null
- * @param missingListOut the List for any expected results not found - ignored if null
- * @param comparator the Comparator for comparisons - not null
- * @throws IllegalArgumentException if comp is null
- */
- public static void makeSoftDiffs( // XXX no intersect or union on collections???
- List expectedListIn,
- List actualListIn,
- List missingListOut,
- List extraListOut,
- Comparator comparator) {
- if ((null == missingListOut) && (null == extraListOut)) {
- return;
- }
- if (null == comparator) {
- throw new IllegalArgumentException("null comparator");
- }
- if (null == expectedListIn) {
- expectedListIn = Collections.EMPTY_LIST;
- }
- if (null == actualListIn) {
- actualListIn = Collections.EMPTY_LIST;
- }
- if ((0 == actualListIn.size()) && (0 == expectedListIn.size()) ) {
- return;
- }
-
- ArrayList expected = new ArrayList();
- expected.addAll(expectedListIn);
- Collections.sort(expected, comparator);
- Iterator expectedIter = expected.iterator();
- Object exp = null;
-
- ArrayList actual = new ArrayList();
- actual.addAll(actualListIn);
- Collections.sort(actual, comparator);
- Iterator actualIter = actual.iterator();
- Object act = null;
-
- while (((null != act) || actualIter.hasNext())
- && ((null != exp) || expectedIter.hasNext())) {
- if (null == act) {
- act = actualIter.next();
- }
- if (null == exp) {
- exp = expectedIter.next();
- }
- int diff = comparator.compare(exp, act);
- if (0 > diff) { // exp < act
- if (null != missingListOut) {
- missingListOut.add(exp);
- exp = null;
- }
- } else if (0 < diff) { // exp > act
- if (null != extraListOut) {
- extraListOut.add(act);
- act = null;
- }
- } else { // got match of actual to expected
- // absorb all actual matching expected (duplicates)
- while ((0 == diff) && actualIter.hasNext()) {
- act = actualIter.next();
- diff = comparator.compare(exp, act);
- }
- if (0 == diff) {
- act = null;
- }
- exp = null;
- }
- }
- if (null != missingListOut) {
- if (null != exp) {
- missingListOut.add(exp);
- }
- while (expectedIter.hasNext()) {
- missingListOut.add(expectedIter.next());
- }
- }
- if (null != extraListOut) {
- if (null != act) {
- extraListOut.add(act);
- }
- while (actualIter.hasNext()) {
- extraListOut.add(actualIter.next());
- }
- }
- }
- public static class FlattenSpec {
- /**
- * This tells unflatten(..) to throw IllegalArgumentException
- * if it finds two contiguous delimiters.
- */
- public static final String UNFLATTEN_EMPTY_ERROR
- = "empty items not permitted when unflattening";
- /**
- * This tells unflatten(..) to skip empty items when unflattening
- * (since null means "use null")
- */
- public static final String UNFLATTEN_EMPTY_AS_NULL
- = "unflatten empty items as null";
-
- /**
- * This tells unflatten(..) to skip empty items when unflattening
- * (since null means "use null")
- */
- public static final String SKIP_EMPTY_IN_UNFLATTEN
- = "skip empty items when unflattening";
-
- /**
- * For Ant-style attributes: "item,item" (with escaped commas).
- * There is no way when unflattening to distinguish
- * values which were empty from those which were null,
- * so all are unflattened as empty.
- */
- public static final FlattenSpec COMMA
- = new FlattenSpec(null, "", "\\", ",", null, "") {
- public String toString() { return "FlattenSpec.COMMA"; }
- };
-
- /** this attempts to mimic ((List)l).toString() */
- public static final FlattenSpec LIST
- = new FlattenSpec("[", "", null, ", ", "]", UNFLATTEN_EMPTY_ERROR) {
- public String toString() { return "FlattenSpec.LIST"; }
- };
-
- /** how toString renders null values */
- public static final String NULL = "<null>";
- private static String r(String s) {
- return (null == s ? NULL : s);
- }
-
- public final String prefix;
- public final String nullFlattened;
- public final String escape;
- public final String delim;
- public final String suffix;
- public final String emptyUnflattened;
- private transient String toString;
-
- public FlattenSpec(
- String prefix,
- String nullRendering,
- String escape,
- String delim,
- String suffix,
- String emptyUnflattened) {
- this.prefix = prefix;
- this.nullFlattened = nullRendering;
- this.escape = escape;
- this.delim = delim;
- this.suffix = suffix;
- this.emptyUnflattened = emptyUnflattened;
- throwIaxIfNull(emptyUnflattened, "use UNFLATTEN_EMPTY_AS_NULL");
- }
-
- public String toString() {
- if (null == toString) {
- toString = "FlattenSpec("
- + "prefix=" + r(prefix)
- + ", nullRendering=" + r(nullFlattened)
- + ", escape=" + r(escape)
- + ", delim=" + r(delim)
- + ", suffix=" + r(suffix)
- + ", emptyUnflattened=" + r(emptyUnflattened)
- + ")";
- }
- return toString;
- }
- }
- } // class LangUtil
-
- // --------- java runs using Ant
- // /**
- // * Run a Java command separately.
- // * @param className the fully-qualified String name of the class
- // * with the main method to run
- // * @param classpathFiles the File to put on the classpath
- // * @param args to the main method of the class
- // * @param outSink the PrintStream for the output stream - may be null
- // */
- // public static void oldexecuteJava(
- // String className,
- // File[] classpathFiles,
- // String[] args,
- // PrintStream outSink) {
- // Project project = new Project();
- // project.setName("LangUtil.executeJava(" + className + ")");
- // Path classpath = new Path(project, classpathFiles[0].getAbsolutePath());
- // for (int i = 1; i < classpathFiles.length; i++) {
- // classpath.addExisting(new Path(project, classpathFiles[i].getAbsolutePath()));
- // }
- //
- // Commandline cmds = new Commandline();
- // cmds.addArguments(new String[] {className});
- // cmds.addArguments(args);
- //
- // ExecuteJava runner = new ExecuteJava();
- // runner.setClasspath(classpath);
- // runner.setJavaCommand(cmds);
- // if (null != outSink) {
- // runner.setOutput(outSink); // XXX todo
- // }
- // runner.execute(project);
- // }
-
- // public static void executeJava(
- // String className,
- // File dir,
- // File[] classpathFiles,
- // String[] args,
- // PrintStream outSink) {
- // StringBuffer sb = new StringBuffer();
- //
- // sb.append("c:/apps/jdk1.3.1/bin/java.exe -classpath \"");
- // for (int i = 0; i < classpathFiles.length; i++) {
- // if (i < 0) {
- // sb.append(";");
- // }
- // sb.append(classpathFiles[i].getAbsolutePath());
- // }
- // sb.append("\" -verbose " + className);
- // for (int i = 0; i < args.length; i++) {
- // sb.append(" " + args[i]);
- // }
- // Exec exec = new Exec();
- // Project project = new Project();
- // project.setProperty("ant.home", "c:/home/wes/aj/aspectj/modules/lib/ant");
- // System.setProperty("ant.home", "c:/home/wes/aj/aspectj/modules/lib/ant");
- // exec.setProject(new Project());
- // exec.setCommand(sb.toString());
- // exec.setDir(dir.getAbsolutePath());
- // exec.execute();
- // }
- // public static void execJavaProcess(
- // String className,
- // File dir,
- // File[] classpathFiles,
- // String[] args,
- // PrintStream outSink) throws Throwable {
- // StringBuffer sb = new StringBuffer();
- //
- // sb.append("c:\\apps\\jdk1.3.1\\bin\\java.exe -classpath \"");
- // for (int i = 0; i < classpathFiles.length; i++) {
- // if (i > 0) {
- // sb.append(";");
- // }
- // sb.append(classpathFiles[i].getAbsolutePath());
- // }
- // sb.append("\" -verbose " + className);
- // for (int i = 0; i < args.length; i++) {
- // sb.append(" " + args[i]);
- // }
- // String command = sb.toString();
- // System.err.println("launching process: " + command);
- // Process process = Runtime.getRuntime().exec(command);
- // // huh? err/out
- // InputStream errStream = null;
- // InputStream outStream = null;
- // Throwable toThrow = null;
- // int result = -1;
- // try {
- // System.err.println("waiting for process: " + command);
- // errStream = null; // process.getErrorStream();
- // outStream = null; // process.getInputStream(); // misnamed - out
- // result = process.waitFor();
- // System.err.println("Done waiting for process: " + command);
- // process.destroy();
- // } catch (Throwable t) {
- // toThrow = t;
- // } finally {
- // if (null != outStream) {
- // FileUtil.copy(outStream, System.out, false);
- // try { outStream.close(); }
- // catch (IOException e) {}
- // }
- // if (null != errStream) {
- // FileUtil.copy(errStream, System.err, false);
- // try { errStream.close(); }
- // catch (IOException e) {}
- // }
- // }
- // if (null != toThrow) {
- // throw toThrow;
- // }
- // }
- // try {
- // // show the command
- // log(command, Project.MSG_VERBOSE);
- //
- // // exec command on system runtime
- // Process proc = Runtime.getRuntime().exec(command);
- //
- // if (out != null) {
- // fos = new PrintWriter(new FileWriter(out));
- // log("Output redirected to " + out, Project.MSG_VERBOSE);
- // }
- //
- // // copy input and error to the output stream
- // StreamPumper inputPumper =
- // new StreamPumper(proc.getInputStream(), Project.MSG_INFO);
- // StreamPumper errorPumper =
- // new StreamPumper(proc.getErrorStream(), Project.MSG_WARN);
- //
- // // starts pumping away the generated output/error
- // inputPumper.start();
- // errorPumper.start();
- //
- // // Wait for everything to finish
- // proc.waitFor();
- // inputPumper.join();
- // errorPumper.join();
- // proc.destroy();
- //
- // // close the output file if required
- // logFlush();
- //
- // // check its exit value
- // err = proc.exitValue();
- // if (err != 0) {
- // if (failOnError) {
- // throw new BuildException("Exec returned: " + err, getLocation());
- // } else {
- // log("Result: " + err, Project.MSG_ERR);
- // }
- // }
- // } catch (IOException ioe) {
- // throw new BuildException("Error exec: " + command, ioe, getLocation());
- // } catch (InterruptedException ex) {}
- //
-
|