/* * Copyright: (c) 2004-2011 Mayo Foundation for Medical Education and * Research (MFMER). All rights reserved. MAYO, MAYO CLINIC, and the * triple-shield Mayo logo are trademarks and service marks of MFMER. * * Except as contained in the copyright notice above, or as used to identify * MFMER as the author of this software, the trade names, trademarks, service * marks, or product names of the copyright holder shall not be used in * advertising, promotion or otherwise in connection with this software without * prior written authorization of the copyright holder. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.mayo.cts2.framework.webapp.service; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import javax.annotation.Resource; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.InitializingBean; import edu.mayo.cts2.framework.service.profile.Cts2Profile; import edu.mayo.cts2.framework.service.provider.ServiceProvider; import edu.mayo.cts2.framework.service.provider.ServiceProviderChangeObserver; import edu.mayo.cts2.framework.service.provider.ServiceProviderFactory; /** * The Class AbstractServiceAwareController. * * @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a> */ public class AbstractServiceAwareBean implements InitializingBean, ServiceProviderChangeObserver { private static Log log = LogFactory .getLog(AbstractServiceAwareBean.class); @Resource private ServiceProviderFactory serviceProviderFactory; /** * The Interface Cts2Service. * * @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a> */ @Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) public @interface Cts2Service { } /* * (non-Javadoc) * * @see * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public final void afterPropertiesSet() throws Exception { this.serviceProviderFactory.registerListener(this); this.loadServices(); this.doInitialize(); } protected void doInitialize(){ //no-op } protected <T extends Cts2Profile> T getCts2Service(Class<T> clazz){ ServiceProvider provider = this.serviceProviderFactory.getServiceProvider(); return provider.getService(clazz); } /** * Load services. */ protected void loadServices() { for (Field field : this.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(Cts2Service.class)) { @SuppressWarnings("unchecked") final Class<? extends Cts2Profile> clazz = (Class<? extends Cts2Profile>) field .getType(); Cts2Profile service = ProxyFactory.getProxy(clazz, new MethodInterceptor(){ @Override public Object invoke(MethodInvocation method) throws Throwable { ServiceProvider retrievedServiceProvider = serviceProviderFactory.getServiceProvider(); Cts2Profile retrievedService; if (retrievedServiceProvider == null) { throw new UnsupportedOperationException("This service is not implemented."); } else { retrievedService = retrievedServiceProvider.getService(clazz); if(retrievedService == null){ throw new UnsupportedOperationException("This service is not implemented."); } } try { return method.getMethod() .invoke(retrievedService, method.getArguments()); } catch (InvocationTargetException e) { throw e.getCause(); } } }); if(service == null){ service = proxyNullService(clazz); } field.setAccessible(true); try { field.set(this, service); } catch (Exception e) { throw new IllegalStateException(e); } log.info("Setting service: " + field.getType() + " on: " + this.getClass().getName()); } } } @SuppressWarnings("unchecked") protected <T extends Cts2Profile> T proxyNullService(Class<T> serviceClass){ ProxyFactory factory = new ProxyFactory(serviceClass, nullServiceMethodInterceptor); return (T) factory.getProxy(); } protected MethodInterceptor nullServiceMethodInterceptor = new MethodInterceptor() { @Override public Object invoke(MethodInvocation invocation) throws Throwable { throw new UnsupportedOperationException("This service is not implemented."); } }; @Override public void onServiceProviderChange() { this.loadServices(); } protected ServiceProviderFactory getServiceProviderFactory() { return serviceProviderFactory; } protected void setServiceProviderFactory( ServiceProviderFactory serviceProviderFactory) { this.serviceProviderFactory = serviceProviderFactory; } }