/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* 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 alma.acs.monitoring;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import alma.acs.monitoring.DynamicInterceptor.InterceptionHandler;
import alma.acs.monitoring.DynamicInterceptor.InterceptionHandlerFactory;
import alma.acs.util.StopWatch;
/**
* Uses {@link DynamicInterceptor} to intercept and log calls to an interface.
* @author hsommer
*/
public class SimpleCallInterceptor
{
/**
* Calls {@link DynamicInterceptor#createDynamicInterceptor(Class, Object, Logger, ClassLoader, InterceptionHandlerFactory)},
* using {@link SimpleInterceptionHandler} objects to handle (log) the intercepted calls.
*/
public static <T> T createSimpleInterceptor(Class<T> corbaInterface, T delegate, Logger logger)
{
InterceptionHandlerFactory interceptionHandlerFactory =
new SimpleInterceptionHandlerFactory(logger);
return DynamicInterceptor.createDynamicInterceptor(corbaInterface, delegate, logger, null, interceptionHandlerFactory);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Callbacks for Dynamic Interceptor //////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
/**
* The handler created for every call to the DAL or DAO (with lightweight implementation).
* Will log method invocation and return.
*/
private static class SimpleInterceptionHandler implements DynamicInterceptor.InterceptionHandler {
private final Logger logger;
private final Level logLevel = Level.FINER;
private StopWatch methodInvWatch;
/**
* Whether the call should be logged (because of level or suppressed logging for the given interface method).
*/
private boolean isLoggable = false;
/**
* The method that was called
*/
private Method method;
SimpleInterceptionHandler(Logger logger) {
this.logger = logger;
}
@Override
public boolean callReceived(Method method, Object[] args) {
this.method = method;
isLoggable = logger.isLoggable(logLevel);
if (isLoggable) {
methodInvWatch = new StopWatch(logger);
logger.log(logLevel, "intercepted a call to '" + method.getName() + "'.");
}
return true;
}
@Override
public Object callFinished(Object retVal, Object[] args, Throwable realThr) throws Throwable {
// log invocation time
if (isLoggable) {
String msg = "returning from " + method.getName() + " after " + methodInvWatch.getLapTimeMillis() + " ms. ";
if (realThr != null) {
msg += realThr.getClass().getSimpleName() + " was thrown."; // TODO log more exception details if needed.
}
logger.log(logLevel, msg);
}
if (realThr != null) {
throw realThr;
}
return retVal;
}
}
/**
*
*/
private static class SimpleInterceptionHandlerFactory implements DynamicInterceptor.InterceptionHandlerFactory {
private final Logger logger;
SimpleInterceptionHandlerFactory(Logger logger) {
this.logger = logger;
}
@Override
public InterceptionHandler createInterceptionHandler() {
return new SimpleInterceptionHandler(logger);
}
}
}