All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jvnet.hk2.component.Creators Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2007-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package org.jvnet.hk2.component;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.sun.hk2.component.*;
import org.glassfish.hk2.Provider;
import org.jvnet.hk2.annotations.Factory;
import org.jvnet.hk2.annotations.FactoryFor;
import org.jvnet.hk2.annotations.Inject;

/**
 * {@link Creator} factory.
 *
 * @author Kohsuke Kawaguchi
 */
public class Creators {
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static  Creator create(Class c, Habitat habitat, MultiMap metadata) {
        Factory f = c.getAnnotation(Factory.class);
        if (f != null) {
            return new FactoryCreator(c,f.value(),habitat,metadata);
        }

        Inhabitant factory = habitat.getInhabitantByAnnotation(FactoryFor.class, c.getName());
        if (factory != null) {
            return new FactoryCreator(c,factory,habitat,metadata);
        }

        // A constructor invoked on an abstract class will fail,
        // so only return constructors for concrete classes
        boolean isAbstract = Modifier.isAbstract(c.getModifiers());
        
        if (!isAbstract) {
          Reference> defaultCtorRef = new Reference();
          Reference> noArgCtorRef = new Reference();
          qualifyingConstructors(c, null, getInjectionAnnotations(habitat), defaultCtorRef, noArgCtorRef);
          if (defaultCtorRef.get() != null) {
            return new InjectableParametizedConstructorCreator(c, defaultCtorRef.get(), habitat, metadata);
          }
          if (noArgCtorRef.get() != null) {
            return new ConstructorCreator(c,habitat,metadata);
          }
        }
        
        return null;
    }

    /**
     * Returns all currently available injection annotations
     *
     */
    private static Set> getInjectionAnnotations(Habitat habitat) {

        Set> annotations = new HashSet>();
        for (Inhabitant resolver : getAllInjectionResolvers(habitat)) {
            annotations.add(resolver.get().type);
        }
        return annotations;
    }

    /**
     * Returns all currently available injection annotations
     * @param habitat the service registry
     * @return the list of injection resolvers registered in this service registry in its parent.
     *
     */
    public static List> getAllInjectionResolvers(Habitat habitat) {

        List> resolvers = new ArrayList>();

        // we treat the @Inject injection resolver specially as the other injectors might be
        // using default HK2 injection themselves.
        Inhabitant specialResolver = habitat.getInhabitant(InjectionResolver.class, "Inject");
        specialResolver.get(); // force initialization
        resolvers.add(specialResolver);
        for (Inhabitant injectionResolver : habitat.getInhabitants(InjectionResolver.class)) {
            if (injectionResolver!=specialResolver)
                resolvers.add(injectionResolver);
        }

        if (habitat.getDefault()!=habitat) {
            for (Provider injectionResolver : habitat.getDefault().forContract(InjectionResolver.class).all()) {
                resolvers.add((Inhabitant) injectionResolver);
            }
        }
        return resolvers;
    }

    /**
     * Returns all "eligible" constructors for injection. Eligibility is
     * determined by:
     * 
     * (a) the no-arg constructor, or (b) @Inject annotated constructor.
     * 
     * 

* Note, however, that this does not verify that the arguments on the * constructor are indeed injectable out of the habitat. * * @param c * The class to find the constructors for * @param defaultCtor * (optional) The "favored" default constructor reference; meaning that all arguments can be injected based on the contents of the habitat * @param noArgCtor * (optional The no-arg constructor reference * @return * The list of all eligible constructors */ @SuppressWarnings("unchecked") public static void qualifyingConstructors(Class c, List> allList, Set> injectionAnnotations, Reference> defaultCtor, Reference> noArgCtor) { Constructor[] ctors; try { ctors = (Constructor[]) c.getDeclaredConstructors(); } catch(Exception e) { ctors = (Constructor[]) c.getConstructors(); } for (Constructor ctor : ctors) { if (0 == ctor.getParameterTypes().length) { if (null != allList) { allList.add(ctor); } if (null != noArgCtor) { noArgCtor.set(ctor); } } else if (isInjectable(injectionAnnotations, ctor)) { if (null != allList) { allList.add(ctor); } if (null != defaultCtor && null == defaultCtor.get()) { defaultCtor.set(ctor); } } else { boolean allInjectable = true; for (Annotation[] a : ctor.getParameterAnnotations()) { if (!isInject(injectionAnnotations, a)) { allInjectable = false; break; } } if (allInjectable) { if (null != allList) { allList.add(ctor); } if (null != defaultCtor && null == defaultCtor.get()) { defaultCtor.set(ctor); } } } } } private static boolean isInject(Set> injectionAnnotations, Annotation... a) { for (Annotation ae : a) { if (injectionAnnotations.contains(ae.annotationType()) || ae.annotationType().equals(javax.inject.Inject.class)) { return true; } } return false; } public static boolean isInjectable(Set> injectionAnnotations,AnnotatedElement ae) { for (Class injectionAnnotation : injectionAnnotations) { if (ae.getAnnotation(injectionAnnotation)!=null) return true; } return (null != ae.getAnnotation(Inject.class) || null != ae.getAnnotation(javax.inject.Inject.class)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy