package org.oddjob.framework; import java.beans.ExceptionListener; import java.lang.reflect.Method; import org.oddjob.FailedToStopException; import org.oddjob.arooa.ArooaAnnotations; import org.oddjob.arooa.ArooaBeanDescriptor; import org.oddjob.arooa.ArooaSession; import org.oddjob.arooa.reflect.PropertyAccessor; /** * A collection of different strategies that are applied to a component * to see if it can be adapted to a {@link Service}. * * @author rob * */ public class ServiceStrategies implements ServiceStrategy { @Override public ServiceAdaptor serviceFor(Object component, ArooaSession session) { ServiceAdaptor adaptor = new IsServiceAlreadyStrategy().serviceFor( component, session); if (adaptor == null) { adaptor = new HasServiceAnnotationsStrategy().serviceFor( component, session); } if (adaptor == null) { adaptor = new HasServiceMethodsStrategy().serviceFor( component, session); } return adaptor; } /** * Provides a strategy that checks to see if the component is a * {@link Service} already. * */ public static class IsServiceAlreadyStrategy implements ServiceStrategy { @Override public ServiceAdaptor serviceFor(Object component, ArooaSession session) { if (component instanceof Service) { final Service service = (Service) component; return new ServiceAdaptor() { @Override public void start() throws Exception { service.start(); } @Override public void stop() throws FailedToStopException { service.stop(); } @Override public Object getComponent() { return service; } @Override public void acceptExceptionListener( ExceptionListener exceptionListener) { if (service instanceof AsynchronousJob) { ((AsynchronousJob) service ).acceptExceptionListener( exceptionListener); } } }; } else { return null; } } } public static class HasServiceMethodsStrategy implements ServiceStrategy { @Override public ServiceMethodAdaptor serviceFor(Object component, ArooaSession session) { Class<?> cl = component.getClass(); try { Method startMethod = cl.getDeclaredMethod( "start", new Class[0]); if (startMethod.getReturnType() != Void.TYPE) { return null; } Method stopMethod = cl.getDeclaredMethod( "stop", new Class[0]); if (startMethod.getReturnType() != Void.TYPE) { return null; } return new ServiceMethodAdaptor( component, startMethod, stopMethod); } catch (Exception e) { return null; } } } public static class HasServiceAnnotationsStrategy implements ServiceStrategy { @Override public ServiceAdaptor serviceFor(Object component, ArooaSession session) { PropertyAccessor accessor = session.getTools().getPropertyAccessor(); ArooaBeanDescriptor beanDescriptor = session.getArooaDescriptor().getBeanDescriptor( accessor.getClassName(component), accessor); ArooaAnnotations annotations = beanDescriptor.getAnnotations(); Method startMethod = annotations.methodFor( Start.class.getName()); Method stopMethod = annotations.methodFor( Stop.class.getName()); Method exceptionMethod = annotations.methodFor( AcceptExceptionListener.class.getName()); if (startMethod == null && stopMethod == null) { return null; } if (startMethod != null && stopMethod != null) { return new ServiceMethodAdaptor( component, startMethod, stopMethod, exceptionMethod); } throw new IllegalStateException( "Class " + component.getClass().getName() + " must have both a @Start and a @Stop method annoted."); } } }