@@ -18,23 +18,23 @@ import java.io.PrintWriter; | |||
import java.util.ArrayList; | |||
/** | |||
* Signal that a process was aborted before completion. | |||
* This may contain a structured IMessage which indicates | |||
* why the process was aborted (e.g., the underlying exception). | |||
* For processes using try/catch to complete a method abruptly | |||
* but complete the process normally (e.g., a test failure | |||
* causes the test to abort but the reporting and testing continues | |||
* normally), use the static methods to borrow and return a "porter" | |||
* to avoid the expense of constructing a stack trace each time. | |||
* A porter stack trace is invalid, and it should only be used | |||
* to convey a message. E.g., to print the stack of the | |||
* AbortException and any contained message: | |||
* <pre>catch (AbortException ae) { | |||
* Signal that a process was aborted before completion. This may contain a structured IMessage which indicates why the process was | |||
* aborted (e.g., the underlying exception). For processes using try/catch to complete a method abruptly but complete the process | |||
* normally (e.g., a test failure causes the test to abort but the reporting and testing continues normally), use the static methods | |||
* to borrow and return a "porter" to avoid the expense of constructing a stack trace each time. A porter stack trace is invalid, | |||
* and it should only be used to convey a message. E.g., to print the stack of the AbortException and any contained message: | |||
* | |||
* <pre> | |||
* catch (AbortException ae) { | |||
* IMessage m = ae.getMessage(); | |||
* if (!ae.isPorter()) ae.printStackTrace(System.err); | |||
* Throwable thrown = ae.getThrown(); | |||
* if (null != thrown) thrown.printStackTrace(System.err); | |||
* }</pre> | |||
* } | |||
* </pre> | |||
* | |||
* @author PARC | |||
* @author Andy Clement | |||
*/ | |||
public class AbortException extends RuntimeException { // XXX move porters out, handle proxy better | |||
@@ -42,189 +42,185 @@ public class AbortException extends RuntimeException { // XXX move porters out, | |||
private boolean isSilent = false; | |||
/** used when message text is null */ | |||
public static final String NO_MESSAGE_TEXT | |||
= "AbortException (no message)"; | |||
private static final ArrayList porters = new ArrayList(); | |||
/** | |||
* Get a porter exception from the pool. | |||
* Porter exceptions do <b>not</b> have valid stack traces. | |||
* They are used only to avoid generating stack traces when | |||
* using throw/catch to abruptly complete but continue. | |||
*/ | |||
public static AbortException borrowPorter(IMessage message) { | |||
AbortException result; | |||
synchronized(porters) { | |||
if (porters.size() > 0) { | |||
result = (AbortException) porters.get(0); | |||
} else { | |||
result = new AbortException(); | |||
result.setIsSilent(false); | |||
} | |||
} | |||
result.setIMessage(message); | |||
result.isPorter = true; | |||
return result; | |||
} | |||
/** | |||
* Return (or add) a porter exception to the pool. | |||
*/ | |||
public static void returnPorter(AbortException porter) { | |||
synchronized(porters) { | |||
if (porters.contains(porter)) { | |||
throw new IllegalStateException("already have " + porter); | |||
} else { | |||
porters.add(porter); | |||
} | |||
} | |||
} | |||
/** @return NO_MESSAGE_TEXT or message.getMessage() if not null */ | |||
private static String extractMessage(IMessage message) { | |||
if (null == message) { | |||
return NO_MESSAGE_TEXT; | |||
} else { | |||
String m = message.getMessage(); | |||
if (null == m) { | |||
return NO_MESSAGE_TEXT; | |||
} else { | |||
return m; | |||
} | |||
} | |||
} | |||
/** structured message abort */ | |||
protected IMessage message; | |||
/** true if this is a porter exception - only used to hold message */ | |||
protected boolean isPorter; | |||
/** abort with default String message */ | |||
public AbortException() { | |||
this("ABORT"); | |||
isSilent = true; | |||
} | |||
/** abort with message */ | |||
public AbortException(String s) { | |||
super(null != s ? s : NO_MESSAGE_TEXT); | |||
this.message = null; | |||
} | |||
/** abort with structured message */ | |||
public AbortException(IMessage message) { | |||
super(extractMessage(message)); | |||
this.message = message; | |||
} | |||
/** @return IMessage structured message, if set */ | |||
public IMessage getIMessage() { | |||
return message; | |||
} | |||
/** | |||
* The stack trace of a porter is invalid; it is only used | |||
* to carry a message (which may itself have a wrapped exception). | |||
* @return true if this exception is only to carry exception | |||
*/ | |||
public boolean isPorter() { | |||
return isPorter; | |||
} | |||
/** @return Throwable at bottom of IMessage chain, if any */ | |||
public Throwable getThrown() { | |||
Throwable result = null; | |||
IMessage m = getIMessage(); | |||
if (null != m) { | |||
result = m.getThrown(); | |||
if (result instanceof AbortException) { | |||
return ((AbortException) result).getThrown(); | |||
} | |||
} | |||
return result; | |||
} | |||
private void setIMessage(IMessage message) { | |||
this.message = message; | |||
} | |||
// ----------- proxy attempts | |||
/** | |||
* Get message for this AbortException, | |||
* either associated explicitly as message | |||
* or implicitly as IMessage message or | |||
* its thrown message. | |||
/** used when message text is null */ | |||
public static final String NO_MESSAGE_TEXT = "AbortException (no message)"; | |||
private static final ArrayList<AbortException> porters = new ArrayList<AbortException>(); | |||
/** | |||
* Get a porter exception from the pool. Porter exceptions do <b>not</b> have valid stack traces. They are used only to avoid | |||
* generating stack traces when using throw/catch to abruptly complete but continue. | |||
*/ | |||
public static AbortException borrowPorter(IMessage message) { | |||
AbortException result; | |||
synchronized (porters) { | |||
if (porters.size() > 0) { | |||
result = porters.get(0); | |||
} else { | |||
result = new AbortException(); | |||
result.setIsSilent(false); | |||
} | |||
} | |||
result.setIMessage(message); | |||
result.isPorter = true; | |||
return result; | |||
} | |||
/** | |||
* Return (or add) a porter exception to the pool. | |||
*/ | |||
public static void returnPorter(AbortException porter) { | |||
synchronized (porters) { | |||
if (porters.contains(porter)) { | |||
throw new IllegalStateException("already have " + porter); | |||
} else { | |||
porters.add(porter); | |||
} | |||
} | |||
} | |||
/** @return NO_MESSAGE_TEXT or message.getMessage() if not null */ | |||
private static String extractMessage(IMessage message) { | |||
if (null == message) { | |||
return NO_MESSAGE_TEXT; | |||
} else { | |||
String m = message.getMessage(); | |||
if (null == m) { | |||
return NO_MESSAGE_TEXT; | |||
} else { | |||
return m; | |||
} | |||
} | |||
} | |||
/** structured message abort */ | |||
protected IMessage message; | |||
/** true if this is a porter exception - only used to hold message */ | |||
protected boolean isPorter; | |||
/** abort with default String message */ | |||
public AbortException() { | |||
this("ABORT"); | |||
isSilent = true; | |||
} | |||
/** abort with message */ | |||
public AbortException(String s) { | |||
super(null != s ? s : NO_MESSAGE_TEXT); | |||
this.message = null; | |||
} | |||
/** abort with structured message */ | |||
public AbortException(IMessage message) { | |||
super(extractMessage(message)); | |||
this.message = message; | |||
} | |||
/** @return IMessage structured message, if set */ | |||
public IMessage getIMessage() { | |||
return message; | |||
} | |||
/** | |||
* The stack trace of a porter is invalid; it is only used to carry a message (which may itself have a wrapped exception). | |||
* | |||
* @return true if this exception is only to carry exception | |||
*/ | |||
public boolean isPorter() { | |||
return isPorter; | |||
} | |||
/** @return Throwable at bottom of IMessage chain, if any */ | |||
public Throwable getThrown() { | |||
Throwable result = null; | |||
IMessage m = getIMessage(); | |||
if (null != m) { | |||
result = m.getThrown(); | |||
if (result instanceof AbortException) { | |||
return ((AbortException) result).getThrown(); | |||
} | |||
} | |||
return result; | |||
} | |||
private void setIMessage(IMessage message) { | |||
this.message = message; | |||
} | |||
// ----------- proxy attempts | |||
/** | |||
* Get message for this AbortException, either associated explicitly as message or implicitly as IMessage message or its thrown | |||
* message. | |||
* | |||
* @see java.lang.Throwable#getMessage() | |||
*/ | |||
public String getMessage() { | |||
String message = super.getMessage(); | |||
if ((null == message) || (NO_MESSAGE_TEXT == message)) { | |||
IMessage m = getIMessage(); | |||
if (null != m) { | |||
message = m.getMessage(); | |||
if (null == message) { | |||
Throwable thrown = m.getThrown(); | |||
if (null != thrown) { | |||
message = thrown.getMessage(); | |||
} | |||
} | |||
} | |||
if (null == message) { | |||
message = NO_MESSAGE_TEXT; // better than nothing | |||
} | |||
} | |||
return message; | |||
} | |||
/** | |||
String message = super.getMessage(); | |||
if ((null == message) || (NO_MESSAGE_TEXT == message)) { | |||
IMessage m = getIMessage(); | |||
if (null != m) { | |||
message = m.getMessage(); | |||
if (null == message) { | |||
Throwable thrown = m.getThrown(); | |||
if (null != thrown) { | |||
message = thrown.getMessage(); | |||
} | |||
} | |||
} | |||
if (null == message) { | |||
message = NO_MESSAGE_TEXT; // better than nothing | |||
} | |||
} | |||
return message; | |||
} | |||
/** | |||
* @see java.lang.Throwable#printStackTrace() | |||
*/ | |||
public void printStackTrace() { | |||
printStackTrace(System.out); | |||
printStackTrace(System.out); | |||
} | |||
/** | |||
* Print the stack trace of any enclosed thrown | |||
* or this otherwise. | |||
/** | |||
* Print the stack trace of any enclosed thrown or this otherwise. | |||
* | |||
* @see java.lang.Throwable#printStackTrace(PrintStream) | |||
*/ | |||
public void printStackTrace(PrintStream s) { | |||
IMessage m = getIMessage(); | |||
Throwable thrown = (null == m? null : m.getThrown()); | |||
if (!isPorter() || (null == thrown)) { | |||
s.println("Message: " + m); | |||
super.printStackTrace(s); | |||
} else { | |||
thrown.printStackTrace(s); | |||
} | |||
} | |||
/** | |||
* Print the stack trace of any enclosed thrown | |||
* or this otherwise. | |||
* @see java.lang.Throwable#printStackTrace(PrintWriter) | |||
*/ | |||
public void printStackTrace(PrintWriter s) { | |||
IMessage m = getIMessage(); | |||
Throwable thrown = (null == m? null : m.getThrown()); | |||
if (null == thrown) { // Always print | |||
if (isPorter()) { | |||
s.println("(Warning porter AbortException without thrown)"); | |||
} | |||
s.println("Message: " + m); | |||
super.printStackTrace(s); | |||
} else { | |||
thrown.printStackTrace(s); | |||
} | |||
} | |||
IMessage m = getIMessage(); | |||
Throwable thrown = (null == m ? null : m.getThrown()); | |||
if (!isPorter() || (null == thrown)) { | |||
s.println("Message: " + m); | |||
super.printStackTrace(s); | |||
} else { | |||
thrown.printStackTrace(s); | |||
} | |||
} | |||
/** | |||
* Print the stack trace of any enclosed thrown or this otherwise. | |||
* | |||
* @see java.lang.Throwable#printStackTrace(PrintWriter) | |||
*/ | |||
public void printStackTrace(PrintWriter s) { | |||
IMessage m = getIMessage(); | |||
Throwable thrown = (null == m ? null : m.getThrown()); | |||
if (null == thrown) { // Always print | |||
if (isPorter()) { | |||
s.println("(Warning porter AbortException without thrown)"); | |||
} | |||
s.println("Message: " + m); | |||
super.printStackTrace(s); | |||
} else { | |||
thrown.printStackTrace(s); | |||
} | |||
} | |||
public boolean isSilent() { | |||
return isSilent; | |||
} | |||
public void setIsSilent(boolean isSilent) { | |||
this.isSilent = isSilent; | |||
} |
@@ -15,148 +15,143 @@ package org.aspectj.bridge; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import org.aspectj.util.LangUtil; | |||
/** | |||
* Wrap an IMessageHandler to count messages handled. | |||
* Messages being ignored by the delegate IMessageHandler are not counted. | |||
/** | |||
* Wrap an IMessageHandler to count messages handled. Messages being ignored by the delegate IMessageHandler are not counted. | |||
*/ | |||
public class CountingMessageHandler implements IMessageHandler { | |||
public final IMessageHandler delegate; | |||
public final CountingMessageHandler proxy; | |||
private final Hashtable counters; | |||
public static CountingMessageHandler makeCountingMessageHandler(IMessageHandler handler) { | |||
if (handler instanceof CountingMessageHandler) { | |||
return (CountingMessageHandler)handler; | |||
} else { | |||
return new CountingMessageHandler(handler); | |||
} | |||
} | |||
public CountingMessageHandler(IMessageHandler delegate) { | |||
LangUtil.throwIaxIfNull(delegate, "delegate"); | |||
this.delegate = delegate; | |||
this.counters = new Hashtable(); | |||
proxy = (delegate instanceof CountingMessageHandler | |||
? (CountingMessageHandler) delegate | |||
: null); | |||
} | |||
/** @return delegate.handleMessage(IMessage) */ | |||
public boolean handleMessage(IMessage message) throws AbortException { | |||
if (null != proxy) { | |||
return proxy.handleMessage(message); | |||
} | |||
if (null != message) { | |||
IMessage.Kind kind = message.getKind(); | |||
if (!isIgnoring(kind)) { | |||
increment(kind); | |||
} | |||
} | |||
return delegate.handleMessage(message); | |||
} | |||
/** @return delegate.isIgnoring(IMessage.Kind) */ | |||
public boolean isIgnoring(IMessage.Kind kind) { | |||
return delegate.isIgnoring(kind); | |||
} | |||
/** | |||
* Delegate | |||
* @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) | |||
* @param kind | |||
*/ | |||
public void dontIgnore(IMessage.Kind kind) { | |||
delegate.dontIgnore(kind); | |||
} | |||
/** | |||
* Delegate | |||
* @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) | |||
* @param kind | |||
*/ | |||
public final IMessageHandler delegate; | |||
public final CountingMessageHandler proxy; | |||
private final Hashtable<IMessage.Kind, IntHolder> counters; | |||
public static CountingMessageHandler makeCountingMessageHandler(IMessageHandler handler) { | |||
if (handler instanceof CountingMessageHandler) { | |||
return (CountingMessageHandler) handler; | |||
} else { | |||
return new CountingMessageHandler(handler); | |||
} | |||
} | |||
public CountingMessageHandler(IMessageHandler delegate) { | |||
LangUtil.throwIaxIfNull(delegate, "delegate"); | |||
this.delegate = delegate; | |||
this.counters = new Hashtable<IMessage.Kind, IntHolder>(); | |||
proxy = (delegate instanceof CountingMessageHandler ? (CountingMessageHandler) delegate : null); | |||
} | |||
/** @return delegate.handleMessage(IMessage) */ | |||
public boolean handleMessage(IMessage message) throws AbortException { | |||
if (null != proxy) { | |||
return proxy.handleMessage(message); | |||
} | |||
if (null != message) { | |||
IMessage.Kind kind = message.getKind(); | |||
if (!isIgnoring(kind)) { | |||
increment(kind); | |||
} | |||
} | |||
return delegate.handleMessage(message); | |||
} | |||
/** @return delegate.isIgnoring(IMessage.Kind) */ | |||
public boolean isIgnoring(IMessage.Kind kind) { | |||
return delegate.isIgnoring(kind); | |||
} | |||
/** | |||
* Delegate | |||
* | |||
* @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) | |||
* @param kind | |||
*/ | |||
public void dontIgnore(IMessage.Kind kind) { | |||
delegate.dontIgnore(kind); | |||
} | |||
/** | |||
* Delegate | |||
* | |||
* @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) | |||
* @param kind | |||
*/ | |||
public void ignore(IMessage.Kind kind) { | |||
delegate.ignore(kind); | |||
} | |||
/** @return delegate.toString() */ | |||
public String toString() { | |||
return delegate.toString(); | |||
} | |||
/** | |||
* Return count of messages seen through this interface. | |||
* @param kind the IMessage.Kind of the messages to count | |||
* (if null, count all) | |||
* @param orGreater if true, then count this kind and any | |||
* considered greater by the ordering of | |||
* IMessage.Kind.COMPARATOR | |||
* @return number of messages of this kind (optionally or greater) | |||
* @see IMessage.Kind.COMPARATOR | |||
*/ | |||
public int numMessages(IMessage.Kind kind, boolean orGreater) { | |||
if (null != proxy) { | |||
return proxy.numMessages(kind, orGreater); | |||
} | |||
int result = 0; | |||
if (null == kind) { | |||
for (Enumeration enu = counters.elements(); enu.hasMoreElements();) { | |||
result += ((IntHolder) enu.nextElement()).count; | |||
/** @return delegate.toString() */ | |||
public String toString() { | |||
return delegate.toString(); | |||
} | |||
/** | |||
* Return count of messages seen through this interface. | |||
* | |||
* @param kind the IMessage.Kind of the messages to count (if null, count all) | |||
* @param orGreater if true, then count this kind and any considered greater by the ordering of IMessage.Kind.COMPARATOR | |||
* @return number of messages of this kind (optionally or greater) | |||
* @see IMessage.Kind.COMPARATOR | |||
*/ | |||
public int numMessages(IMessage.Kind kind, boolean orGreater) { | |||
if (null != proxy) { | |||
return proxy.numMessages(kind, orGreater); | |||
} | |||
int result = 0; | |||
if (null == kind) { | |||
for (Enumeration<IntHolder> enu = counters.elements(); enu.hasMoreElements();) { | |||
result += (enu.nextElement()).count; | |||
} | |||
} else if (!orGreater) { | |||
result = numMessages(kind); | |||
} else { | |||
for (IMessage.Kind k : IMessage.KINDS) { | |||
if (kind.isSameOrLessThan(k)) { | |||
result += numMessages(k); | |||
} | |||
} | |||
} else if (!orGreater) { | |||
result = numMessages(kind); | |||
} else { | |||
for (Iterator iter = IMessage.KINDS.iterator(); iter.hasNext();) { | |||
IMessage.Kind k = (IMessage.Kind) iter.next(); | |||
if (kind.isSameOrLessThan(k)) { | |||
result += numMessages(k); | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
* @return true if 0 is less than | |||
* <code>numMessages(IMessage.ERROR, true)</code> | |||
*/ | |||
public boolean hasErrors() { | |||
return (0 < numMessages(IMessage.ERROR, true)); | |||
} | |||
private int numMessages(IMessage.Kind kind) { | |||
if (null != proxy) { | |||
return proxy.numMessages(kind); | |||
} | |||
IntHolder counter = (IntHolder) counters.get(kind); | |||
return (null == counter ? 0 : counter.count); | |||
} | |||
private void increment(IMessage.Kind kind) { | |||
if (null != proxy) { | |||
throw new IllegalStateException("not called when proxying"); | |||
} | |||
IntHolder counter = (IntHolder) counters.get(kind); | |||
if (null == counter) { | |||
counter = new IntHolder(); | |||
counters.put(kind, counter); | |||
} | |||
counter.count++; | |||
} | |||
private static class IntHolder { | |||
int count; | |||
} | |||
public void reset() { | |||
if (proxy != null) proxy.reset(); | |||
counters.clear(); | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
* @return true if 0 is less than <code>numMessages(IMessage.ERROR, true)</code> | |||
*/ | |||
public boolean hasErrors() { | |||
return (0 < numMessages(IMessage.ERROR, true)); | |||
} | |||
private int numMessages(IMessage.Kind kind) { | |||
if (null != proxy) { | |||
return proxy.numMessages(kind); | |||
} | |||
IntHolder counter = counters.get(kind); | |||
return (null == counter ? 0 : counter.count); | |||
} | |||
private void increment(IMessage.Kind kind) { | |||
if (null != proxy) { | |||
throw new IllegalStateException("not called when proxying"); | |||
} | |||
IntHolder counter = counters.get(kind); | |||
if (null == counter) { | |||
counter = new IntHolder(); | |||
counters.put(kind, counter); | |||
} | |||
counter.count++; | |||
} | |||
private static class IntHolder { | |||
int count; | |||
} | |||
public void reset() { | |||
if (proxy != null) { | |||
proxy.reset(); | |||
} | |||
counters.clear(); | |||
} | |||
} |
@@ -90,11 +90,9 @@ public interface IMessage { | |||
/** @return source location associated with this message, or null if none */ | |||
ISourceLocation getSourceLocation(); | |||
public static final class Kind implements Comparable { | |||
public static final Comparator COMPARATOR = new Comparator() { | |||
public int compare(Object o1, Object o2) { | |||
Kind one = (Kind) o1; | |||
Kind two = (Kind) o2; | |||
public static final class Kind implements Comparable<IMessage.Kind> { | |||
public static final Comparator<IMessage.Kind> COMPARATOR = new Comparator<IMessage.Kind>() { | |||
public int compare(IMessage.Kind one, IMessage.Kind two) { | |||
if (null == one) { | |||
return (null == two ? 0 : -1); | |||
} else if (null == two) { | |||
@@ -115,7 +113,7 @@ public interface IMessage { | |||
return (0 >= COMPARATOR.compare(this, kind)); | |||
} | |||
public int compareTo(Object other) { | |||
public int compareTo(IMessage.Kind other) { | |||
return COMPARATOR.compare(this, other); | |||
} | |||
@@ -148,5 +146,5 @@ public interface IMessage { | |||
* being based on a subtype of a defining type. | |||
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=41952">AspectJ bug 41952</a> | |||
*/ | |||
public List getExtraSourceLocations(); | |||
public List<ISourceLocation> getExtraSourceLocations(); | |||
} |
@@ -18,53 +18,49 @@ import java.util.List; | |||
/** | |||
* Hold and query a collection of messages. | |||
*/ | |||
public interface IMessageHolder | |||
extends IMessageHandler { // XXX do not extend - mix instead | |||
// XXX go to LT EQ GT GE LE rather than simple orGreater | |||
public interface IMessageHolder extends IMessageHandler { // XXX do not extend - mix instead | |||
// XXX go to LT EQ GT GE LE rather than simple orGreater | |||
/** value for orGreater parameter */ | |||
public static final boolean ORGREATER = true; | |||
/** value for orGreater parameter */ | |||
public static final boolean EQUAL = false; | |||
/** | |||
* Tell whether this holder has any message of this kind | |||
* (optionally or greater). | |||
/** | |||
* Tell whether this holder has any message of this kind (optionally or greater). | |||
* | |||
* @param kind the IMessage.Kind to check for - accept any if null | |||
* @param orGreater if true, also any greater than the target kind | |||
* as determined by IMessage.Kind.COMPARATOR | |||
* @return true if this holder has any message of this kind, | |||
* or if orGreater and any message has a greater kind, | |||
* as determined by IMessage.Kind.COMPARATOR | |||
* @param orGreater if true, also any greater than the target kind as determined by IMessage.Kind.COMPARATOR | |||
* @return true if this holder has any message of this kind, or if orGreater and any message has a greater kind, as determined | |||
* by IMessage.Kind.COMPARATOR | |||
*/ | |||
boolean hasAnyMessage(IMessage.Kind kind, boolean orGreater); | |||
/** | |||
* Count the messages currently held by this holder. | |||
* Pass null to get all kinds. | |||
* Count the messages currently held by this holder. Pass null to get all kinds. | |||
* | |||
* @param kind the IMessage.Kind expected, or null for all messages | |||
* @param orGreater if true, also any greater than the target kind | |||
* as determined by IMessage.Kind.COMPARATOR | |||
* @param orGreater if true, also any greater than the target kind as determined by IMessage.Kind.COMPARATOR | |||
* @return number of IMessage held (now) by this holder | |||
*/ | |||
int numMessages(IMessage.Kind kind, boolean orGreater); | |||
/** | |||
* Get all messages or those of a specific kind. | |||
* Pass null to get all kinds. | |||
* Get all messages or those of a specific kind. Pass null to get all kinds. | |||
* | |||
* @param kind the IMessage.Kind expected, or null for all messages | |||
* @param orGreater if true, also get any greater than the target kind | |||
* as determined by IMessage.Kind.COMPARATOR | |||
* @param orGreater if true, also get any greater than the target kind as determined by IMessage.Kind.COMPARATOR | |||
* @return IMessage[] of messages of the right kind, or IMessage.NONE | |||
*/ | |||
IMessage[] getMessages(IMessage.Kind kind, boolean orGreater); | |||
/** @return unmodifiable List view of underlying collection of IMessage */ | |||
List getUnmodifiableListView(); | |||
/** | |||
* Clear any messages. | |||
* @throws UnsupportedOperationException if message list is read-only | |||
*/ | |||
void clearMessages() throws UnsupportedOperationException; | |||
/** @return unmodifiable List view of underlying collection of IMessage */ | |||
List<IMessage> getUnmodifiableListView(); | |||
/** | |||
* Clear any messages. | |||
* | |||
* @throws UnsupportedOperationException if message list is read-only | |||
*/ | |||
void clearMessages() throws UnsupportedOperationException; | |||
} |
@@ -11,177 +11,168 @@ | |||
* Xerox/PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.bridge; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
* Implement messages. | |||
* This implementation is immutable if ISourceLocation is immutable. | |||
* Implement messages. This implementation is immutable if ISourceLocation is immutable. | |||
*/ | |||
public class Message implements IMessage { | |||
private final String message; | |||
private final IMessage.Kind kind; | |||
private final Throwable thrown; | |||
private final ISourceLocation sourceLocation; | |||
private final String details; | |||
private final List/*SourceLocation*/ extraSourceLocations; | |||
private final boolean declared; // Is it a DEOW ? | |||
private final int id; | |||
private final int sourceStart,sourceEnd; | |||
/** | |||
* Create a (compiler) error or warning message | |||
* @param message the String used as the underlying message | |||
* @param location the ISourceLocation, if any, associated with this message | |||
* @param isError if true, use IMessage.ERROR; else use IMessage.WARNING | |||
*/ | |||
public Message(String message, ISourceLocation location, boolean isError) { | |||
this(message, (isError ? IMessage.ERROR : IMessage.WARNING), null, | |||
location); | |||
} | |||
public Message(String message, ISourceLocation location, boolean isError, ISourceLocation[] extraSourceLocations) { | |||
this(message, "",(isError ? IMessage.ERROR : IMessage.WARNING), location, null, | |||
(extraSourceLocations.length > 0 ? extraSourceLocations : null)); | |||
} | |||
private final String message; | |||
private final IMessage.Kind kind; | |||
private final Throwable thrown; | |||
private final ISourceLocation sourceLocation; | |||
private final String details; | |||
private final List<ISourceLocation> extraSourceLocations; | |||
private final boolean declared; // Is it a DEOW ? | |||
private final int id; | |||
private final int sourceStart, sourceEnd; | |||
/** | |||
* Create a message, handling null values for message and kind | |||
* if thrown is not null. | |||
* Create a (compiler) error or warning message | |||
* | |||
* @param message the String used as the underlying message | |||
* @param location the ISourceLocation, if any, associated with this message | |||
* @param isError if true, use IMessage.ERROR; else use IMessage.WARNING | |||
*/ | |||
public Message(String message, ISourceLocation location, boolean isError) { | |||
this(message, (isError ? IMessage.ERROR : IMessage.WARNING), null, location); | |||
} | |||
public Message(String message, ISourceLocation location, boolean isError, ISourceLocation[] extraSourceLocations) { | |||
this(message, "", (isError ? IMessage.ERROR : IMessage.WARNING), location, null, | |||
(extraSourceLocations.length > 0 ? extraSourceLocations : null)); | |||
} | |||
/** | |||
* Create a message, handling null values for message and kind if thrown is not null. | |||
* | |||
* @param message the String used as the underlying message | |||
* @param kind the IMessage.Kind of message - not null | |||
* @param thrown the Throwable, if any, associated with this message | |||
* @param sourceLocation the ISourceLocation, if any, associated with this message | |||
* @param details descriptive information about the message | |||
* @throws IllegalArgumentException if message is null and | |||
* thrown is null or has a null message, or if kind is null | |||
* and thrown is null. | |||
* @throws IllegalArgumentException if message is null and thrown is null or has a null message, or if kind is null and thrown | |||
* is null. | |||
*/ | |||
public Message(String message, String details, IMessage.Kind kind, | |||
ISourceLocation sourceLocation, Throwable thrown, ISourceLocation[] extraSourceLocations) { | |||
this(message,details,kind,sourceLocation,thrown,extraSourceLocations,false,0,-1,-1); | |||
} | |||
public Message(String message, String details, IMessage.Kind kind, | |||
ISourceLocation sLoc, Throwable thrown, ISourceLocation[] otherLocs, | |||
boolean declared,int id,int sourcestart,int sourceend) { | |||
public Message(String message, String details, IMessage.Kind kind, ISourceLocation sourceLocation, Throwable thrown, | |||
ISourceLocation[] extraSourceLocations) { | |||
this(message, details, kind, sourceLocation, thrown, extraSourceLocations, false, 0, -1, -1); | |||
} | |||
public Message(String message, String details, IMessage.Kind kind, ISourceLocation sLoc, Throwable thrown, | |||
ISourceLocation[] otherLocs, boolean declared, int id, int sourcestart, int sourceend) { | |||
this.details = details; | |||
this.id = id; | |||
this.sourceStart = sourcestart; | |||
this.sourceEnd = sourceend; | |||
this.message = ((message!=null) ? message : ((thrown==null) ? null : thrown.getMessage())); | |||
this.message = ((message != null) ? message : ((thrown == null) ? null : thrown.getMessage())); | |||
this.kind = kind; | |||
this.sourceLocation = sLoc; | |||
this.thrown = thrown; | |||
if (otherLocs != null) { | |||
this.extraSourceLocations | |||
= Collections.unmodifiableList(Arrays.asList(otherLocs)); | |||
} | |||
else { | |||
this.extraSourceLocations = Collections.EMPTY_LIST; | |||
if (otherLocs != null) { | |||
this.extraSourceLocations = Collections.unmodifiableList(Arrays.asList(otherLocs)); | |||
} else { | |||
this.extraSourceLocations = Collections.emptyList(); | |||
} | |||
if (null == this.kind) { | |||
throw new IllegalArgumentException("null kind"); | |||
throw new IllegalArgumentException("null kind"); | |||
} | |||
if (null == this.message) { | |||
throw new IllegalArgumentException("null message"); | |||
} | |||
} | |||
this.declared = declared; | |||
} | |||
/** | |||
* Create a message, handling null values for message and kind | |||
* if thrown is not null. | |||
* @param message the String used as the underlying message | |||
* @param kind the IMessage.Kind of message - not null | |||
* @param thrown the Throwable, if any, associated with this message | |||
* @param sourceLocation the ISourceLocation, if any, associated with this message | |||
* @throws IllegalArgumentException if message is null and | |||
* thrown is null or has a null message, or if kind is null | |||
* and thrown is null. | |||
*/ | |||
public Message(String message, IMessage.Kind kind, Throwable thrown, | |||
ISourceLocation sourceLocation) { | |||
this(message, "", kind, sourceLocation, thrown, null ); | |||
} | |||
/** @return the kind of this message */ | |||
public IMessage.Kind getKind() { | |||
return kind; | |||
} | |||
/** @return true if kind == IMessage.ERROR */ | |||
public boolean isError() { | |||
return kind == IMessage.ERROR; | |||
} | |||
/** @return true if kind == IMessage.WARNING */ | |||
public boolean isWarning() { | |||
return kind == IMessage.WARNING; | |||
} | |||
/** @return true if kind == IMessage.DEBUG */ | |||
public boolean isDebug() { | |||
return kind == IMessage.DEBUG; | |||
} | |||
/** | |||
* Create a message, handling null values for message and kind if thrown is not null. | |||
* | |||
* @param message the String used as the underlying message | |||
* @param kind the IMessage.Kind of message - not null | |||
* @param thrown the Throwable, if any, associated with this message | |||
* @param sourceLocation the ISourceLocation, if any, associated with this message | |||
* @throws IllegalArgumentException if message is null and thrown is null or has a null message, or if kind is null and thrown | |||
* is null. | |||
*/ | |||
public Message(String message, IMessage.Kind kind, Throwable thrown, ISourceLocation sourceLocation) { | |||
this(message, "", kind, sourceLocation, thrown, null); | |||
} | |||
/** @return the kind of this message */ | |||
public IMessage.Kind getKind() { | |||
return kind; | |||
} | |||
/** @return true if kind == IMessage.ERROR */ | |||
public boolean isError() { | |||
return kind == IMessage.ERROR; | |||
} | |||
/** @return true if kind == IMessage.WARNING */ | |||
public boolean isWarning() { | |||
return kind == IMessage.WARNING; | |||
} | |||
/** @return true if kind == IMessage.DEBUG */ | |||
public boolean isDebug() { | |||
return kind == IMessage.DEBUG; | |||
} | |||
public boolean isTaskTag() { | |||
return kind == IMessage.TASKTAG; | |||
} | |||
/** | |||
* @return true if kind == IMessage.INFO | |||
*/ | |||
public boolean isInfo() { | |||
return kind == IMessage.INFO; | |||
} | |||
/** @return true if kind == IMessage.ABORT */ | |||
public boolean isAbort() { | |||
return kind == IMessage.ABORT; | |||
} | |||
/** Caller can verify if this message came about because of a DEOW */ | |||
public boolean getDeclared() { | |||
return declared; | |||
} | |||
/** | |||
* @return true if kind == IMessage.FAIL | |||
*/ | |||
public boolean isFailed() { | |||
return kind == IMessage.FAIL; | |||
} | |||
/** @return non-null String with simple message */ | |||
final public String getMessage() { | |||
return message; | |||
} | |||
/** @return Throwable associated with this message, or null if none */ | |||
final public Throwable getThrown() { | |||
return thrown; | |||
} | |||
/** @return ISourceLocation associated with this message, or null if none */ | |||
final public ISourceLocation getSourceLocation() { | |||
return sourceLocation; | |||
} | |||
public String toString() { | |||
return MessageUtil.renderMessage(this,false); | |||
} | |||
/** | |||
* @return true if kind == IMessage.INFO | |||
*/ | |||
public boolean isInfo() { | |||
return kind == IMessage.INFO; | |||
} | |||
/** @return true if kind == IMessage.ABORT */ | |||
public boolean isAbort() { | |||
return kind == IMessage.ABORT; | |||
} | |||
/** Caller can verify if this message came about because of a DEOW */ | |||
public boolean getDeclared() { | |||
return declared; | |||
} | |||
/** | |||
* @return true if kind == IMessage.FAIL | |||
*/ | |||
public boolean isFailed() { | |||
return kind == IMessage.FAIL; | |||
} | |||
/** @return non-null String with simple message */ | |||
final public String getMessage() { | |||
return message; | |||
} | |||
/** @return Throwable associated with this message, or null if none */ | |||
final public Throwable getThrown() { | |||
return thrown; | |||
} | |||
/** @return ISourceLocation associated with this message, or null if none */ | |||
final public ISourceLocation getSourceLocation() { | |||
return sourceLocation; | |||
} | |||
public String toString() { | |||
return MessageUtil.renderMessage(this, false); | |||
} | |||
public String getDetails() { | |||
return details; | |||
} | |||
public List getExtraSourceLocations() { | |||
public List<ISourceLocation> getExtraSourceLocations() { | |||
return extraSourceLocations; | |||
} | |||
@@ -192,7 +183,7 @@ public class Message implements IMessage { | |||
public int getSourceStart() { | |||
return sourceStart; | |||
} | |||
public int getSourceEnd() { | |||
return sourceEnd; | |||
} |
@@ -13,260 +13,253 @@ | |||
package org.aspectj.bridge; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
/** | |||
* This handler accumulates messages. | |||
* To control messages accumulated, | |||
* clients can ignore messages of a given kind, | |||
* or install a listener/interceptor. | |||
* The interceptor handles all messages (even null) first, | |||
* and can halt further processing/accumlation by returning true. | |||
* Clients can obtain messages accumulated using the get... methods. | |||
* XXX this does not permit messages to be removed. | |||
* This handler accumulates messages. To control messages accumulated, clients can ignore messages of a given kind, or install a | |||
* listener/interceptor. The interceptor handles all messages (even null) first, and can halt further processing/accumlation by | |||
* returning true. Clients can obtain messages accumulated using the get... methods. XXX this does not permit messages to be | |||
* removed. | |||
* | |||
* @author PARC | |||
* @author Andy Clement | |||
*/ | |||
public class MessageHandler implements IMessageHolder { | |||
/** messages accumulated */ | |||
protected final ArrayList messages; | |||
/** kinds of messages to be ignored */ | |||
protected final ArrayList ignoring; | |||
/** result of handleMessage(..) for messages not accumulated (ignored) */ | |||
protected boolean handleMessageResult; | |||
/** listener which can halt processing by returning true */ | |||
protected IMessageHandler interceptor; | |||
/** | |||
* same as MessageHandler(false) | |||
*/ | |||
public MessageHandler() { | |||
this(false); | |||
} | |||
/** | |||
* @param accumulateOnly the result of handleMessage | |||
* (i.e., if true, then only accumulate messages - stop processing | |||
*/ | |||
public MessageHandler(boolean accumulateOnly) { | |||
messages = new ArrayList(); | |||
ignoring = new ArrayList(); | |||
init(accumulateOnly); | |||
ignore(IMessage.WEAVEINFO); // Off by default, need to explicitly be enabled (see -showWeaveInfo) | |||
} | |||
/** | |||
* Initialize this, removing any messages accumulated, | |||
* kinds being ignored, or interceptor. | |||
* Assume that this should return false from handleMessage(..). | |||
*/ | |||
public void init() { init(false); } | |||
/** | |||
* Initialize this, removing any messages accumulated, | |||
* kinds being ignored, or interceptor. | |||
* @param accumulateOnly boolean value returned from handleMessage | |||
* after accumulating in list | |||
*/ | |||
public void init(boolean accumulateOnly) { | |||
handleMessageResult = accumulateOnly; | |||
if (0 < messages.size()) { | |||
messages.clear(); | |||
} | |||
if (0 < ignoring.size()) { | |||
boolean ignoringWeaveMessages = isIgnoring(IMessage.WEAVEINFO); | |||
ignoring.clear(); | |||
if (ignoringWeaveMessages) ignore(IMessage.WEAVEINFO); | |||
} | |||
if (null != interceptor) { | |||
interceptor = null; | |||
} | |||
} | |||
/** | |||
* Clear the messages without changing other behavior. | |||
*/ | |||
public void clearMessages() { | |||
if (0 < messages.size()) { | |||
messages.clear(); | |||
} | |||
} | |||
/** messages accumulated */ | |||
protected final ArrayList<IMessage> messages; | |||
/** kinds of messages to be ignored */ | |||
protected final ArrayList<IMessage.Kind> ignoring; | |||
/** result of handleMessage(..) for messages not accumulated (ignored) */ | |||
protected boolean handleMessageResult; | |||
/** listener which can halt processing by returning true */ | |||
protected IMessageHandler interceptor; | |||
/** | |||
* same as MessageHandler(false) | |||
*/ | |||
public MessageHandler() { | |||
this(false); | |||
} | |||
/** | |||
* @param accumulateOnly the result of handleMessage (i.e., if true, then only accumulate messages - stop processing | |||
*/ | |||
public MessageHandler(boolean accumulateOnly) { | |||
messages = new ArrayList<IMessage>(); | |||
ignoring = new ArrayList<IMessage.Kind>(); | |||
init(accumulateOnly); | |||
ignore(IMessage.WEAVEINFO); // Off by default, need to explicitly be enabled (see -showWeaveInfo) | |||
} | |||
/** | |||
* Initialize this, removing any messages accumulated, kinds being ignored, or interceptor. Assume that this should return false | |||
* from handleMessage(..). | |||
*/ | |||
public void init() { | |||
init(false); | |||
} | |||
/** | |||
* Initialize this, removing any messages accumulated, kinds being ignored, or interceptor. | |||
* | |||
* @param accumulateOnly boolean value returned from handleMessage after accumulating in list | |||
*/ | |||
public void init(boolean accumulateOnly) { | |||
handleMessageResult = accumulateOnly; | |||
if (0 < messages.size()) { | |||
messages.clear(); | |||
} | |||
if (0 < ignoring.size()) { | |||
boolean ignoringWeaveMessages = isIgnoring(IMessage.WEAVEINFO); | |||
ignoring.clear(); | |||
if (ignoringWeaveMessages) { | |||
ignore(IMessage.WEAVEINFO); | |||
} | |||
} | |||
if (null != interceptor) { | |||
interceptor = null; | |||
} | |||
} | |||
/** | |||
* Clear the messages without changing other behavior. | |||
*/ | |||
public void clearMessages() { | |||
if (0 < messages.size()) { | |||
messages.clear(); | |||
} | |||
} | |||
// ---------------------- IMessageHandler implementation | |||
// ---------------------- IMessageHandler implementation | |||
/** | |||
* This implementation accumulates message. | |||
* If an interceptor is installed and returns true (message handled), | |||
* then processing halts and the message is not accumulated. | |||
* This implementation accumulates message. If an interceptor is installed and returns true (message handled), then processing | |||
* halts and the message is not accumulated. | |||
* | |||
* @see org.aspectj.bridge.IMessageHandler#handleMessage(IMessage) | |||
* @return true on interception or the constructor value otherwise | |||
*/ | |||
*/ | |||
public boolean handleMessage(IMessage message) { | |||
if ((null != interceptor) && (interceptor.handleMessage(message))) { | |||
return true; | |||
} | |||
if (null == message) { | |||
throw new IllegalArgumentException("null message"); | |||
} | |||
if (!ignoring.contains(message.getKind())) { | |||
messages.add(message); | |||
} | |||
return handleMessageResult; | |||
} | |||
if ((null != interceptor) && (interceptor.handleMessage(message))) { | |||
return true; | |||
} | |||
if (null == message) { | |||
throw new IllegalArgumentException("null message"); | |||
} | |||
if (!ignoring.contains(message.getKind())) { | |||
messages.add(message); | |||
} | |||
return handleMessageResult; | |||
} | |||
/** | |||
* @return true if this kind has been flagged to be ignored. | |||
* @see #ignore(IMessage.Kind) | |||
/** | |||
* @return true if this kind has been flagged to be ignored. | |||
* @see #ignore(IMessage.Kind) | |||
* @see org.aspectj.bridge.IMessageHandler#isIgnoring(Kind) | |||
*/ | |||
public boolean isIgnoring(IMessage.Kind kind) { | |||
return ((null != kind) && (ignoring.contains(kind))); | |||
} | |||
// ---------------------- end of IMessageHandler implementation | |||
// ---------------------- end of IMessageHandler implementation | |||
/** | |||
* Set a message kind to be ignored from now on | |||
*/ | |||
public void ignore(IMessage.Kind kind) { // XXX sync | |||
if ((null != kind) && (!ignoring.contains(kind))) { | |||
ignoring.add(kind); | |||
} | |||
} | |||
/** | |||
* Set a message kind to be ignored from now on | |||
*/ | |||
public void ignore(IMessage.Kind kind) { // XXX sync | |||
if ((null != kind) && (!ignoring.contains(kind))) { | |||
ignoring.add(kind); | |||
} | |||
} | |||
/** | |||
* Remove a message kind from the list of those ignored from now on. | |||
*/ | |||
public void dontIgnore(IMessage.Kind kind) { | |||
if (null != kind) { | |||
ignoring.remove(kind); | |||
} | |||
} | |||
/** | |||
* Remove a message kind from the list of those ignored from now on. | |||
*/ | |||
public void dontIgnore(IMessage.Kind kind) { | |||
if (null != kind) { | |||
ignoring.remove(kind); | |||
} | |||
} | |||
/** | |||
/** | |||
* @see org.aspectj.bridge.IMessageHolder#hasAnyMessage(Kind, boolean) | |||
*/ | |||
public boolean hasAnyMessage(final IMessage.Kind kind, final boolean orGreater) { | |||
if (null == kind) { | |||
return (0 < messages.size()); | |||
} | |||
if (!orGreater) { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
if (kind == ((IMessage) iter.next()).getKind()) { | |||
return true; | |||
} | |||
} | |||
} else { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
IMessage m = (IMessage) iter.next(); | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
if (null == kind) { | |||
return (0 < messages.size()); | |||
} | |||
if (!orGreater) { | |||
for (IMessage m : messages) { | |||
if (kind == m.getKind()) { | |||
return true; | |||
} | |||
} | |||
} else { | |||
for (IMessage m : messages) { | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* @return number of messages accumulated of a given kind | |||
*/ | |||
public int numMessages(IMessage.Kind kind, final boolean orGreater) { | |||
if (null == kind) { | |||
return messages.size(); | |||
} | |||
int result = 0; | |||
if (!orGreater) { | |||
for (IMessage m : messages) { | |||
if (kind == m.getKind()) { | |||
result++; | |||
} | |||
} | |||
} else { | |||
for (IMessage m : messages) { | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
result++; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
* @return number of messages accumulated of a given kind | |||
*/ | |||
public int numMessages(IMessage.Kind kind, final boolean orGreater) { | |||
if (null == kind) { | |||
return messages.size(); | |||
} | |||
int result = 0; | |||
if (!orGreater) { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
if (kind == ((IMessage) iter.next()).getKind()) { | |||
result++; | |||
} | |||
} | |||
} else { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
IMessage m = (IMessage) iter.next(); | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
result++; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
/** | |||
* @see org.aspectj.bridge.IMessageHolder#getUnmodifiableListView() | |||
*/ | |||
public List getUnmodifiableListView() { | |||
public List<IMessage> getUnmodifiableListView() { | |||
return Collections.unmodifiableList(messages); | |||
} | |||
/** | |||
* Get all messages or those of a specific kind. | |||
* Pass null to get all kinds. | |||
* @param kind the IMessage.Kind expected, or null for all messages | |||
* @return IMessage[] of messages of the right kind | |||
*/ | |||
public IMessage[] getMessages(IMessage.Kind kind, final boolean orGreater) { | |||
if (null == kind) { | |||
return (IMessage[]) messages.toArray(IMessage.RA_IMessage); | |||
} | |||
ArrayList result = new ArrayList(); | |||
if (!orGreater) { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
IMessage m = (IMessage) iter.next(); | |||
if (kind == m.getKind()) { | |||
result.add(m); | |||
} | |||
} | |||
} else { | |||
for (Iterator iter = messages.iterator(); iter.hasNext();) { | |||
IMessage m = (IMessage) iter.next(); | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
result.add(m); | |||
} | |||
} | |||
} | |||
if (0 == result.size()) { | |||
return IMessage.RA_IMessage; | |||
} | |||
return (IMessage[]) result.toArray(IMessage.RA_IMessage); | |||
} | |||
/** | |||
* @return array of error messages, or IMessage.NONE | |||
*/ | |||
public IMessage[] getErrors() { | |||
return getMessages(IMessage.ERROR, false); | |||
} | |||
/** | |||
* @return array of warning messages, or IMessage.NONE | |||
*/ | |||
public IMessage[] getWarnings() { | |||
return getMessages(IMessage.WARNING, false); | |||
} | |||
/** | |||
* Set the interceptor which gets any message before we process it. | |||
* @param interceptor the IMessageHandler passed the message. | |||
* Pass null to remove the old interceptor. | |||
*/ | |||
public void setInterceptor(IMessageHandler interceptor) { | |||
this.interceptor = interceptor; | |||
} | |||
/** | |||
* @return String containing list of messages | |||
*/ | |||
public String toString() { | |||
if (0 == messages.size()) { | |||
return "MessageHandler: no messages"; | |||
} else { | |||
return "MessageHandler: " + messages; | |||
} | |||
/** | |||
* Get all messages or those of a specific kind. Pass null to get all kinds. | |||
* | |||
* @param kind the IMessage.Kind expected, or null for all messages | |||
* @return IMessage[] of messages of the right kind | |||
*/ | |||
public IMessage[] getMessages(IMessage.Kind kind, final boolean orGreater) { | |||
if (null == kind) { | |||
return messages.toArray(IMessage.RA_IMessage); | |||
} | |||
ArrayList<IMessage> result = new ArrayList<IMessage>(); | |||
if (!orGreater) { | |||
for (IMessage m : messages) { | |||
if (kind == m.getKind()) { | |||
result.add(m); | |||
} | |||
} | |||
} else { | |||
for (IMessage m : messages) { | |||
if (kind.isSameOrLessThan(m.getKind())) { | |||
result.add(m); | |||
} | |||
} | |||
} | |||
if (0 == result.size()) { | |||
return IMessage.RA_IMessage; | |||
} | |||
return result.toArray(IMessage.RA_IMessage); | |||
} | |||
} | |||
/** | |||
* @return array of error messages, or IMessage.NONE | |||
*/ | |||
public IMessage[] getErrors() { | |||
return getMessages(IMessage.ERROR, false); | |||
} | |||
/** | |||
* @return array of warning messages, or IMessage.NONE | |||
*/ | |||
public IMessage[] getWarnings() { | |||
return getMessages(IMessage.WARNING, false); | |||
} | |||
/** | |||
* Set the interceptor which gets any message before we process it. | |||
* | |||
* @param interceptor the IMessageHandler passed the message. Pass null to remove the old interceptor. | |||
*/ | |||
public void setInterceptor(IMessageHandler interceptor) { | |||
this.interceptor = interceptor; | |||
} | |||
/** | |||
* @return String containing list of messages | |||
*/ | |||
public String toString() { | |||
if (0 == messages.size()) { | |||
return "MessageHandler: no messages"; | |||
} else { | |||
return "MessageHandler: " + messages; | |||
} | |||
} | |||
} |
@@ -20,87 +20,84 @@ import java.util.Arrays; | |||
* | |||
*/ | |||
public class ReflectionFactory { // XXX lease, pool | |||
public static final String OLD_AJC = "bridge.tools.impl.OldAjc"; | |||
public static final String ECLIPSE = "org.aspectj.ajdt.ajc.AjdtCommand"; | |||
private static final Object[] NONE = new Object[0]; | |||
/** | |||
* Produce a compiler as an ICommand. | |||
* @param cname the fully-qualified class name of the command | |||
* to create by reflection (assuming a public no-argument constructor). | |||
* @return ICommand compiler or null | |||
*/ | |||
public static ICommand makeCommand(String cname, | |||
IMessageHandler errorSink) { | |||
return (ICommand) make(ICommand.class, cname, NONE, errorSink); | |||
} | |||
/** | |||
* Make an object of type c by reflectively loading the class | |||
* cname and creating an instance using args (if any), | |||
* signalling errors (if any) to any errorSink. | |||
*/ | |||
private static Object make(Class c, String cname, Object[] args, | |||
IMessageHandler errorSink) { | |||
final boolean makeErrors = (null != errorSink); | |||
Object result = null; | |||
try { | |||
final Class cfn = Class.forName(cname); | |||
String error = null; | |||
if (args == NONE) { | |||
result = cfn.newInstance(); | |||
} else { | |||
Class[] types = getTypes(args); | |||
Constructor constructor = cfn.getConstructor(types); | |||
if (null != constructor) { | |||
result = constructor.newInstance(args); | |||
} else { | |||
if (makeErrors) { | |||
error = "no constructor for " + c + " using " | |||
+ Arrays.asList(types); | |||
} | |||
} | |||
} | |||
if (null != result) { | |||
if (!c.isAssignableFrom(result.getClass())) { | |||
if (makeErrors) { | |||
error = "expecting type " + c + " got " + result.getClass(); | |||
} | |||
result = null; | |||
} | |||
} | |||
if (null != error) { | |||
IMessage mssg = new Message(error, IMessage.FAIL, null, null); | |||
errorSink.handleMessage(mssg); | |||
} | |||
} catch (Throwable t) { | |||
if (makeErrors) { | |||
String mssg = "ReflectionFactory unable to load " | |||
+ cname + " as " + c.getName(); | |||
IMessage m = new Message(mssg, IMessage.FAIL, t, null); | |||
errorSink.handleMessage(m); | |||
} | |||
} | |||
return result; | |||
} | |||
public static final String OLD_AJC = "bridge.tools.impl.OldAjc"; | |||
public static final String ECLIPSE = "org.aspectj.ajdt.ajc.AjdtCommand"; | |||
/** | |||
* @return Class[] with types of args or matching null elements | |||
*/ | |||
private static Class[] getTypes(Object[] args) { | |||
if ((null == args) || (0 < args.length)) { | |||
return new Class[0]; | |||
} else { | |||
Class[] result = new Class[args.length]; | |||
for (int i = 0; i < result.length; i++) { | |||
if (null != args[i]) { | |||
result[i] = args[i].getClass(); | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||
private ReflectionFactory(){} | |||
private static final Object[] NONE = new Object[0]; | |||
/** | |||
* Produce a compiler as an ICommand. | |||
* | |||
* @param cname the fully-qualified class name of the command to create by reflection (assuming a public no-argument | |||
* constructor). | |||
* @return ICommand compiler or null | |||
*/ | |||
public static ICommand makeCommand(String cname, IMessageHandler errorSink) { | |||
return (ICommand) make(ICommand.class, cname, NONE, errorSink); | |||
} | |||
/** | |||
* Make an object of type c by reflectively loading the class cname and creating an instance using args (if any), signalling | |||
* errors (if any) to any errorSink. | |||
*/ | |||
private static Object make(Class<?> c, String cname, Object[] args, IMessageHandler errorSink) { | |||
final boolean makeErrors = (null != errorSink); | |||
Object result = null; | |||
try { | |||
final Class<?> cfn = Class.forName(cname); | |||
String error = null; | |||
if (args == NONE) { | |||
result = cfn.newInstance(); | |||
} else { | |||
Class<?>[] types = getTypes(args); | |||
Constructor<?> constructor = cfn.getConstructor(types); | |||
if (null != constructor) { | |||
result = constructor.newInstance(args); | |||
} else { | |||
if (makeErrors) { | |||
error = "no constructor for " + c + " using " + Arrays.asList(types); | |||
} | |||
} | |||
} | |||
if (null != result) { | |||
if (!c.isAssignableFrom(result.getClass())) { | |||
if (makeErrors) { | |||
error = "expecting type " + c + " got " + result.getClass(); | |||
} | |||
result = null; | |||
} | |||
} | |||
if (null != error) { | |||
IMessage mssg = new Message(error, IMessage.FAIL, null, null); | |||
errorSink.handleMessage(mssg); | |||
} | |||
} catch (Throwable t) { | |||
if (makeErrors) { | |||
String mssg = "ReflectionFactory unable to load " + cname + " as " + c.getName(); | |||
IMessage m = new Message(mssg, IMessage.FAIL, t, null); | |||
errorSink.handleMessage(m); | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
* @return Class[] with types of args or matching null elements | |||
*/ | |||
private static Class<?>[] getTypes(Object[] args) { | |||
if ((null == args) || (0 < args.length)) { | |||
return new Class[0]; | |||
} else { | |||
Class<?>[] result = new Class[args.length]; | |||
for (int i = 0; i < result.length; i++) { | |||
if (null != args[i]) { | |||
result[i] = args[i].getClass(); | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||
private ReflectionFactory() { | |||
} | |||
} |
@@ -26,7 +26,7 @@ import org.aspectj.util.LangUtil; | |||
* @see org.aspectj.tools.ide.SourceLine | |||
* @see org.aspectj.testing.harness.ErrorLine | |||
*/ | |||
public class SourceLocation implements ISourceLocation, java.io.Serializable { | |||
public class SourceLocation implements ISourceLocation { | |||
private static final long serialVersionUID = -5434765814401009794L; | |||