/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.aries.blueprint.container;

import static org.apache.aries.blueprint.utils.ReflectionUtils.getRealCause;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.aries.blueprint.BeanProcessor;
import org.apache.aries.blueprint.ComponentDefinitionRegistry;
import org.apache.aries.blueprint.ExtendedBlueprintContainer;
import org.apache.aries.blueprint.Interceptor;
import org.apache.aries.blueprint.di.AbstractRecipe;
import org.apache.aries.blueprint.di.Recipe;
import org.apache.aries.blueprint.proxy.AsmInterceptorWrapper;
import org.apache.aries.blueprint.proxy.CgLibInterceptorWrapper;
import org.apache.aries.blueprint.utils.ReflectionUtils;
import org.apache.aries.blueprint.utils.ReflectionUtils.PropertyDescriptor;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.container.ReifiedType;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A <code>Recipe</code> to create POJOs.
 *
 * @version $Rev: 978875 $, $Date: 2010-07-24 14:45:05 +0100 (Sat, 24 Jul 2010) $
 */
public class BeanRecipe extends AbstractRecipe {

    private static final Logger LOGGER = LoggerFactory.getLogger(BeanRecipe.class);

    private final ExtendedBlueprintContainer blueprintContainer;
    private final LinkedHashMap<String,Object> properties = new LinkedHashMap<String,Object>();
    private final Object type;

    private String initMethod;
    private String destroyMethod;
    private List<Recipe> explicitDependencies;
    
    private Recipe factory;
    private String factoryMethod;
    private List<Object> arguments;
    private List<String> argTypes;
    private boolean reorderArguments;
    private final boolean allowsFieldInjection;
    private BeanMetadata interceptorLookupKey;
    

    public BeanRecipe(String name, ExtendedBlueprintContainer blueprintContainer, Object type, boolean allowsFieldInjection) {
        super(name);
        this.blueprintContainer = blueprintContainer;
        this.type = type;
        this.allowsFieldInjection = allowsFieldInjection;
    }

    public Object getProperty(String name) {
        return properties.get(name);
    }

    public Map<String, Object> getProperties() {
        return new LinkedHashMap<String, Object>(properties);
    }

    public void setProperty(String name, Object value) {
        properties.put(name, value);
    }

    public void setFactoryMethod(String method) {
        this.factoryMethod = method;
    }
    
    public void setFactoryComponent(Recipe factory) {
        this.factory = factory;
    }
    
    public void setArgTypes(List<String> argTypes) {
        this.argTypes = argTypes;
    }
    
    public void setArguments(List<Object> arguments) {
        this.arguments = arguments;
    }
    
    public void setReorderArguments(boolean reorder) {
        this.reorderArguments = reorder;
    }
    
    public void setInitMethod(String initMethod) {
        this.initMethod = initMethod;
    }
    
    public String getInitMethod() {
        return initMethod;
    }
    
    public void setDestroyMethod(String destroyMethod) {
        this.destroyMethod = destroyMethod;
    }
    
    public String getDestroyMethod() {
        return destroyMethod;
    }

    public List<Recipe> getExplicitDependencies() {
        return explicitDependencies;
    }

    public void setExplicitDependencies(List<Recipe> explicitDependencies) {
        this.explicitDependencies = explicitDependencies;
    }

    public void setInterceptorLookupKey(BeanMetadata metadata) {
    	interceptorLookupKey = metadata;
    }
    
    @Override
    public List<Recipe> getConstructorDependencies() {
        List<Recipe> recipes = new ArrayList<Recipe>();
        if (explicitDependencies != null) {
            recipes.addAll(explicitDependencies);
        }
        if (arguments != null) {
            for (Object argument : arguments) {
                if (argument instanceof Recipe) {
                    recipes.add((Recipe)argument);
                }
            }
        }
        return recipes;
    }
    
    public List<Recipe> getDependencies() {
        List<Recipe> recipes = new ArrayList<Recipe>();
        for (Object o : properties.values()) {
            if (o instanceof Recipe) {
                Recipe recipe = (Recipe) o;
                recipes.add(recipe);
            }
        }
        recipes.addAll(getConstructorDependencies());
        return recipes; 
    }

