/** * Create a default object of the given type. Prefers constructors with as few arguments as * possible. Creates an empty proxy for interfaces. * * @param type type to instantiate * @return default instance * @throws Exception if the default instance could not be created */ private static Object instantiateType(Class<?> type) throws Exception { if (type.isPrimitive()) return Defaults.defaultValue(type); else if (type == Void.class) return null; else if (type.isArray()) return Array.newInstance(type, 0); else if (type.isInterface()) return Proxy.newProxyInstance( type.getClassLoader(), new Class[] {type}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }); // Take a constructor with as few params as possible Constructor constructor = type.getDeclaredConstructors()[0]; for (Constructor<?> c : type.getDeclaredConstructors()) { if (c.getParameterTypes().length < constructor.getParameterTypes().length) constructor = c; } Object[] params = new Object[constructor.getParameterTypes().length]; for (int i = 0; i < constructor.getParameterTypes().length; i++) { params[i] = instantiateType(constructor.getParameterTypes()[i]); } return constructor.newInstance(params); }
private Filter newInstance(API api) throws Exception { for (Constructor c : api.filter().getDeclaredConstructors()) { c.setAccessible(true); Class[] ps = c.getParameterTypes(); if (ps.length == 1 && RequestArguments.class.isAssignableFrom(ps[0])) return (Filter) c.newInstance(this); } for (Constructor c : api.filter().getDeclaredConstructors()) { Class[] ps = c.getParameterTypes(); if (ps.length == 0) return (Filter) c.newInstance(); } throw new Exception("Class " + api.filter().getName() + " must have an empty constructor"); }
@SuppressWarnings("unchecked") private <T> T _get(Class<T> type, Set<Class<?>> seenTypes) { if (!seenTypes.add(type)) { throw new IllegalStateException("Cycle in dependencies for " + type); } Object singleton = singletons.get(type); if (singleton != null) { return (T) singleton; } try { Constructor<T> constructor = getConstructor(type); Class<?>[] parameterTypes = constructor.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { parameters[i] = _get(parameterTypes[i], seenTypes); } T instance = postProcess(constructor.newInstance(parameters)); singletons.put(type, instance); return instance; } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Unable to create instance of " + type); } }
protected void _addConstructorMixIns(Class<?> mixin) { MemberKey[] ctorKeys = null; int ctorCount = (_constructors == null) ? 0 : _constructors.size(); for (Constructor<?> ctor : mixin.getDeclaredConstructors()) { switch (ctor.getParameterTypes().length) { case 0: if (_defaultConstructor != null) { _addMixOvers(ctor, _defaultConstructor, false); } break; default: if (ctorKeys == null) { ctorKeys = new MemberKey[ctorCount]; for (int i = 0; i < ctorCount; ++i) { ctorKeys[i] = new MemberKey(_constructors.get(i).getAnnotated()); } } MemberKey key = new MemberKey(ctor); for (int i = 0; i < ctorCount; ++i) { if (!key.equals(ctorKeys[i])) { continue; } _addMixOvers(ctor, _constructors.get(i), true); break; } } } }
private void validateClass(Class<?> source, ValidationProblemCollector problems) { int modifiers = source.getModifiers(); if (Modifier.isInterface(modifiers)) { problems.add("Must be a class, not an interface"); } if (source.getEnclosingClass() != null) { if (Modifier.isStatic(modifiers)) { if (Modifier.isPrivate(modifiers)) { problems.add("Class cannot be private"); } } else { problems.add("Enclosed classes must be static and non private"); } } Constructor<?>[] constructors = source.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { if (constructor.getParameterTypes().length > 0) { problems.add("Cannot declare a constructor that takes arguments"); break; } } Field[] fields = source.getDeclaredFields(); for (Field field : fields) { int fieldModifiers = field.getModifiers(); if (!field.isSynthetic() && !(Modifier.isStatic(fieldModifiers) && Modifier.isFinal(fieldModifiers))) { problems.add(field, "Fields must be static final."); } } }
@SuppressWarnings("unchecked") public static <T> Constructor<T> findConstructor(Class<T> type, Class<?>... paramTypes) { Constructor<T>[] ctors = (Constructor<T>[]) type.getConstructors(); for (Constructor<T> ctor : ctors) if (typesMatch(paramTypes, ctor.getParameterTypes())) return ctor; return null; }
public void apply() throws IllegalAccessException, InvocationTargetException, InstantiationException { if (type.isEnum()) { for (T instance : type.getEnumConstants()) { assertThat( instance.toString(), is( type.getCanonicalName().substring(type.getPackage().getName().length() + 1) + "." + ((Enum<?>) instance).name())); } return; } for (Constructor<?> constructor : type.getDeclaredConstructors()) { if (constructor.isSynthetic() && skipSynthetic) { continue; } constructor.setAccessible(true); Class<?>[] parameterTypes = constructor.getParameterTypes(); Object[] actualArguments = new Object[parameterTypes.length]; Object[] otherArguments = new Object[parameterTypes.length]; int index = 0; for (Class<?> parameterType : parameterTypes) { putInstance(parameterType, actualArguments, otherArguments, index++); } int testIndex = 0; @SuppressWarnings("unchecked") T instance = (T) constructor.newInstance(actualArguments); assertThat(instance, is(instance)); assertThat(instance, not(is((Object) null))); assertThat(instance, not(is(new Object()))); Object similarInstance = constructor.newInstance(actualArguments); assertThat(instance.hashCode(), is(similarInstance.hashCode())); assertThat(instance, is(similarInstance)); if (skipToString) { assertThat(instance.toString(), notNullValue()); } else if (optionalToStringRegex == null) { checkString(instance); } else { assertThat(instance.toString(), new RegexMatcher(optionalToStringRegex)); } for (Object otherArgument : otherArguments) { Object[] compareArguments = new Object[actualArguments.length]; int argumentIndex = 0; for (Object actualArgument : actualArguments) { if (argumentIndex == testIndex) { compareArguments[argumentIndex] = otherArgument; } else { compareArguments[argumentIndex] = actualArgument; } argumentIndex++; } Object unlikeInstance = constructor.newInstance(compareArguments); assertThat(instance.hashCode(), not(is(unlikeInstance))); assertThat(instance, not(is(unlikeInstance))); testIndex++; } } }
private Validator newValidator(API api) throws Exception { for (Constructor c : api.validator().getDeclaredConstructors()) { c.setAccessible(true); Class[] ps = c.getParameterTypes(); return (Validator) c.newInstance(); } return null; }
/** * Finds the constructor of the given class that is compatible with the given arguments. * * @param type the class to find the constructor of * @param args the arguments * @return the constructor */ public static Constructor findConstructor(Class<?> type, Object[] args) { outer: for (Constructor constructor : type.getConstructors()) { Class<?>[] paramTypes = constructor.getParameterTypes(); if (paramTypes.length != args.length) continue; for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg != null && !paramTypes[i].isAssignableFrom(arg.getClass())) continue outer; if (arg == null && paramTypes[i].isPrimitive()) continue outer; } return constructor; } throw new GrammarException( "No constructor found for %s and the given %s arguments", type, args.length); }
public static <T> T newInstance( Constructor<T> constructor, boolean strict, Object... parameters) { if (!strict) parameters = convertArray(parameters, constructor.getParameterTypes()); Class<T> type = constructor.getDeclaringClass(); if (deprecated(type)) escalator.escalate( "Instantiating a deprecated class: " + type.getName(), BeanUtil.class, null); try { return constructor.newInstance(parameters); } catch (InstantiationException e) { throw ExceptionMapper.configurationException(e, type); } catch (IllegalAccessException e) { throw ExceptionMapper.configurationException(e, type); } catch (InvocationTargetException e) { throw ExceptionMapper.configurationException(e, type); } }
private static Object createArgumentPlaceholderForUnknownClass( Class<?> clazz, Integer placeholderId) throws IllegalAccessException, InstantiationException { FinalClassArgumentCreator<?> creator = FINAL_CLASS_ARGUMENT_CREATORS.get(clazz); if (creator != null) return creator.createArgumentPlaceHolder(placeholderId); for (Constructor constructor : clazz.getConstructors()) { Class<?>[] params = constructor.getParameterTypes(); if (params.length != 1) continue; try { if (params[0] == String.class) return constructor.newInstance(String.valueOf(placeholderId)); if (isNumericClass(params[0])) return constructor.newInstance(placeholderId); } catch (IllegalAccessException e1) { } catch (InvocationTargetException e2) { } } return clazz.newInstance(); }
/** * Prints all constructors of a class * * @param cl a class */ public static void printConstructors(Class cl) { Constructor[] constructors = cl.getDeclaredConstructors(); for (Constructor c : constructors) { String name = c.getName(); System.out.print(" "); String modifiers = Modifier.toString(c.getModifiers()); if (modifiers.length() > 0) System.out.print(modifiers + " "); System.out.print(name + "("); // print parameter types Class[] paramTypes = c.getParameterTypes(); for (int j = 0; j < paramTypes.length; j++) { if (j > 0) System.out.print(", "); System.out.print(paramTypes[j].getName()); } System.out.println(");"); } }
public void applyBasic() throws IllegalAccessException, InvocationTargetException, InstantiationException { for (Constructor<?> constructor : type.getDeclaredConstructors()) { if (constructor.isSynthetic() && skipSynthetic) { continue; } constructor.setAccessible(true); Class<?>[] parameterTypes = constructor.getParameterTypes(); Object[] actualArguments = new Object[parameterTypes.length]; Object[] otherArguments = new Object[parameterTypes.length]; int index = 0; for (Class<?> parameterType : parameterTypes) { putInstance(parameterType, actualArguments, otherArguments, index++); } @SuppressWarnings("unchecked") T instance = (T) constructor.newInstance(actualArguments); checkString(instance); assertThat(instance, is(instance)); assertThat(instance, not(is((Object) null))); assertThat(instance, not(is(new Object()))); assertThat(instance, not(is(constructor.newInstance(otherArguments)))); } }
/** * Initialization method that will find out all constructors and potential static factory methods * the class has. * * <p>Starting with 1.2, it will also apply mix-in annotations, as per [JACKSON-76] * * @param includeAll If true, includes all creator methods; if false, will only include the * no-arguments "default" constructor */ public void resolveCreators(boolean includeAll) { // Then see which constructors we have _constructors = null; for (Constructor<?> ctor : _class.getDeclaredConstructors()) { switch (ctor.getParameterTypes().length) { case 0: _defaultConstructor = _constructConstructor(ctor, true); break; default: if (includeAll) { if (_constructors == null) { _constructors = new ArrayList<AnnotatedConstructor>(); } _constructors.add(_constructConstructor(ctor, false)); } } } // and if need be, augment with mix-ins if (_primaryMixIn != null) { if (_defaultConstructor != null || _constructors != null) { _addConstructorMixIns(_primaryMixIn); } } /* And then... let's remove all constructors that are * deemed to be ignorable after all annotations have been * properly collapsed. */ if (_defaultConstructor != null) { if (_annotationIntrospector.isIgnorableConstructor(_defaultConstructor)) { _defaultConstructor = null; } } if (_constructors != null) { // count down to allow safe removal for (int i = _constructors.size(); --i >= 0; ) { if (_annotationIntrospector.isIgnorableConstructor(_constructors.get(i))) { _constructors.remove(i); } } } _creatorMethods = null; if (includeAll) { /* Then static methods which are potential factory * methods */ for (Method m : _class.getDeclaredMethods()) { if (!Modifier.isStatic(m.getModifiers())) { continue; } int argCount = m.getParameterTypes().length; // factory methods take at least one arg: if (argCount < 1) { continue; } if (_creatorMethods == null) { _creatorMethods = new ArrayList<AnnotatedMethod>(); } _creatorMethods.add(_constructCreatorMethod(m)); } // mix-ins to mix in? if (_primaryMixIn != null && _creatorMethods != null) { _addFactoryMixIns(_primaryMixIn); } // anything to ignore at this point? if (_creatorMethods != null) { // count down to allow safe removal for (int i = _creatorMethods.size(); --i >= 0; ) { if (_annotationIntrospector.isIgnorableMethod(_creatorMethods.get(i))) { _creatorMethods.remove(i); } } } } }
private static void generateCtor( ClassFileWriter cfw, String adapterName, String superName, Constructor<?> superCtor) { short locals = 3; // this + factory + delegee Class<?>[] parameters = superCtor.getParameterTypes(); // Note that we swapped arguments in app-facing constructors to avoid // conflicting signatures with serial constructor defined below. if (parameters.length == 0) { cfw.startMethod( "<init>", "(Laurora/javascript/Scriptable;" + "Laurora/javascript/ContextFactory;)V", ClassFileWriter.ACC_PUBLIC); // Invoke base class constructor cfw.add(ByteCode.ALOAD_0); // this cfw.addInvoke(ByteCode.INVOKESPECIAL, superName, "<init>", "()V"); } else { StringBuilder sig = new StringBuilder( "(Laurora/javascript/Scriptable;" + "Laurora/javascript/ContextFactory;"); int marker = sig.length(); // lets us reuse buffer for super signature for (Class<?> c : parameters) { appendTypeString(sig, c); } sig.append(")V"); cfw.startMethod("<init>", sig.toString(), ClassFileWriter.ACC_PUBLIC); // Invoke base class constructor cfw.add(ByteCode.ALOAD_0); // this short paramOffset = 3; for (Class<?> parameter : parameters) { paramOffset += generatePushParam(cfw, paramOffset, parameter); } locals = paramOffset; sig.delete(1, marker); cfw.addInvoke(ByteCode.INVOKESPECIAL, superName, "<init>", sig.toString()); } // Save parameter in instance variable "delegee" cfw.add(ByteCode.ALOAD_0); // this cfw.add(ByteCode.ALOAD_1); // first arg: Scriptable delegee cfw.add(ByteCode.PUTFIELD, adapterName, "delegee", "Laurora/javascript/Scriptable;"); // Save parameter in instance variable "factory" cfw.add(ByteCode.ALOAD_0); // this cfw.add(ByteCode.ALOAD_2); // second arg: ContextFactory instance cfw.add(ByteCode.PUTFIELD, adapterName, "factory", "Laurora/javascript/ContextFactory;"); cfw.add(ByteCode.ALOAD_0); // this for the following PUTFIELD for self // create a wrapper object to be used as "this" in method calls cfw.add(ByteCode.ALOAD_1); // the Scriptable delegee cfw.add(ByteCode.ALOAD_0); // this cfw.addInvoke( ByteCode.INVOKESTATIC, "aurora/javascript/JavaAdapter", "createAdapterWrapper", "(Laurora/javascript/Scriptable;" + "Ljava/lang/Object;" + ")Laurora/javascript/Scriptable;"); cfw.add(ByteCode.PUTFIELD, adapterName, "self", "Laurora/javascript/Scriptable;"); cfw.add(ByteCode.RETURN); cfw.stopMethod(locals); }
@SuppressWarnings({"unchecked", "rawtypes"}) public static <T> T newInstance(Class<T> type, boolean strict, Object... parameters) { if (parameters.length == 0) return newInstanceFromDefaultConstructor(type); Constructor<T> constructorToUse = null; try { Constructor<T>[] constructors = (Constructor<T>[]) type.getConstructors(); List<Constructor<T>> candidates = new ArrayList<Constructor<T>>(constructors.length); int paramCount = parameters.length; for (Constructor<T> constructor : constructors) if (constructor.getParameterTypes().length == paramCount) candidates.add(constructor); if (candidates.size() == 1) constructorToUse = candidates.get(0); else if (candidates.size() == 0) throw new ConfigurationError( "No constructor with " + paramCount + " parameters found for " + type); else { // there are several candidates - find the first one with matching types Class<?>[] paramTypes = new Class[parameters.length]; for (int i = 0; i < parameters.length; i++) paramTypes[i] = parameters[i].getClass(); for (Constructor c : type.getConstructors()) { if (typesMatch(c.getParameterTypes(), paramTypes)) { constructorToUse = c; break; } } // there is no ideal match if (constructorToUse == null) { if (strict) throw new NoSuchMethodException( "No appropriate constructor found: " + type + '(' + ArrayFormat.format(", ", paramTypes) + ')'); Exception mostRecentException = null; for (Constructor<T> candidate : candidates) { try { return newInstance(candidate, strict, parameters); } catch (Exception e) { mostRecentException = e; logger.warn("Exception in constructor call: " + candidate, e); continue; // ignore exception and try next constructor } } // no constructor could be called without exception String errMsg = (mostRecentException != null ? "None of these constructors could be called without exception: " + candidates + ", latest exception: " + mostRecentException : type + " has no appropriate constructor for the arguments " + ArrayFormat.format(", ", parameters)); throw new ConfigurationError(errMsg); } } if (!strict) parameters = convertArray(parameters, constructorToUse.getParameterTypes()); return newInstance(constructorToUse, parameters); } catch (SecurityException e) { throw ExceptionMapper.configurationException(e, constructorToUse); } catch (NoSuchMethodException e) { throw ExceptionMapper.configurationException(e, type); } }