org.eclipse.gemini.blueprint.blueprint.container.support.internal.config.CycleOrderingProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gemini.blueprint.blueprint.container.support.internal.config.CycleOrderingProcessor.java

Source

/******************************************************************************
 * Copyright (c) 2006, 2010 VMware Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution. 
 * The Eclipse Public License is available at 
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
 * is available at http://www.opensource.org/licenses/apache2.0.php.
 * You may elect to redistribute this code under either of these licenses. 
 * 
 * Contributors:
 *   VMware Inc.
 *****************************************************************************/

package org.eclipse.gemini.blueprint.blueprint.container.support.internal.config;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.blueprint.config.internal.ParsingUtils;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.core.Ordered;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * Simple processor for sorting out cycles between beans. Inspects the construction relationship between beans to
 * provide hints to the container. Specifically, it forces the creation of any beans referred inside the construction
 * through the 'depends-on' attribute on the inspected bean.
 * 
 * @author Costin Leau
 */
public class CycleOrderingProcessor implements BeanFactoryPostProcessor, Ordered {

    public static final String SYNTHETIC_DEPENDS_ON = "org.eclipse.gemini.blueprint.blueprint.container.support.internal.config.dependson";

    /** logger */
    private static final Log log = LogFactory.getLog(CycleOrderingProcessor.class);

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        boolean trace = log.isTraceEnabled();

        String[] names = beanFactory.getBeanDefinitionNames();
        for (String name : names) {
            BeanDefinition definition = beanFactory.getBeanDefinition(name);
            if (definition.hasAttribute(ParsingUtils.BLUEPRINT_MARKER_NAME)) {
                ConstructorArgumentValues cArgs = definition.getConstructorArgumentValues();
                if (trace)
                    log.trace("Inspecting cycles for (blueprint) bean " + name);

                tag(cArgs.getGenericArgumentValues(), name, definition);
                tag(cArgs.getIndexedArgumentValues().values(), name, definition);
            }
        }
    }

    private void tag(Collection<ValueHolder> values, String name, BeanDefinition definition) {
        boolean trace = log.isTraceEnabled();

        for (ValueHolder value : values) {
            Object val = value.getValue();
            if (val instanceof BeanMetadataElement) {
                if (val instanceof RuntimeBeanReference) {
                    String beanName = ((RuntimeBeanReference) val).getBeanName();

                    if (trace) {
                        log.trace("Adding (cycle breaking) depends-on on " + name + " to " + beanName);
                    }

                    addSyntheticDependsOn(definition, beanName);
                }
            }
        }
    }

    private void addSyntheticDependsOn(BeanDefinition definition, String beanName) {
        if (StringUtils.hasText(beanName)) {
            String[] dependsOn = definition.getDependsOn();
            if (dependsOn != null && dependsOn.length > 0) {
                for (String dependOn : dependsOn) {
                    if (beanName.equals(dependOn)) {
                        return;
                    }
                }
            }

            // add depends on
            dependsOn = (String[]) ObjectUtils.addObjectToArray(dependsOn, beanName);
            definition.setDependsOn(dependsOn);
            Collection<String> markers = (Collection<String>) definition.getAttribute(SYNTHETIC_DEPENDS_ON);
            if (markers == null) {
                markers = new ArrayList<String>(2);
                definition.setAttribute(SYNTHETIC_DEPENDS_ON, markers);
            }
            markers.add(beanName);
        }
    }

    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}