    private void instantiateExplicitDependencies() {
        if (explicitDependencies != null) {
            for (Recipe recipe : explicitDependencies) {
                recipe.create();
            }
        }
    }

    @Override
    protected Class loadClass(String className) {
        ClassLoader loader = type instanceof Class ? ((Class) type).getClassLoader() : null;
        ReifiedType t = loadType(className, loader);
        return t != null ? t.getRawClass() : null;
    }

    @Override
    protected ReifiedType loadType(String className) {
        return loadType(className, type instanceof Class ? ((Class) type).getClassLoader() : null);
    }

    private Object getInstance() throws ComponentDefinitionException {
        Object instance;
        
        // Instanciate arguments
        List<Object> args = new ArrayList<Object>();
        List<ReifiedType> argTypes = new ArrayList<ReifiedType>();
        if (arguments != null) {
            for (int i = 0; i < arguments.size(); i++) {
                Object arg = arguments.get(i);
                if (arg instanceof Recipe) {
                    args.add(((Recipe) arg).create());
                } else {
                    args.add(arg);
                }
                if (this.argTypes != null) {
                    argTypes.add(this.argTypes.get(i) != null ? loadType(this.argTypes.get(i)) : null);
                }
            }
        }

        if (factory != null) {
            // look for instance method on factory object
            Object factoryObj = factory.create();
            
            // If the factory is a service reference, we need to get hold of the actual proxy for the service
            if (factoryObj instanceof ReferenceRecipe.ServiceProxyWrapper) {
                try {
                    factoryObj = ((ReferenceRecipe.ServiceProxyWrapper) factoryObj).convert(new ReifiedType(Object.class));
                } catch (Exception e) {
                    throw new ComponentDefinitionException("Error when instantiating bean " + getName() + " of class " + getType(), getRealCause(e));
                }
            }
            
            // Map of matching methods
            Map<Method, List<Object>> matches = findMatchingMethods(factoryObj.getClass(), factoryMethod, true, args, argTypes);
            if (matches.size() == 1) {
                try {
                    Map.Entry<Method, List<Object>> match = matches.entrySet().iterator().next();
                    instance = invoke(match.getKey(), factoryObj, match.getValue().toArray());
                } catch (Throwable e) {
                    throw new ComponentDefinitionException("Error when instantiating bean " + getName() + " of class " + getType(), getRealCause(e));
                }
            } else if (matches.size() == 0) {
                throw new ComponentDefinitionException("Unable to find a matching factory method " + factoryMethod + " on class " + factoryObj.getClass().getName() + " for arguments " + args + " when instanciating bean " + getName());
            } else {
                throw new ComponentDefinitionException("Multiple matching factory methods " + factoryMethod + " found on class " + factoryObj.getClass().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
            }
        } else if (factoryMethod != null) {
            // Map of matching methods
            Map<Method, List<Object>> matches = findMatchingMethods(getType(), factoryMethod, false, args, argTypes);
            if (matches.size() == 1) {
                try {
                    Map.Entry<Method, List<Object>> match = matches.entrySet().iterator().next();
                    instance = invoke(match.getKey(), null, match.getValue().toArray());
                } catch (Throwable e) {
                    throw new ComponentDefinitionException("Error when instanciating bean " + getName() + " of class " + getType(), getRealCause(e));
                }
            } else if (matches.size() == 0) {
                throw new ComponentDefinitionException("Unable to find a matching factory method " + factoryMethod + " on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName());
            } else {
                throw new ComponentDefinitionException("Multiple matching factory methods " + factoryMethod + " found on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
            }
        } else {
            if (getType() == null) {
                throw new ComponentDefinitionException("No factoryMethod nor class is defined for this bean");
            }
            // Map of matching constructors
            Map<Constructor, List<Object>> matches = findMatchingConstructors(getType(), args, argTypes);
            if (matches.size() == 1) {
                try {
                    Map.Entry<Constructor, List<Object>> match = matches.entrySet().iterator().next();
                    instance = newInstance(match.getKey(), match.getValue().toArray());
                } catch (Throwable e) {
                    throw new ComponentDefinitionException("Error when instanciating bean " + getName() + " of class " + getType(), getRealCause(e));
                }
            } else if (matches.size() == 0) {
                throw new ComponentDefinitionException("Unable to find a matching constructor on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName());
            } else {
                throw new ComponentDefinitionException("Multiple matching constructors found on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
            }
        }
        
        return instance;
    }

    private Map<Method, List<Object>> findMatchingMethods(Class type, String name, boolean instance, List<Object> args, List<ReifiedType> types) {
        Map<Method, List<Object>> matches = new HashMap<Method, List<Object>>();
        // Get constructors
        List<Method> methods = new ArrayList<Method>(Arrays.asList(type.getMethods()));
        // Discard any signature with wrong cardinality
        for (Iterator<Method> it = methods.iterator(); it.hasNext();) {
            Method mth = it.next();
            if (!mth.getName().equals(name)) {
                it.remove();
            } else if (mth.getParameterTypes().length != args.size()) {
                it.remove();
            } else if (instance ^ !Modifier.isStatic(mth.getModifiers())) {
                it.remove();
            } else if (mth.isBridge()) {
                it.remove();
            }
        }
        
        // on some JVMs (J9) hidden static methods are returned by Class.getMethods so we need to weed them out
        // to reduce ambiguity
        if (!instance) {
        	methods = applyStaticHidingRules(methods);
        }
        
        // Find a direct match with assignment
        if (matches.size() != 1) {
            Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
            for (Method mth : methods) {
                boolean found = true;
                List<Object> match = new ArrayList<Object>();
                for (int i = 0; i < args.size(); i++) {
                    ReifiedType argType = new GenericType(mth.getGenericParameterTypes()[i]);
                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
                        found = false;
                        break;
                    }
                    if (!AggregateConverter.isAssignable(args.get(i), argType)) {
                        found = false;
                        break;
                    }
                    try {
                        match.add(convert(args.get(i), mth.getGenericParameterTypes()[i]));
                    } catch (Throwable t) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    nmatches.put(mth, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Find a direct match with conversion
        if (matches.size() != 1) {
            Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
            for (Method mth : methods) {
                boolean found = true;
                List<Object> match = new ArrayList<Object>();
                for (int i = 0; i < args.size(); i++) {
                    ReifiedType argType = new GenericType(mth.getGenericParameterTypes()[i]);
                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
                        found = false;
                        break;
                    }
                    try {
                        Object val = convert(args.get(i), argType);
                        match.add(val);
                    } catch (Throwable t) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    nmatches.put(mth, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Start reordering with assignment
        if (matches.size() != 1 && reorderArguments && args.size() > 1) {
            Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
            for (Method mth : methods) {
                ArgumentMatcher matcher = new ArgumentMatcher(mth.getGenericParameterTypes(), false);
                List<Object> match = matcher.match(args, types);
                if (match != null) {
                    nmatches.put(mth, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Start reordering with conversion
        if (matches.size() != 1 && reorderArguments && args.size() > 1) {
            Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
            for (Method mth : methods) {
                ArgumentMatcher matcher = new ArgumentMatcher(mth.getGenericParameterTypes(), true);
                List<Object> match = matcher.match(args, types);
                if (match != null) {
                    nmatches.put(mth, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        
        return matches;
    }
    
    private static List<Method> applyStaticHidingRules(Collection<Method> methods) {
    	List<Method> result = new ArrayList<Method>(methods.size());
    	for (Method m : methods) {
    		boolean toBeAdded = true;

    		Iterator<Method> it = result.iterator();
    		inner: while (it.hasNext()) {
    			Method other = it.next();
    			if (hasIdenticalParameters(m, other)) {
    				Class<?> mClass = m.getDeclaringClass();
    				Class<?> otherClass = other.getDeclaringClass();
    				
    				if (mClass.isAssignableFrom(otherClass)) {
    					toBeAdded = false;
    					break inner;
    				} else if (otherClass.isAssignableFrom(mClass)) {
    					it.remove();
    				}
    			}
    		}
    		
    		if (toBeAdded) result.add(m);
    	}
    	
    	return result;
    }
    
    private static boolean hasIdenticalParameters(Method one, Method two) {
		Class<?>[] oneTypes = one.getParameterTypes();
		Class<?>[] twoTypes = two.getParameterTypes();
    	
		if (oneTypes.length != twoTypes.length) return false;
		
		for (int i=0; i<oneTypes.length; i++) {
			if (!oneTypes[i].equals(twoTypes[i])) return false;
		}
		
		return true;
    }

    private Map<Constructor, List<Object>> findMatchingConstructors(Class type, List<Object> args, List<ReifiedType> types) {
        Map<Constructor, List<Object>> matches = new HashMap<Constructor, List<Object>>();
        // Get constructors
        List<Constructor> constructors = new ArrayList<Constructor>(Arrays.asList(type.getConstructors()));
        // Discard any signature with wrong cardinality
        for (Iterator<Constructor> it = constructors.iterator(); it.hasNext();) {
            if (it.next().getParameterTypes().length != args.size()) {
                it.remove();
            }
        }
        // Find a direct match with assignment
        if (matches.size() != 1) {
            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
            for (Constructor cns : constructors) {
                boolean found = true;
                List<Object> match = new ArrayList<Object>();
                for (int i = 0; i < args.size(); i++) {
                    ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
                        found = false;
                        break;
                    }
                    if (!AggregateConverter.isAssignable(args.get(i), argType)) {
                        found = false;
                        break;
                    }
                    try {
                        match.add(convert(args.get(i), cns.getGenericParameterTypes()[i]));
                    } catch (Throwable t) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    nmatches.put(cns, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Find a direct match with conversion
        if (matches.size() != 1) {
            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
            for (Constructor cns : constructors) {
                boolean found = true;
                List<Object> match = new ArrayList<Object>();
                for (int i = 0; i < args.size(); i++) {
                    ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
                        found = false;
                        break;
                    }
                    try {
                        Object val = convert(args.get(i), argType);
                        match.add(val);
                    } catch (Throwable t) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    nmatches.put(cns, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Start reordering with assignment
        if (matches.size() != 1 && reorderArguments && arguments.size() > 1) {
            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
            for (Constructor cns : constructors) {
                ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), false);
                List<Object> match = matcher.match(args, types);
                if (match != null) {
                    nmatches.put(cns, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        // Start reordering with conversion
        if (matches.size() != 1 && reorderArguments && arguments.size() > 1) {
            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
            for (Constructor cns : constructors) {
                ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), true);
                List<Object> match = matcher.match(args, types);
                if (match != null) {
                    nmatches.put(cns, match);
                }
            }
            if (nmatches.size() > 0) {
                matches = nmatches;
            }
        }
        return matches;
    }

    /**
     * Returns init method (if any). Throws exception if the init-method was set explicitly on the bean
     * and the method is not found on the instance.
     */
    protected Method getInitMethod(Object instance) throws ComponentDefinitionException {
        Method method = null;        
        if (initMethod != null && initMethod.length() > 0) {
            method = ReflectionUtils.getLifecycleMethod(instance.getClass(), initMethod);
            if (method == null) {
                throw new ComponentDefinitionException("Component '" + getName() + "' does not have init-method: " + initMethod);
            }
        }
        return method;
    }

    /**
     * Returns destroy method (if any). Throws exception if the destroy-method was set explicitly on the bean
     * and the method is not found on the instance.
     */
    public Method getDestroyMethod(Object instance) throws ComponentDefinitionException {
        Method method = null;        
        if (destroyMethod != null && destroyMethod.length() > 0) {
            method = ReflectionUtils.getLifecycleMethod(instance.getClass(), destroyMethod);
            if (method == null) {
                throw new ComponentDefinitionException("Component '" + getName() + "' does not have destroy-method: " + destroyMethod);
            }
        }
        return method;
    }
    
    /**
     * Small helper class, to construct a chain of BeanCreators.
     * <br> 
     * Each bean creator in the chain will return a bean that has been 
     * processed by every BeanProcessor in the chain before it.
     */
    private static class BeanCreatorChain implements BeanProcessor.BeanCreator {
        public enum ChainType{Before,After};
        private BeanProcessor.BeanCreator parentBeanCreator;
        private BeanProcessor parentBeanProcessor;
        private BeanMetadata beanData;
        private String beanName;        
        private ChainType when;
        public BeanCreatorChain(BeanProcessor.BeanCreator parentBeanCreator, 
                                BeanProcessor parentBeanProcessor,
                                BeanMetadata beanData,
                                String beanName,
                                ChainType when){
            this.parentBeanCreator = parentBeanCreator;
            this.parentBeanProcessor = parentBeanProcessor;
            this.beanData = beanData;
            this.beanName = beanName;
            this.when = when;
        }

        public Object getBean() {
            Object previousBean = parentBeanCreator.getBean();
            Object processed = null;
            switch(when){
                case Before :
                  processed = parentBeanProcessor.beforeInit(previousBean, beanName, parentBeanCreator, beanData);
                  break;
                case After:
                  processed = parentBeanProcessor.afterInit(previousBean, beanName, parentBeanCreator, beanData);
                  break;
            }
            return processed;
        }   
    }
    
    private Object runBeanProcPreInit(Object obj){
        String beanName = getName();
        BeanMetadata beanData = (BeanMetadata) blueprintContainer
          .getComponentDefinitionRegistry().getComponentDefinition(beanName);        
        List<BeanProcessor> processors = blueprintContainer.getProcessors(BeanProcessor.class);
        
        //The start link of the chain, that provides the 
        //original, unprocessed bean to the head of the chain.
        BeanProcessor.BeanCreator initialBeanCreator = new BeanProcessor.BeanCreator() {            
            public Object getBean() {
                Object obj = getInstance();
                //getinit, getdestroy, addpartial object don't need calling again.
                //however, property injection does.
                setProperties(obj);
                return obj;
            }
        };

        BeanProcessor.BeanCreator currentCreator = initialBeanCreator;
        for(BeanProcessor processor : processors){
            obj = processor.beforeInit(obj, getName(), currentCreator, beanData);
            currentCreator = new BeanCreatorChain(currentCreator, processor, beanData, beanName, BeanCreatorChain.ChainType.Before);
        }
        return obj;
    }
    
    private void runBeanProcInit(Method initMethod, Object obj){
        // call init method
        if (initMethod != null) {
            try {
                invoke(initMethod, obj, (Object[]) null);
            } catch (Throwable t) {
                throw new ComponentDefinitionException("Unable to intialize bean " + getName(), getRealCause(t));
            }
        }   
    }
    
    private Object runBeanProcPostInit(Object obj){
        String beanName = getName();
        BeanMetadata beanData = (BeanMetadata) blueprintContainer
          .getComponentDefinitionRegistry().getComponentDefinition(beanName);        
        List<BeanProcessor> processors = blueprintContainer.getProcessors(BeanProcessor.class);
        
        //The start link of the chain, that provides the 
        //original, unprocessed bean to the head of the chain.
        BeanProcessor.BeanCreator initialBeanCreator = new BeanProcessor.BeanCreator() {            
            public Object getBean() {                                
                Object obj = getInstance();
                //getinit, getdestroy, addpartial object don't need calling again.
                //however, property injection does.
                setProperties(obj);
                //as this is the post init chain, new beans need to go thru 
                //the pre-init chain, and then have init called, before 
                //being passed along the post-init chain.
                obj = runBeanProcPreInit(obj);
                runBeanProcInit(getInitMethod(obj), obj);
                return obj;
            }
        };

        BeanProcessor.BeanCreator currentCreator = initialBeanCreator;
        for(BeanProcessor processor : processors){
            obj = processor.afterInit(obj, getName(), currentCreator, beanData);
            currentCreator = new BeanCreatorChain(currentCreator, processor, beanData, beanName, BeanCreatorChain.ChainType.After);
        }
        return obj;
    }    
    
    private Object addInterceptors(Object original)
            throws ComponentDefinitionException {

        Object intercepted = null;
        ComponentDefinitionRegistry reg = blueprintContainer
                .getComponentDefinitionRegistry();
        List<Interceptor> interceptors = reg.getInterceptors(interceptorLookupKey);
        if (interceptors != null && interceptors.size() > 0) {
            boolean asmAvailable = false;
            try {
                // Try load load an asm class (to make sure it's actually
                // available)
                getClass().getClassLoader().loadClass(
                        "org.objectweb.asm.ClassVisitor");
                LOGGER.debug("asm available for interceptors");
                asmAvailable = true;
            } catch (Throwable t) {
                try {
                    // Try load load a cglib class (to make sure it's actually
                    // available)
                    getClass().getClassLoader().loadClass(
                            "net.sf.cglib.proxy.Enhancer");
                } catch (Throwable u) {
                    throw new ComponentDefinitionException(
                            "Interceptors have been configured but neither asm nor cglib are available",
                            u);
                }
            }
            if (asmAvailable) {
                // if asm is available we can proxy the original object with the
                // AsmInterceptorWrapper
                intercepted = AsmInterceptorWrapper.createProxyObject(original
                        .getClass().getClassLoader(), interceptorLookupKey, interceptors,
                        original, original.getClass());
            } else {
                LOGGER.debug("cglib available for interceptors");
                // otherwise we're using cglib and need to use the interfaces
                // with the CgLibInterceptorWrapper
                intercepted = CgLibInterceptorWrapper.createProxyObject(
                        original.getClass().getClassLoader(), interceptorLookupKey,
                        interceptors, original, original.getClass()
                                .getInterfaces());
            }

        } else {
            intercepted = original;
        }
        return intercepted;
    }
        
    @Override
    protected Object internalCreate() throws ComponentDefinitionException {
        
        instantiateExplicitDependencies();

        Object obj = getInstance();
                
        // check for init lifecycle method (if any)
        Method initMethod = getInitMethod(obj);
        
        // check for destroy lifecycle method (if any)
        getDestroyMethod(obj);
        
        // Add partially created object to the container
//        if (initMethod == null) {
            addPartialObject(obj);
//        }

        // inject properties
        setProperties(obj);
        
        obj = runBeanProcPreInit(obj);
        
        runBeanProcInit(initMethod, obj);
        
        obj = runBeanProcPostInit(obj);
        
        obj = addInterceptors(obj);
        
        return obj;
    }
    
    @Override
    public void destroy(Object obj) {
        for (BeanProcessor processor : blueprintContainer.getProcessors(BeanProcessor.class)) {
            processor.beforeDestroy(obj, getName());
        }
        try {
            Method method = getDestroyMethod(obj);
            if (method != null) {
                invoke(method, obj, (Object[]) null);
            }
        } catch (Exception e) {
            LOGGER.info("Error invoking destroy method", getRealCause(e));
        }
        for (BeanProcessor processor : blueprintContainer.getProcessors(BeanProcessor.class)) {
            processor.afterDestroy(obj, getName());
        }
    }

    public void setProperties(Object instance) throws ComponentDefinitionException {
        // clone the properties so they can be used again
        Map<String,Object> propertyValues = new LinkedHashMap<String,Object>(properties);
        setProperties(propertyValues, instance, instance.getClass());
    }

    public Class getType() {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof String) {
            return loadClass((String) type);
        } else {
            return null;
        }
    }

    private void setProperties(Map<String, Object> propertyValues, Object instance, Class clazz) {
        // set remaining properties
        for (Map.Entry<String, Object> entry : propertyValues.entrySet()) {
            String propertyName = entry.getKey();
            Object propertyValue = entry.getValue();

            setProperty(instance, clazz, propertyName, propertyValue);
        }

    }

    private void setProperty(Object instance, Class clazz, String propertyName, Object propertyValue) {
        String[] names = propertyName.split("\\.");
        for (int i = 0; i < names.length - 1; i++) {
            PropertyDescriptor pd = getPropertyDescriptor(clazz, names[i]);
            if (pd.allowsGet()) {
                try {
                    instance = pd.get(instance, blueprintContainer.getAccessControlContext());
                } catch (Exception e) {
                    throw new ComponentDefinitionException("Error getting property: " + names[i] + " on bean " + getName() + " when setting property " + propertyName + " on class " + clazz.getName(), getRealCause(e));
                }
                if (instance == null) {
                    throw new ComponentDefinitionException("Error setting compound property " + propertyName + " on bean " + getName() + ". Property " + names[i] + " is null");
                }
                clazz = instance.getClass();
            } else {
                throw new ComponentDefinitionException("No getter for " + names[i] + " property on bean " + getName() + " when setting property " + propertyName + " on class " + clazz.getName());
            }
        }
        
        // Instantiate value
        if (propertyValue instanceof Recipe) {
            propertyValue = ((Recipe) propertyValue).create();
        }

        final PropertyDescriptor pd = getPropertyDescriptor(clazz, names[names.length - 1]);
        if (pd.allowsSet()) {
            try {
                pd.set(instance, propertyValue, blueprintContainer.getAccessControlContext());
            } catch (Exception e) {
                throw new ComponentDefinitionException("Error setting property: " + pd, getRealCause(e));
            }
        } else {
            throw new ComponentDefinitionException("No setter for " + names[names.length - 1] + " property");
        }
    }

    private ReflectionUtils.PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String name) {
        for (ReflectionUtils.PropertyDescriptor pd : ReflectionUtils.getPropertyDescriptors(clazz, allowsFieldInjection)) {
            if (pd.getName().equals(name)) {
                return pd;
            }
        }
        throw new ComponentDefinitionException("Unable to find property descriptor " + name + " on class " + clazz.getName());
    }
        
    private Object invoke(Method method, Object instance, Object... args) throws Exception {
        return ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(), method, instance, args);        
    }
    
    private Object newInstance(Constructor constructor, Object... args) throws Exception {
        return ReflectionUtils.newInstance(blueprintContainer.getAccessControlContext(), constructor, args);         
    }
    
    private static Object UNMATCHED = new Object();

    private class ArgumentMatcher {

        private List<TypeEntry> entries;
        private boolean convert;

        public ArgumentMatcher(Type[] types, boolean convert) {
            entries = new ArrayList<TypeEntry>();
            for (Type type : types) {
                entries.add(new TypeEntry(new GenericType(type)));
            }
            this.convert = convert;
        }

        public List<Object> match(List<Object> arguments, List<ReifiedType> forcedTypes) {
            if (find(arguments, forcedTypes)) {
                return getArguments();
            }
            return null;
        }

        private List<Object> getArguments() {
            List<Object> list = new ArrayList<Object>();
            for (TypeEntry entry : entries) {
                if (entry.argument == UNMATCHED) {
                    throw new RuntimeException("There are unmatched types");
                } else {
                    list.add(entry.argument);
                }
            }
            return list;
        }

        private boolean find(List<Object> arguments, List<ReifiedType> forcedTypes) {
            if (entries.size() == arguments.size()) {
                boolean matched = true;
                for (int i = 0; i < arguments.size() && matched; i++) {
                    matched = find(arguments.get(i), forcedTypes.get(i));
                }
                return matched;
            }
            return false;
        }

        private boolean find(Object arg, ReifiedType forcedType) {
            for (TypeEntry entry : entries) {
                Object val = arg;
                if (entry.argument != UNMATCHED) {
                    continue;
                }
                if (forcedType != null) {
                    if (!forcedType.equals(entry.type)) {
                        continue;
                    }
                } else if (arg != null) {
                    if (convert) {
                        try {
                            // TODO: call canConvert instead of convert()
                            val = convert(arg, entry.type);
                        } catch (Throwable t) {
                            continue;
                        }
                    } else {
                        if (!AggregateConverter.isAssignable(arg, entry.type)) {
                            continue;
                        }
                    }
                }
                entry.argument = val;
                return true;
            }
            return false;
        }

    }

    private static class TypeEntry {

        private final ReifiedType type;
        private Object argument;

        public TypeEntry(ReifiedType type) {
            this.type = type;
            this.argument = UNMATCHED;
        }

    }

}
