/*
* Copyright(C) 2001 Mika Riekkinen, Joni Suominen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or(at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alt.jiapi.event;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import alt.jiapi.InstrumentationDescriptor;
import alt.jiapi.instrumentor.ChainInstrumentor;
import alt.jiapi.instrumentor.InstrumentorChain;
import alt.jiapi.instrumentor.CatchInstrumentor;
import alt.jiapi.instrumentor.GrepInstrumentor;
import alt.jiapi.instrumentor.HeadInstrumentor;
import alt.jiapi.instrumentor.MethodCallInstrumentor;
import alt.jiapi.instrumentor.MethodDispatcherInstrumentor;
/**
* This class registers itself to Jiapi runtime and tracks Exception
* related events. When such an event happens, each registered listener
* will notified.
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.9 $ $Date: 2004/03/15 14:47:52 $
*/
public class ExceptionEventProducer extends EventProducer {
private List listeners = new ArrayList();
/**
* Constructor. Resolution is set to '*', which indicates all the
* ExceptionEvents are produced.
*
* @param id Instrumentation decsriptor, that this ExceptionEventProducer
* registers itself to.
*/
public ExceptionEventProducer(InstrumentationDescriptor id) {
this(id, "*");
}
/**
* Constructor. Only ExceptionEvents, that match with resolution,
* are produced. Resolution is compared against the name of the
* Exception during instrumentation. Name of the Exception is exactly
* the same, as it is given in Java source code in
* <code>catch(....)</code> statement. This means, that if one is
* catching <code>java.lang.Exception</code>, and
* <code>java.lang.ClassNotFoundException</code> is trapped, the former
* is used in resolution comparison.
*
* @param id Instrumentation decsriptor, that this ExceptionEventProducer
* registers itself to.
* @param resolution Resolution, that is used further to select which
* Exceptions will trigger events to be produced.
*/
public ExceptionEventProducer(InstrumentationDescriptor id, String resolution) {
super(resolution);
try {
InstrumentorChain chain = new InstrumentorChain();
ChainInstrumentor dispatcher = new MethodDispatcherInstrumentor();
CatchInstrumentor selectCatchBlocks = new CatchInstrumentor();
ChainInstrumentor selectHead = new HeadInstrumentor();
ChainInstrumentor callMethod =
new MethodCallInstrumentor(new CatchHook(this));
selectCatchBlocks.setResolutions(getResolutions());
chain.add(dispatcher);
chain.add(selectCatchBlocks);
chain.add(selectHead);
chain.add(callMethod);
id.addInstrumentor(chain);
} catch (Exception e) {
// NOTE! Fix exception handling.
e.printStackTrace();
}
}
/**
* Adds a ExceptionListener.
* @param fl a ExceptionListener
*/
public synchronized void addExceptionListener(ExceptionListener fl) {
listeners.add(fl);
}
/**
* Removes a ExceptionListener.
* @param fl a ExceptionListener
*/
public synchronized void removeExceptionListener(ExceptionListener fl) {
listeners.remove(fl);
}
/**
* This method is called by the Jiapi runtime. It should not be called
* by others.
*/
public void catchTrapped(Object sourceObject, String exceptionName) {
catchTrapped(sourceObject, exceptionName, null);
}
/**
* This method is called by the Jiapi runtime. It should not be called
* by others.
*/
public void catchTrapped(Object sourceObject, String exceptionName,
Object target) {
if (!isProtected(sourceObject)) {
fireCatchEvent(sourceObject, exceptionName, target);
}
}
/**
* Fires an event when exception has been caught.
* @param target Target object
* @param methodName Name of the method
*/
protected synchronized void fireCatchEvent(Object sourceObject,
String exceptionName,
Object target) {
Iterator i = listeners.iterator();
ExceptionEvent event =
new ExceptionEvent(this, sourceObject, exceptionName,
target,
ExceptionEvent.CATCH_TRAPPED);
while (i.hasNext()) {
ExceptionListener el = (ExceptionListener)i.next();
el.exceptionCaught(event);
}
}
}