001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.reflect; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016 017import java.lang.annotation.*; 018import java.lang.reflect.*; 019 020import org.apache.juneau.*; 021import org.apache.juneau.annotation.*; 022 023/** 024 * Lightweight utility class for introspecting information about a constructor. 025 */ 026@BeanIgnore 027public final class ConstructorInfo extends ExecutableInfo implements Comparable<ConstructorInfo> { 028 029 private final Constructor<?> c; 030 031 //----------------------------------------------------------------------------------------------------------------- 032 // Instantiation. 033 //----------------------------------------------------------------------------------------------------------------- 034 035 /** 036 * Constructor. 037 * 038 * @param declaringClass The class that declares this method. 039 * @param c The constructor being wrapped. 040 * @param rc The "real" constructor if the constructor above is defined against a CGLIB proxy. 041 */ 042 protected ConstructorInfo(ClassInfo declaringClass, Constructor<?> c, Constructor<?> rc) { 043 super(declaringClass, c, rc); 044 this.c = c; 045 } 046 047 /** 048 * Convenience method for instantiating a {@link ConstructorInfo}; 049 * 050 * @param declaringClass The class that declares this method. 051 * @param c The constructor being wrapped. 052 * @param rc The "real" constructor if the constructor above is defined against a CGLIB proxy. 053 * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null; 054 */ 055 public static ConstructorInfo of(ClassInfo declaringClass, Constructor<?> c, Constructor<?> rc) { 056 if (c == null) 057 return null; 058 return new ConstructorInfo(declaringClass, c, rc); 059 } 060 061 /** 062 * Convenience method for instantiating a {@link ConstructorInfo}; 063 * 064 * @param c The constructor being wrapped. 065 * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null; 066 */ 067 public static ConstructorInfo of(Constructor<?> c) { 068 if (c == null) 069 return null; 070 return new ConstructorInfo(ClassInfo.of(c.getDeclaringClass()), c, c); 071 } 072 073 /** 074 * Returns the wrapped method. 075 * 076 * @return The wrapped method. 077 */ 078 @SuppressWarnings("unchecked") 079 public <T> Constructor<T> inner() { 080 return (Constructor<T>)c; 081 } 082 083 084 //----------------------------------------------------------------------------------------------------------------- 085 // Annotations 086 //----------------------------------------------------------------------------------------------------------------- 087 088 /** 089 * Finds the annotation of the specified type defined on this constructor. 090 * 091 * @param a 092 * The annotation to search for. 093 * @return 094 * The annotation if found, or <jk>null</jk> if not. 095 */ 096 public final <T extends Annotation> T getAnnotation(Class<T> a) { 097 return getAnnotation(a, MetaProvider.DEFAULT); 098 } 099 100 /** 101 * Finds the annotation of the specified type defined on this constructor. 102 * 103 * @param a 104 * The annotation to search for. 105 * @param mp 106 * The meta provider for looking up annotations on classes/methods/fields. 107 * @return 108 * The first annotation found, or <jk>null</jk> if it doesn't exist. 109 */ 110 public final <T extends Annotation> T getAnnotation(Class<T> a, MetaProvider mp) { 111 return last(mp.getAnnotations(a, c)); 112 } 113 114 /** 115 * Returns <jk>true</jk> if the specified annotation is present on this constructor. 116 * 117 * @param a The annotation to check for. 118 * @return <jk>true</jk> if the specified annotation is present on this constructor. 119 */ 120 public final boolean hasAnnotation(Class<? extends Annotation> a) { 121 return getAnnotation(a) != null; 122 } 123 124 125 //----------------------------------------------------------------------------------------------------------------- 126 // Other methods 127 //----------------------------------------------------------------------------------------------------------------- 128 129 /** 130 * Shortcut for calling the new-instance method on the underlying constructor. 131 * 132 * @param args the arguments used for the method call 133 * @return The object returned from the constructor. 134 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 135 */ 136 @SuppressWarnings("unchecked") 137 public <T> T invoke(Object...args) throws ExecutableException { 138 try { 139 return (T)c.newInstance(args); 140 } catch (InvocationTargetException e) { 141 throw new ExecutableException(e.getTargetException()); 142 } catch (Exception e) { 143 throw new ExecutableException(e); 144 } 145 } 146 147 /** 148 * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't. 149 * 150 * <p> 151 * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored. 152 * 153 * @param v The minimum visibility. 154 * @return 155 * The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not 156 * met or call to {@link Constructor#setAccessible(boolean)} throws a security exception. 157 */ 158 public ConstructorInfo makeAccessible(Visibility v) { 159 if (v.transform(c) == null) 160 return null; 161 return this; 162 } 163 164 @Override 165 public int compareTo(ConstructorInfo o) { 166 int i = getSimpleName().compareTo(o.getSimpleName()); 167 if (i == 0) { 168 i = getParamCount() - o.getParamCount(); 169 if (i == 0) { 170 for (int j = 0; j < getParamCount() && i == 0; j++) { 171 Class<?>[] tpt = _getRawParamTypes(), opt = o._getRawParamTypes(); 172 i = tpt[j].getName().compareTo(opt[j].getName()); 173 } 174 } 175 } 176 return i; 177 } 178 179 // <FluentSetters> 180 181 @Override /* GENERATED - ExecutableInfo */ 182 public ConstructorInfo accessible() { 183 super.accessible(); 184 return this; 185 } 186 187 // </FluentSetters> 188}