Bug 102479 - unable to specify a custom IMessageHolder class with ajc
Summary: unable to specify a custom IMessageHolder class with ajc
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.5.0RC1   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-07-01 09:30 EDT by Helen Beeken CLA
Modified: 2005-11-04 04:03 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Helen Beeken CLA 2005-07-01 09:30:09 EDT
You can currently provide your own implementation of IMessageHolder and use it
via iajc (using messageHolderClass="myMessageHolderClass" and
showWeaveInfo="true"), however, you can't do a similar thing when using ajc.
Comment 1 Andrew Clement CLA 2005-07-07 04:27:36 EDT
try and look at this for 1.5.0 ...
Comment 2 Adrian Colyer CLA 2005-09-01 13:08:28 EDT
Extended Ajde to allow specification of a custom IMessageHandler (which would also allow passing an 
IMessageHolder since that is a sub-interface). 

AJDT would call Ajde.init(....) as normal.

Then optionally can call Ajde.getDefault().setMessageHandler(IMessageHandler aHandler). If this call is 
made all messages will be routed to the user-supplied handler bypassing the default handler (which 
pushes messages out to the TaskListManager).

A subsequent call to setMessageHandler(null) will remove any custom handler and restore default 
processing.
Comment 3 Helen Beeken CLA 2005-09-14 05:40:14 EDT
Reopening this bug to cover the remaining issues.....

There is currently the "-XmessageHandlerClass" option which is used for LTW and
requires a class which implements IMessageHandler.

On the other hand, with iajc there is the messageHolderClass option which
requires a class which implements IMessageHolder.

IMessageHolder extends IMessageHandler.

The remaining issues are based around how best to surface this in ajdt and the
corresponding implementation that is required for this. Do we use the ltw -X
option and loose the consistency between what users can do with ant and the
compiler in AJDT, or do we provide another option which keeps the consistency
with ant but is different to the ltw option? Also, should it be a -X option?
Comment 4 Andrew Clement CLA 2005-09-14 14:18:43 EDT
Hmmm.  I think I need to clear up what exactly we want here - from Helens last
note on the bug, I might have been getting a couple of cases mixed up....  

I thought Helen wanted the extension to 'ajc' so that she could collect messages
and sift through them for the purposes of analysing coverage.  If so, we should
properly support -XmessageHandlerClass that LTW uses.  As with all -X options,
if it proves useful we'll migrate it to be a standard option.  Any old user can
exploit this with:

ajc -XmessageHandlerClass:Someclass A.java X.aj


If, however, we just want to enable users of *AJDT* to specify their own message
handler class then what Adrian has done should be sufficient and AJDT just needs
the ability for a user to set and remember a class name which can then be set
via the usual interface with AJDE.

The difference between a holder and a handler is that a holder is expected to
maintain the set of messages for querying sometime later - a handler is free to
process each one and then move on.  We wouldnt want the LTW to have a holder
(think of the memory use over time...) - we might do for the ANT support as some
operation after the compiler has run could process the output - probably don't
want a holder for inside AJDT either..I think.
Comment 5 Andrew Clement CLA 2005-09-27 08:04:09 EDT
I looked at what it takes to add this option.  There is already a bunch of
infrastructure for intercepting messages and it seems a shame to make it even
more complicated for this option.  Given that ajc is supposedly comparable with
javac, I don't see a similar option in javac.  And it does seem a little odd to
me that I could write a class to pass to the command line compiler.

Anyway, the easiest way to run the compiler and intercept the messages is like
this - and maybe the problem all along is that the ease with which this can be
done has not been documented and thats what we should do.  In order to continue
after the compiler finishes, may need to pass -noExit.

import java.util.List;

import org.aspectj.bridge.AbortException;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHolder;
import org.aspectj.bridge.IMessage.Kind;
import org.aspectj.tools.ajc.Main;

public class RunCompiler { 
  public static void main(String[] args) {
    Main compiler = new Main();
    compiler.run(args,new MyLocalHolder());
  }
}

class MyLocalHolder implements IMessageHolder {

	public boolean hasAnyMessage(Kind kind, boolean orGreater) {return false;}
	public int numMessages(Kind kind, boolean orGreater) {return 0;}
	public IMessage[] getMessages(Kind kind, boolean orGreater) {return null;}
	public List getUnmodifiableListView() {	return null;}
	public void clearMessages() throws UnsupportedOperationException {}
	public boolean isIgnoring(Kind kind) {	return false;}
	public void dontIgnore(Kind kind) {}

	public boolean handleMessage(IMessage message) throws AbortException {
		System.err.println("Intercepted: "+message);
		return false;
	}

}

java RunCompiler A.java B.aj -noExit -showWeaveInfo

The handleMessage() gets full control to do whatever it wants.

I think this would give Helen ample ability to process the IMessage objects to
confirm code coverage.
Comment 6 Andrew Clement CLA 2005-11-02 08:18:05 EST
Hi Wes - just wondered if I could get a 2nd opinion.  What do you think about us
doc'ing my final comment here?  For users who want to process compiler output.
Comment 7 Wes Isberg CLA 2005-11-03 00:46:17 EST
Sounds good -- I can add to end of devguideDB/ajc.xml.  I'd use (poorly-named)
MessageHandler rather than MyLocalHolder.  The compiler plumbing might downcast
from IMessageHandler to IMessageHolder (for incremental mode to check whether to
bail?), so without further review I'd agree ..Holder is the safe way.
Comment 8 Andrew Clement CLA 2005-11-03 06:25:54 EST
thanks Wes - I also thought you'd know where it would live in the docs.  If you
could put it in for me, that would be great!  Another bug down...
Comment 9 Wes Isberg CLA 2005-11-04 04:02:08 EST
This was already documented in the devguide ajc section:  "To access compiler
messages programmatically, use the methods setHolder(IMessageHolder holder)
and/or run(String[] args, IMessageHolder holder)."

I added to ajc.xml:1.14
----------
ajc reports each message to the holder using IMessageHolder.handleMessage(..).
If you just want to collect the messages, use MessageHandler as your
IMessageHolder. For example, compile and run the following with aspectjtools.jar
on the classpath:

import org.aspectj.bridge.*;
import org.aspectj.tools.ajc.Main;
import java.util.Arrays;

public class WrapAjc {
  public static void main(String[] args) {
    Main compiler = new Main();
    MessageHandler m = new MessageHandler();
    compiler.run(args, m);
    IMessage[] ms = m.getMessages(null, true);
    System.out.println("messages: " + Arrays.asList(ms));
  }
----------

Ok to close?
Comment 10 Andrew Clement CLA 2005-11-04 04:03:39 EST
thanks Wes!