/* * Copyright 2002-2016 the original author or authors. * * 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 org.springframework.integration.config; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ApplicationContextEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.messaging.MessageHeaders; import org.springframework.util.IdGenerator; import org.springframework.util.ReflectionUtils; /** * @author Oleg Zhurakousky * @author Mark Fisher * @author Gary Russell * @since 2.0.4 */ public final class IdGeneratorConfigurer implements ApplicationListener<ApplicationContextEvent> { private static final Set<String> generatorContextId = new HashSet<String>(); private static volatile IdGenerator theIdGenerator; private final Log logger = LogFactory.getLog(getClass()); public synchronized void onApplicationEvent(ApplicationContextEvent event) { ApplicationContext context = event.getApplicationContext(); if (event instanceof ContextRefreshedEvent) { boolean contextHasIdGenerator = context.getBeanNamesForType(IdGenerator.class).length > 0; if (contextHasIdGenerator) { if (this.setIdGenerator(context)) { IdGeneratorConfigurer.generatorContextId.add(context.getId()); } } } else if (event instanceof ContextClosedEvent) { if (IdGeneratorConfigurer.generatorContextId.contains(context.getId())) { if (IdGeneratorConfigurer.generatorContextId.size() == 1) { this.unsetIdGenerator(); } IdGeneratorConfigurer.generatorContextId.remove(context.getId()); } } } private boolean setIdGenerator(ApplicationContext context) { try { IdGenerator idGeneratorBean = context.getBean(IdGenerator.class); if (this.logger.isDebugEnabled()) { this.logger.debug("using custom MessageHeaders.IdGenerator [" + idGeneratorBean.getClass() + "]"); } Field idGeneratorField = ReflectionUtils.findField(MessageHeaders.class, "idGenerator"); ReflectionUtils.makeAccessible(idGeneratorField); IdGenerator currentIdGenerator = (IdGenerator) ReflectionUtils.getField(idGeneratorField, null); if (currentIdGenerator != null) { if (currentIdGenerator.equals(idGeneratorBean)) { // same instance is already set, nothing needs to be done return false; } else { if (IdGeneratorConfigurer.theIdGenerator.getClass() == idGeneratorBean.getClass()) { if (this.logger.isWarnEnabled()) { this.logger.warn("Another instance of " + idGeneratorBean.getClass() + " has already been established; ignoring"); } return true; } else { // different instance has been set, not legal throw new BeanDefinitionStoreException("'MessageHeaders.idGenerator' has already been set and can not be set again"); } } } if (this.logger.isInfoEnabled()) { this.logger.info("Message IDs will be generated using custom IdGenerator [" + idGeneratorBean.getClass() + "]"); } ReflectionUtils.setField(idGeneratorField, null, idGeneratorBean); IdGeneratorConfigurer.theIdGenerator = idGeneratorBean; } catch (NoSuchBeanDefinitionException e) { // No custom IdGenerator. We will use the default. int idBeans = context.getBeansOfType(IdGenerator.class).size(); if (idBeans > 1 && this.logger.isWarnEnabled()) { this.logger.warn("Found too many 'IdGenerator' beans (" + idBeans + ") " + "Will use the existing UUID strategy."); } else if (this.logger.isDebugEnabled()) { this.logger.debug("Unable to locate MessageHeaders.IdGenerator. Will use the existing UUID strategy."); } return false; } catch (IllegalStateException e) { // thrown from ReflectionUtils if (this.logger.isWarnEnabled()) { this.logger.warn("Unexpected exception occurred while accessing idGenerator of MessageHeaders." + " Will use the existing UUID strategy.", e); } return false; } return true; } private void unsetIdGenerator() { try { Field idGeneratorField = ReflectionUtils.findField(MessageHeaders.class, "idGenerator"); ReflectionUtils.makeAccessible(idGeneratorField); idGeneratorField.set(null, null); IdGeneratorConfigurer.theIdGenerator = null; } catch (Exception e) { if (this.logger.isWarnEnabled()) { this.logger.warn("Unexpected exception occurred while accessing idGenerator of MessageHeaders.", e); } } } }