1 /*
   2  * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.sun.beans.finder;
  26 
  27 import com.sun.beans.util.Cache;
  28 
  29 import java.lang.reflect.Constructor;
  30 import java.lang.reflect.Modifier;
  31 
  32 import static com.sun.beans.util.Cache.Kind.SOFT;
  33 import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
  34 
  35 /**
  36  * This utility class provides {@code static} methods
  37  * to find a public constructor with specified parameter types
  38  * in specified class.
  39  *
  40  * @since 1.7
  41  *
  42  * @author Sergey A. Malenkov
  43  */
  44 public final class ConstructorFinder extends AbstractFinder<Constructor<?>> {
  45     private static final Cache<Signature, Constructor<?>> CACHE = new Cache<Signature, Constructor<?>>(SOFT, SOFT) {
  46         @Override
  47         public Constructor create(Signature signature) {
  48             try {
  49                 ConstructorFinder finder = new ConstructorFinder(signature.getArgs());
  50                 return finder.find(signature.getType().getConstructors());
  51             }
  52             catch (Exception exception) {
  53                 throw new SignatureException(exception);
  54             }
  55         }
  56     };
  57 
  58     /**
  59      * Finds public constructor
  60      * that is declared in public class.
  61      *
  62      * @param type  the class that can have constructor
  63      * @param args  parameter types that is used to find constructor
  64      * @return object that represents found constructor
  65      * @throws NoSuchMethodException if constructor could not be found
  66      *                               or some constructors are found
  67      */
  68     public static Constructor<?> findConstructor(Class<?> type, Class<?>...args) throws NoSuchMethodException {
  69         if (type.isPrimitive()) {
  70             throw new NoSuchMethodException("Primitive wrapper does not contain constructors");
  71         }
  72         if (type.isInterface()) {
  73             throw new NoSuchMethodException("Interface does not contain constructors");
  74         }
  75         if (Modifier.isAbstract(type.getModifiers())) {
  76             throw new NoSuchMethodException("Abstract class cannot be instantiated");
  77         }
  78         if (!Modifier.isPublic(type.getModifiers()) || !isPackageAccessible(type)) {
  79             throw new NoSuchMethodException("Class is not accessible");
  80         }
  81         PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
  82         Signature signature = new Signature(type, args);
  83 
  84         try {
  85             return CACHE.get(signature);
  86         }
  87         catch (SignatureException exception) {
  88             throw exception.toNoSuchMethodException("Constructor is not found");
  89         }
  90     }
  91 
  92     /**
  93      * Creates constructor finder with specified array of parameter types.
  94      *
  95      * @param args  the array of parameter types
  96      */
  97     private ConstructorFinder(Class<?>[] args) {
  98         super(args);
  99     }
 100 }