/** * Returns a new injection point for the injectable constructor of {@code type}. * * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject}, * or a no-arguments constructor that is not private. * @throws ConfigurationException if there is no injectable constructor, more than one injectable * constructor, or if parameters of the injectable constructor are malformed, such as a * parameter with multiple binding annotations. */ public static InjectionPoint forConstructorOf(TypeLiteral<?> type) { Class<?> rawType = getRawType(type.getType()); Errors errors = new Errors(rawType); Constructor<?> injectableConstructor = null; for (Constructor<?> constructor : rawType.getDeclaredConstructors()) { boolean optional; Inject guiceInject = constructor.getAnnotation(Inject.class); if (guiceInject == null) { javax.inject.Inject javaxInject = constructor.getAnnotation(javax.inject.Inject.class); if (javaxInject == null) { continue; } optional = false; } else { optional = guiceInject.optional(); } if (optional) { errors.optionalConstructor(constructor); } if (injectableConstructor != null) { errors.tooManyConstructors(rawType); } injectableConstructor = constructor; checkForMisplacedBindingAnnotations(injectableConstructor, errors); } errors.throwConfigurationExceptionIfErrorsExist(); if (injectableConstructor != null) { return new InjectionPoint(type, injectableConstructor); } // If no annotated constructor is found, look for a no-arg constructor instead. try { Constructor<?> noArgConstructor = rawType.getDeclaredConstructor(); // Disallow private constructors on non-private classes (unless they have @Inject) if (Modifier.isPrivate(noArgConstructor.getModifiers()) && !Modifier.isPrivate(rawType.getModifiers())) { errors.missingConstructor(rawType); throw new ConfigurationException(errors.getMessages()); } checkForMisplacedBindingAnnotations(noArgConstructor, errors); return new InjectionPoint(type, noArgConstructor); } catch (NoSuchMethodException e) { errors.missingConstructor(rawType); throw new ConfigurationException(errors.getMessages()); } }
private void checkCompoundIds(Class<?> javaClass) throws IOException { String javaClassName = javaClass.getCanonicalName(); PsiClass psiClass = myJavaPsiFacade.findClass( javaClassName, GlobalSearchScope.moduleWithLibrariesScope(myModule)); assertNotNull(psiClass); for (java.lang.reflect.Method javaMethod : javaClass.getDeclaredMethods()) { Method method = new Method( Type.getType(javaClass).getInternalName(), javaMethod.getName(), Type.getMethodDescriptor(javaMethod)); boolean noKey = javaMethod.getAnnotation(ExpectNoPsiKey.class) != null; PsiMethod psiMethod = psiClass.findMethodsByName(javaMethod.getName(), false)[0]; checkCompoundId(method, psiMethod, noKey); } for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) { Method method = new Method( Type.getType(javaClass).getInternalName(), "<init>", Type.getConstructorDescriptor(constructor)); boolean noKey = constructor.getAnnotation(ExpectNoPsiKey.class) != null; PsiMethod[] constructors = psiClass.getConstructors(); PsiMethod psiMethod = constructors[0]; checkCompoundId(method, psiMethod, noKey); } }
@Test(groups = "unit", timeOut = 1000) public void test() throws ClassNotFoundException { final Collection<Class<?>> descriptionClasses = Lists.newArrayList(); final URL url = AnnotationTests.class.getClassLoader().getResource("META-INF/jobs/persistence.xml"); final String jpaConfigContents = InputContexts.toString(InputContexts.forUrl(url)); final List<Class<? extends ActivityDescription>> activityDescriptionsMapped = Lists.newArrayList(); for (final Class<? extends ActivityFactory<?>> factoryClass : FACTORIES) { // Make sure the class is make as a ManageBean to DI context picks it up. assert factoryClass.getAnnotation(ManagedBean.class) != null : "Factory class " + factoryClass + " is not annotated with @ManagedBean"; // assert factoryClass.getDeclaredConstructors().length == 1; boolean foundInjectedConstructor = false; for (Constructor<?> constructor : factoryClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0 || constructor.getAnnotation(Inject.class) != null) { foundInjectedConstructor = true; } } assert foundInjectedConstructor; final ActivityFactoryFor factoryAnnotation = factoryClass.getAnnotation(ActivityFactoryFor.class); // Make sure this class specifies which ActivityDescription it acts an ActivityFactory for. assert factoryAnnotation != null; final Class<? extends ActivityDescription> descriptionClass = factoryAnnotation.value(); activityDescriptionsMapped.add(descriptionClass); assert ActivityDescription.class.isAssignableFrom(descriptionClass); // Make sure there are not multiple descriptions per factory assert !descriptionClasses.contains(descriptionClass); // Make sure the description can be persisted assert descriptionClass.getAnnotation(Entity.class) != null : descriptionClass + " is not annotated with entity."; assert jpaConfigContents.contains(descriptionClass.getCanonicalName()) : "Class " + descriptionClass.getCanonicalName() + " not found in JPA configuration."; } final Pattern pattern = Pattern.compile("\\<class\\>.*\\<"); final Matcher matcher = pattern.matcher(jpaConfigContents); int start = 0; while (matcher.find(start)) { final int startIdx = matcher.start() + "<class>".length(); final int endIdx = jpaConfigContents.indexOf("<", startIdx); final String classStr = jpaConfigContents.substring(startIdx, endIdx); final Class<?> clazz = Class.forName(classStr); if (ActivityDescription.class.isAssignableFrom(clazz)) { if (!Modifier.isAbstract(clazz.getModifiers())) { assert activityDescriptionsMapped.contains(clazz) : "No activity factory found for description class " + clazz; } } start = endIdx; } }
@Test public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception { Constructor<?> deprecatedCtor = Date.class.getConstructor(String.class); assertEquals( deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class)); assertEquals( Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class)); }
private EnumSet<ExecutableType> executableTypesDefinedOnConstructor(Constructor<?> constructor) { ValidateOnExecution validateOnExecutionAnnotation = constructor.getAnnotation(ValidateOnExecution.class); EnumSet<ExecutableType> executableTypes = commonExecutableTypeChecks(validateOnExecutionAnnotation); if (executableTypes.contains(ExecutableType.IMPLICIT)) { executableTypes.add(ExecutableType.CONSTRUCTORS); } return executableTypes; }
static int examine(Class enclosedClass, String constructorSig) { Constructor c = enclosedClass.getEnclosingConstructor(); if (c == null && constructorSig == null) return 0; if (c != null && c.getAnnotation(ConstructorDescriptor.class).value().equals(constructorSig)) return 0; // everything is okay else { System.err.println( "\nUnexpected constructor value; expected:\t" + constructorSig + "\ngot:\t" + c); return 1; } }
/** * Finds the conversion method. * * @param <T> the type of the converter * @param cls the class to find a method for, not null * @return the method to call, null means use {@code toString} * @throws RuntimeException if invalid */ private <T> Constructor<T> findFromStringConstructor(Class<T> cls) { Constructor<T> con; try { con = cls.getDeclaredConstructor(String.class); } catch (NoSuchMethodException ex) { try { con = cls.getDeclaredConstructor(CharSequence.class); } catch (NoSuchMethodException ex2) { return null; } } FromString fromString = con.getAnnotation(FromString.class); return fromString != null ? con : null; }
private void initProperties(Class<?> clazz, Set<Class<?>> visited) { if (visited.add(clazz)) { CssDocProperty property = clazz.getAnnotation(CssDocProperty.class); if (property != null) { properties.add(new DocProperty(this, property, clazz)); } for (Constructor<?> constructor : clazz.getDeclaredConstructors()) { property = constructor.getAnnotation(CssDocProperty.class); if (property != null) { properties.add(new DocProperty(this, property, clazz)); } } for (Field field : clazz.getDeclaredFields()) { property = field.getAnnotation(CssDocProperty.class); if (property != null) { properties.add(new DocProperty(this, property, field.getType())); } } for (Method method : clazz.getDeclaredMethods()) { property = method.getAnnotation(CssDocProperty.class); if (property != null) { properties.add(new DocProperty(this, property, method.getReturnType())); } } Collections.sort( properties, new Comparator<DocProperty>() { private Collator collator = Collator.getInstance(); @Override public int compare(DocProperty a, DocProperty b) { return collator.compare(a.getName(), b.getName()); } }); CssDocSeeAlso seeAlso = clazz.getAnnotation(CssDocSeeAlso.class); if (seeAlso != null) { for (Class<?> next : seeAlso.value()) { initProperties(next, visited); } } } }
public static String[] evaluate(Constructor<?> candidate, int paramCount) { ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class); if (cp != null) { String[] names = cp.value(); if (names.length != paramCount) { throw new IllegalStateException( "Constructor annotated with @ConstructorProperties but not " + "corresponding to actual number of parameters (" + paramCount + "): " + candidate); } return names; } else { return null; } }
private void initPaths() { paths = new HashMap<String, CssDocPath>(); addPath(clazz.getAnnotation(CssDocPath.class)); for (Constructor<?> constructor : clazz.getDeclaredConstructors()) { addPath(constructor.getAnnotation(CssDocPath.class)); } for (Field field : clazz.getDeclaredFields()) { addPath(field.getAnnotation(CssDocPath.class)); } for (Method method : clazz.getDeclaredMethods()) { addPath(method.getAnnotation(CssDocPath.class)); } for (DocProperty property : this) { addPath(property.getAnnotation().path()); } }
/** * Return true if the type is not abstract and not an interface, and has a constructor annotated * with {@link Inject} or its only constructor is the default constructor. * * @param type A class type * @return True if the class type is instantiable */ public static boolean isInstantiable(Class<?> type) { if (!Modifier.isAbstract(type.getModifiers()) && !type.isInterface()) { // first check for a constructor annotated with @Inject, // - this doesn't care how many we'll let the injector complain // if there are more than one for (Constructor<?> c : type.getDeclaredConstructors()) { if (c.getAnnotation(Inject.class) != null) { return true; } } // check if we only have the public default constructor if (type.getConstructors().length == 1 && type.getConstructors()[0].getParameterTypes().length == 0) { return true; } } // no constructor available return false; }
private static Collection<? extends MockBinder> createMockBinders(Constructor<?> constructor) { if (constructor.getAnnotation(Inject.class) != null) { HashSet<MockBinder> mockBinders = new HashSet<MockBinder>(); for (int parameterIndex = 0; parameterIndex < constructor.getParameterTypes().length; parameterIndex++) { for (Annotation annotation : constructor.getParameterAnnotations()[parameterIndex]) { if (annotation.annotationType() == Mock.class) { Class<?> mockClass = constructor.getParameterTypes()[parameterIndex]; String mockName = defaultIfEmpty( ((Mock) annotation).value(), uncapitalize(mockClass.getSimpleName())); mockBinders.add(new SimpleMockBinder(mockClass, mockName)); } } } return mockBinders; } else { return Collections.emptyList(); } }
private void fillCat2Funs(final Map<String, FunctionInfo> funs) { for (Entry<String, FunctionInfo> e : funs.entrySet()) { Class<?> funClass = e.getValue().getFunction().getClass(); assert (funClass.getConstructors().length == 1); Constructor<?> cons = funClass.getConstructors()[0]; String name = e.getKey(); String constructorDescription = null; Description consAnno = cons.getAnnotation(Description.class); if (consAnno != null) { constructorDescription = consAnno.description(); } HashMap<Category, ArrayList<SignatureInfo>> cat2sig = new HashMap<>(); int methodCount = e.getValue().signatures.length; for (int i = 0; i < methodCount; i++) { createSigInfo(e, consAnno, cat2sig, i); } for (Category cat : cat2sig.keySet()) { SortedMap<String, AnnotationInfo> m = cat2funs.get(cat); if (m == null) { m = new TreeMap<>(); cat2funs.put(cat, m); } AnnotationInfo aninfo = new AnnotationInfo(); aninfo.name = name; aninfo.constructorDescription = constructorDescription; aninfo.signatureInfos = cat2sig.get(cat).toArray(new SignatureInfo[] {}); m.put(aninfo.name, aninfo); cat2funs.put(cat, m); } } }
private final void init(E instance) { // Arrays can be mapped easily if (type.isArray()) { delegate = new ArrayMapper(instance); return; } // [#3212] "Value types" can be mapped from single-field Record1 types for convenience if (type.isPrimitive() || DefaultDataType.types().contains(type)) { delegate = new ValueTypeMapper(); return; } // [#1470] Return a proxy if the supplied type is an interface if (Modifier.isAbstract(type.getModifiers())) { delegate = new ProxyMapper(); return; } // [#2989] [#2836] Records are mapped if (AbstractRecord.class.isAssignableFrom(type)) { delegate = (RecordMapper<R, E>) new RecordToRecordMapper(); return; } // [#1340] Allow for using non-public default constructors try { delegate = new MutablePOJOMapper(type.getDeclaredConstructor(), instance); return; } catch (NoSuchMethodException ignore) { } // [#1336] If no default constructor is present, check if there is a // "matching" constructor with the same number of fields as this record Constructor<E>[] constructors = (Constructor<E>[]) type.getDeclaredConstructors(); // [#1837] If any java.beans.ConstructorProperties annotations are // present use those rather than matching constructors by the number of // arguments for (Constructor<E> constructor : constructors) { ConstructorProperties properties = constructor.getAnnotation(ConstructorProperties.class); if (properties != null) { delegate = new ImmutablePOJOMapperWithConstructorProperties(constructor, properties); return; } } // [#1837] Without ConstructorProperties, match constructors by matching // argument length for (Constructor<E> constructor : constructors) { Class<?>[] parameterTypes = constructor.getParameterTypes(); // Match the first constructor by parameter length if (parameterTypes.length == fields.length) { delegate = new ImmutablePOJOMapper(constructor, parameterTypes); return; } } throw new MappingException( "No matching constructor found on type " + type + " for record " + this); }
@SuppressWarnings("unchecked") public static <T> JsapResultsWithObject<T> constructObject( Class<T> clazz, String[] rawArguments, String mainHelp, Parameter[] otherParameters) throws JSAPException, IOException, IllegalArgumentException, ReflectiveOperationException { Constructor<T> constructor = null; for (Constructor<?> constr : clazz.getConstructors()) { boolean annotationPresent = constr.isAnnotationPresent(CommandLine.class); if (annotationPresent) { constructor = (Constructor<T>) constr; break; } } if (constructor == null) throw new IllegalAccessError( "Class " + clazz + " must have a constructor annotated with @CommandLine"); String[] argNames = constructor.getAnnotation(CommandLine.class).argNames(); if (argNames.length != constructor.getParameterCount()) throw new IllegalAnnotationException( "Annotation @CommandLine argNames are out of sync with the constructor arguments."); boolean[] isSerializedFile = new boolean[argNames.length]; SimpleJSAP jsap = new SimpleJSAP(clazz.getName(), mainHelp, otherParameters); int i = 0; for (java.lang.reflect.Parameter x : constructor.getParameters()) { Parameter option; if (x.getType().equals(boolean.class)) { isSerializedFile[i] = false; option = new Switch( argNames[i], JSAP.NO_SHORTFLAG, argNames[i], "Set the value of " + argNames[i] + " for " + clazz.getSimpleName() + " as true."); } else { StringParser parser; String help; try { parser = getParserFor(x.getType()); isSerializedFile[i] = false; help = "The " + x.getType().getSimpleName() + " value of " + argNames[i]; } catch (NoJSAPParserForThisTypeException e) { parser = JSAP.STRING_PARSER; isSerializedFile[i] = true; help = "A serialized " + x.getType().getSimpleName() + " file to initialize " + argNames[i]; } option = new UnflaggedOption(argNames[i], parser, JSAP.REQUIRED, help); } jsap.registerParameter(option); i++; } JSAPResult args = jsap.parse(rawArguments); if (jsap.messagePrinted()) System.exit(1); LOGGER.info("Initializing..."); Object[] arguments = new Object[argNames.length]; i = 0; for (String argName : argNames) { if (isSerializedFile[i]) arguments[i] = SerializationUtils.read(args.getString(argName)); else arguments[i] = args.getObject(argName); i++; } T object = constructor.newInstance(arguments); LOGGER.info("Ready."); return new JsapResultsWithObject<T>(args, object); }
public final String getHtmlDescription() { StringBuilder sb = new StringBuilder(); sb.append("<html><body><p>GReQL function <font color=\"blue\"><strong>") .append(name) .append("</strong></font></p><dl>"); assert (functionClass.getConstructors().length == 1); Constructor<?> cons = functionClass.getConstructors()[0]; Description consDesc = cons.getAnnotation(Description.class); for (Signature sig : signatures) { Description funDesc = sig.evaluateMethod.getAnnotation(Description.class); if (funDesc == null) { funDesc = consDesc; } if (funDesc == null) { continue; } Class<?> ret = sig.evaluateMethod.getReturnType(); String returnType = Types.getGreqlTypeName(ret); boolean acceptsType = sig.parameterTypes[sig.parameterTypes.length - 1] == TypeCollection.class; sb.append("<dt><strong><font color=\"purple\">") .append(returnType) .append(" <font color=\"blue\">") .append(name) .append("</font></strong>"); if (acceptsType) { sb.append(" { <font color=\"#008000\">types...</font> } "); } sb.append("("); String delim = ""; int i = 0; for (String p : funDesc.params()) { if ((i == 0) && needsGraphArgument) { // don't show Graph argument ++i; continue; } if ((i == 0) && needsEvaluatorArgument) { // don't show evaluator argument ++i; continue; } if ((i == (sig.parameterTypes.length - 1)) && acceptsType) { // don't show TypeCollection argument ++i; continue; } Class<?> cls = sig.parameterTypes[i++]; String type = Types.getGreqlTypeName(cls); sb.append(delim) .append("<strong><font color=\"purple\">") .append(type) .append("</font></strong> ") .append(p); delim = ", "; } sb.append(")</dt><dd>").append(funDesc.description()).append("</dd>"); } sb.append("</dl></body></html>"); return sb.toString(); }