/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2013, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.spring.ctx; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.core.io.Resource; import org.springframework.util.ReflectionUtils; /** * <p>Title: NamedGenericXmlApplicationContext</p> * <p>Description: An extension of {@link GenericXmlApplicationContext} that supports a settable and gettable application name</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.spring.ctx.NamedGenericXmlApplicationContext</code></p> */ public class NamedGenericXmlApplicationContext extends GenericXmlApplicationContext { /** The app name for this context */ protected String applicationName = null; /** App logger */ protected final Logger log = Logger.getLogger(getClass()); /** * Creates a new NamedGenericXmlApplicationContext */ public NamedGenericXmlApplicationContext() { } /** * Creates a new NamedGenericXmlApplicationContext * @param resources */ public NamedGenericXmlApplicationContext(Resource... resources) { super(resources); } /** * Creates a new NamedGenericXmlApplicationContext * @param resourceLocations */ public NamedGenericXmlApplicationContext(String... resourceLocations) { super(resourceLocations); } /** * Creates a new NamedGenericXmlApplicationContext * @param relativeClass * @param resourceNames */ public NamedGenericXmlApplicationContext(Class<?> relativeClass, String... resourceNames) { super(relativeClass, resourceNames); } /** * Sets the application context app name for this context * @param name the application context app name for this context */ public void setApplicationName(String name) { this.applicationName = name; } /** * {@inheritDoc} * @see org.springframework.context.support.AbstractApplicationContext#getApplicationName() */ @Override public String getApplicationName() { return applicationName; } // protected Map<Object, String> getTriggerInitMethods(Set<Object> triggerBeans) { // if(triggerBeans.isEmpty()) return Collections.emptyMap(); // Map<Object, String> triggerMethods = new HashMap<Object, String>(triggerBeans.size()); // for(String beanName: getBeanDefinitionNames()) { // if(triggerBeans.contains(getBean(beanName))) { // BeanDefinition beanDef = getBeanDefinition(beanName); // beanDef. // } // } // } /** * {@inheritDoc} * @see org.springframework.context.support.AbstractApplicationContext#finishRefresh() */ @Override protected void finishRefresh() { log.info("\n\t#########################\n\tFiring OnRefresh Triggers\n\t#########################\n"); int invocations = 0; AppContextRefreshTriggers triggers = new AppContextRefreshTriggers(); getAutowireCapableBeanFactory().autowireBean(triggers); log.info("Located [" + triggers.getRefreshTriggers().size() + "] qualified triggers"); Set<Object> triggerBeans = triggers.getRefreshTriggers(); Map<String, Object> beans = getBeansWithAnnotation(OnRefresh.class); for(Object trigger: triggerBeans) { beans.put(trigger.getClass().getSimpleName() + "@" + System.identityHashCode(trigger), trigger); } try { for(Map.Entry<String, Object> entry: beans.entrySet()) { log.info("Firing OnRefresh Bean [" + entry.getKey() + "]"); if(entry.getValue().getClass().getAnnotation(OnRefresh.class)==null) { try { ReflectionUtils.invokeMethod(ReflectionUtils.findMethod(entry.getValue().getClass(), "start"), entry.getValue()); } catch (Exception ex) { log.warn("failed to invoke start on trigger bean [" + entry.getValue()+ "]", ex); } continue; } for(Method method: ReflectionUtils.getUniqueDeclaredMethods(entry.getValue().getClass())) { if(method.getAnnotation(OnRefresh.class)!=null) { if(method.getParameterTypes().length>0) continue; if(!method.isAccessible()) { method.setAccessible(true); } log.info("Invoking OnRefresh Method [" + method.getDeclaringClass().getSimpleName() + "." + method.getName() + "]"); if(Modifier.isStatic(method.getModifiers())) { method.invoke(null); } else { method.invoke(entry.getValue()); } invocations++; } } } } catch (Exception ex) { log.error("Failed to fire onRefresh Triggers", ex); throw new RuntimeException("Failed to fire onRefresh Triggers", ex); } log.info("\n\t#########################\n\tFired [" + invocations + "] OnRefresh Triggers\n\t#########################\n"); super.finishRefresh(); } }