use of io.micronaut.core.annotation.AnnotationClassValue in project micronaut-core by micronaut-projects.
the class GroovyAnnotationMetadataBuilder method readAnnotationValue.
@Override
protected Object readAnnotationValue(AnnotatedNode originatingElement, AnnotatedNode member, String memberName, Object annotationValue) {
if (annotationValue instanceof ConstantExpression) {
if (annotationValue instanceof AnnotationConstantExpression) {
AnnotationConstantExpression ann = (AnnotationConstantExpression) annotationValue;
AnnotationNode value = (AnnotationNode) ann.getValue();
final AnnotationValue<?> av = readNestedAnnotationValue(originatingElement, value);
if (member instanceof MethodNode && ((MethodNode) member).getReturnType().isArray()) {
return new AnnotationValue[] { av };
} else {
return av;
}
} else {
return ((ConstantExpression) annotationValue).getValue();
}
} else if (annotationValue instanceof PropertyExpression) {
PropertyExpression pe = (PropertyExpression) annotationValue;
if (pe.getObjectExpression() instanceof ClassExpression) {
ClassExpression ce = (ClassExpression) pe.getObjectExpression();
ClassNode propertyType = ce.getType();
if (propertyType.isEnum()) {
return pe.getPropertyAsString();
} else {
if (propertyType.isResolved()) {
Class typeClass = propertyType.getTypeClass();
try {
final Field f = ReflectionUtils.getRequiredField(typeClass, pe.getPropertyAsString());
f.setAccessible(true);
return f.get(typeClass);
} catch (Throwable e) {
// ignore
}
}
}
}
} else if (annotationValue instanceof ClassExpression) {
return new AnnotationClassValue<>(((ClassExpression) annotationValue).getType().getName());
} else if (annotationValue instanceof ListExpression) {
ListExpression le = (ListExpression) annotationValue;
List<Object> converted = new ArrayList<>();
Class<?> arrayType = Object.class;
for (Expression exp : le.getExpressions()) {
if (exp instanceof PropertyExpression) {
PropertyExpression propertyExpression = (PropertyExpression) exp;
Expression valueExpression = propertyExpression.getProperty();
Expression objectExpression = propertyExpression.getObjectExpression();
if (valueExpression instanceof ConstantExpression && objectExpression instanceof ClassExpression) {
Object value = ((ConstantExpression) valueExpression).getValue();
if (value != null) {
if (value instanceof CharSequence) {
value = value.toString();
}
ClassNode enumType = objectExpression.getType();
if (enumType.isResolved()) {
arrayType = enumType.getTypeClass();
} else {
arrayType = String.class;
}
converted.add(value);
}
}
}
if (exp instanceof AnnotationConstantExpression) {
arrayType = AnnotationValue.class;
AnnotationConstantExpression ann = (AnnotationConstantExpression) exp;
AnnotationNode value = (AnnotationNode) ann.getValue();
converted.add(readNestedAnnotationValue(originatingElement, value));
} else if (exp instanceof ConstantExpression) {
Object value = ((ConstantExpression) exp).getValue();
if (value != null) {
if (value instanceof CharSequence) {
value = value.toString();
}
arrayType = value.getClass();
converted.add(value);
}
} else if (exp instanceof ClassExpression) {
arrayType = AnnotationClassValue.class;
ClassExpression classExp = ((ClassExpression) exp);
String typeName;
if (classExp.getType().isArray()) {
typeName = "[L" + classExp.getType().getComponentType().getName() + ";";
} else {
typeName = classExp.getType().getName();
}
converted.add(new AnnotationClassValue<>(typeName));
}
}
// for some reason this is necessary to produce correct array type in Groovy
return ConversionService.SHARED.convert(converted, Array.newInstance(arrayType, 0).getClass()).orElse(null);
} else if (annotationValue instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) annotationValue;
Variable variable = ve.getAccessedVariable();
if (variable != null && variable.hasInitialExpression()) {
return readAnnotationValue(originatingElement, member, memberName, variable.getInitialExpression());
}
} else if (annotationValue != null) {
if (ClassUtils.isJavaLangType(annotationValue.getClass())) {
return annotationValue;
}
}
return null;
}
use of io.micronaut.core.annotation.AnnotationClassValue in project micronaut-core by micronaut-projects.
the class IntrospectedTypeElementVisitor method processIntrospected.
private void processIntrospected(ClassElement element, VisitorContext context, AnnotationValue<Introspected> introspected) {
final String[] packages = introspected.stringValues("packages");
final AnnotationClassValue[] classes = introspected.get("classes", AnnotationClassValue[].class, new AnnotationClassValue[0]);
final boolean metadata = introspected.booleanValue("annotationMetadata").orElse(true);
final Set<String> includes = CollectionUtils.setOf(introspected.stringValues("includes"));
final Set<String> excludes = CollectionUtils.setOf(introspected.stringValues("excludes"));
final Set<String> excludedAnnotations = CollectionUtils.setOf(introspected.stringValues("excludedAnnotations"));
final Set<String> includedAnnotations = CollectionUtils.setOf(introspected.stringValues("includedAnnotations"));
final Set<AnnotationValue> indexedAnnotations;
final Set<AnnotationValue> toIndex = CollectionUtils.setOf(introspected.get("indexed", AnnotationValue[].class, new AnnotationValue[0]));
Introspected.AccessKind[] accessKinds = introspected.enumValues("accessKind", Introspected.AccessKind.class);
Introspected.Visibility[] visibilities = introspected.enumValues("visibility", Introspected.Visibility.class);
if (ArrayUtils.isEmpty(accessKinds)) {
accessKinds = DEFAULT_ACCESS_KIND;
}
if (ArrayUtils.isEmpty(visibilities)) {
visibilities = DEFAULT_VISIBILITY;
}
Introspected.AccessKind[] finalAccessKinds = accessKinds;
Introspected.Visibility[] finalVisibilities = visibilities;
if (CollectionUtils.isEmpty(toIndex)) {
indexedAnnotations = CollectionUtils.setOf(ANN_CONSTRAINT, ANN_VALID);
} else {
toIndex.addAll(CollectionUtils.setOf(ANN_CONSTRAINT, ANN_VALID));
indexedAnnotations = toIndex;
}
if (ArrayUtils.isNotEmpty(classes)) {
AtomicInteger index = new AtomicInteger(0);
for (AnnotationClassValue aClass : classes) {
final Optional<ClassElement> classElement = context.getClassElement(aClass.getName());
classElement.ifPresent(ce -> {
if (ce.isPublic() && !isIntrospected(context, ce)) {
final AnnotationMetadata typeMetadata = ce.getAnnotationMetadata();
final AnnotationMetadata resolvedMetadata = typeMetadata == AnnotationMetadata.EMPTY_METADATA ? element.getAnnotationMetadata() : new AnnotationMetadataHierarchy(element.getAnnotationMetadata(), typeMetadata);
final BeanIntrospectionWriter writer = new BeanIntrospectionWriter(element.getName(), index.getAndIncrement(), element, ce, metadata ? resolvedMetadata : null);
processElement(metadata, includes, excludes, excludedAnnotations, indexedAnnotations, ce, writer, finalVisibilities, finalAccessKinds);
}
});
}
} else if (ArrayUtils.isNotEmpty(packages)) {
if (includedAnnotations.isEmpty()) {
context.fail("When specifying 'packages' you must also specify 'includedAnnotations' to limit scanning", element);
} else {
for (String aPackage : packages) {
ClassElement[] elements = context.getClassElements(aPackage, includedAnnotations.toArray(new String[0]));
int j = 0;
for (ClassElement classElement : elements) {
if (classElement.isAbstract() || !classElement.isPublic() || isIntrospected(context, classElement)) {
continue;
}
final BeanIntrospectionWriter writer = new BeanIntrospectionWriter(element.getName(), j++, element, classElement, metadata ? element.getAnnotationMetadata() : null);
processElement(metadata, includes, excludes, excludedAnnotations, indexedAnnotations, classElement, writer, finalVisibilities, finalAccessKinds);
}
}
}
} else {
final BeanIntrospectionWriter writer = new BeanIntrospectionWriter(element, metadata ? element.getAnnotationMetadata() : null);
processElement(metadata, includes, excludes, excludedAnnotations, indexedAnnotations, element, writer, finalVisibilities, finalAccessKinds);
}
}
use of io.micronaut.core.annotation.AnnotationClassValue in project micronaut-core by micronaut-projects.
the class AnnotationMetadataWriter method writeAnnotationDefaults.
/**
* Write annotation defaults into the given static init block.
*
* @param owningType The owning type
* @param classWriter The class writer
* @param staticInit The staitc init
* @param annotationMetadata The annotation metadata
* @param defaultsStorage The annotation defaults
* @param loadTypeMethods The load type methods
*/
@Internal
public static void writeAnnotationDefaults(Type owningType, ClassWriter classWriter, GeneratorAdapter staticInit, DefaultAnnotationMetadata annotationMetadata, Map<String, Integer> defaultsStorage, Map<String, GeneratorAdapter> loadTypeMethods) {
final Map<String, Map<CharSequence, Object>> annotationDefaultValues = annotationMetadata.annotationDefaultValues;
if (CollectionUtils.isNotEmpty(annotationDefaultValues)) {
for (Map.Entry<String, Map<CharSequence, Object>> entry : annotationDefaultValues.entrySet()) {
final Map<CharSequence, Object> annotationValues = entry.getValue();
final boolean typeOnly = CollectionUtils.isEmpty(annotationValues);
String annotationName = entry.getKey();
// skip already registered
if (typeOnly && AnnotationMetadataSupport.getRegisteredAnnotationType(annotationName).isPresent()) {
continue;
}
// Label falseCondition = new Label();
//
// staticInit.push(annotationName);
// staticInit.invokeStatic(TYPE_DEFAULT_ANNOTATION_METADATA, METHOD_ARE_DEFAULTS_REGISTERED);
// staticInit.push(true);
// staticInit.ifCmp(Type.BOOLEAN_TYPE, GeneratorAdapter.EQ, falseCondition);
// staticInit.visitLabel(new Label());
invokeLoadClassValueMethod(owningType, classWriter, staticInit, loadTypeMethods, new AnnotationClassValue(annotationName));
if (!typeOnly) {
pushStringMapOf(staticInit, annotationValues, true, null, v -> pushValue(owningType, classWriter, staticInit, v, defaultsStorage, loadTypeMethods, true));
staticInit.invokeStatic(TYPE_DEFAULT_ANNOTATION_METADATA, METHOD_REGISTER_ANNOTATION_DEFAULTS);
} else {
staticInit.invokeStatic(TYPE_DEFAULT_ANNOTATION_METADATA, METHOD_REGISTER_ANNOTATION_TYPE);
}
// staticInit.visitLabel(falseCondition);
}
if (annotationMetadata.repeated != null && !annotationMetadata.repeated.isEmpty()) {
Map<String, String> repeated = new HashMap<>();
for (Map.Entry<String, String> e : annotationMetadata.repeated.entrySet()) {
repeated.put(e.getValue(), e.getKey());
}
AnnotationMetadataSupport.removeCoreRepeatableAnnotations(repeated);
if (!repeated.isEmpty()) {
pushStringMapOf(staticInit, repeated, true, null, v -> pushValue(owningType, classWriter, staticInit, v, defaultsStorage, loadTypeMethods, true));
staticInit.invokeStatic(TYPE_DEFAULT_ANNOTATION_METADATA, METHOD_REGISTER_REPEATABLE_ANNOTATIONS);
}
}
}
}
use of io.micronaut.core.annotation.AnnotationClassValue in project micronaut-core by micronaut-projects.
the class AnnotationMetadataWriter method pushValue.
private static void pushValue(Type declaringType, ClassVisitor declaringClassWriter, GeneratorAdapter methodVisitor, Object value, Map<String, Integer> defaultsStorage, Map<String, GeneratorAdapter> loadTypeMethods, boolean boxValue) {
if (value == null) {
throw new IllegalStateException("Cannot map null value in: " + declaringType.getClassName());
} else if (value instanceof Boolean) {
methodVisitor.push((Boolean) value);
if (boxValue) {
pushBoxPrimitiveIfNecessary(boolean.class, methodVisitor);
}
} else if (value instanceof String) {
methodVisitor.push(value.toString());
} else if (value instanceof AnnotationClassValue) {
AnnotationClassValue acv = (AnnotationClassValue) value;
if (acv.isInstantiated()) {
methodVisitor.visitTypeInsn(NEW, TYPE_ANNOTATION_CLASS_VALUE.getInternalName());
methodVisitor.visitInsn(DUP);
methodVisitor.visitTypeInsn(NEW, getInternalName(acv.getName()));
methodVisitor.visitInsn(DUP);
methodVisitor.invokeConstructor(getTypeReferenceForName(acv.getName()), new Method(CONSTRUCTOR_NAME, getConstructorDescriptor()));
methodVisitor.invokeConstructor(TYPE_ANNOTATION_CLASS_VALUE, CONSTRUCTOR_CLASS_VALUE_WITH_INSTANCE);
} else {
invokeLoadClassValueMethod(declaringType, declaringClassWriter, methodVisitor, loadTypeMethods, acv);
}
} else if (value instanceof Enum) {
Enum enumObject = (Enum) value;
Class declaringClass = enumObject.getDeclaringClass();
Type t = Type.getType(declaringClass);
methodVisitor.getStatic(t, enumObject.name(), t);
} else if (value.getClass().isArray()) {
Class<?> jt = ReflectionUtils.getPrimitiveType(value.getClass().getComponentType());
final Type componentType = Type.getType(jt);
int len = Array.getLength(value);
if (Object.class == jt && len == 0) {
pushEmptyObjectsArray(methodVisitor);
} else {
pushNewArray(methodVisitor, jt, len);
for (int i = 0; i < len; i++) {
final Object v = Array.get(value, i);
pushStoreInArray(methodVisitor, componentType, i, len, () -> pushValue(declaringType, declaringClassWriter, methodVisitor, v, defaultsStorage, loadTypeMethods, !jt.isPrimitive()));
}
}
} else if (value instanceof Collection) {
if (((Collection<?>) value).isEmpty()) {
pushEmptyObjectsArray(methodVisitor);
} else {
List array = Arrays.asList(((Collection) value).toArray());
int len = array.size();
boolean first = true;
Class<?> arrayType = Object.class;
for (int i = 0; i < len; i++) {
Object v = array.get(i);
if (first) {
arrayType = v == null ? Object.class : v.getClass();
pushNewArray(methodVisitor, arrayType, len);
first = false;
}
Class<?> finalArrayType = arrayType;
pushStoreInArray(methodVisitor, Type.getType(arrayType), i, len, () -> pushValue(declaringType, declaringClassWriter, methodVisitor, v, defaultsStorage, loadTypeMethods, !finalArrayType.isPrimitive()));
}
}
} else if (value instanceof Long) {
methodVisitor.push(((Long) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(long.class, methodVisitor);
}
} else if (value instanceof Double) {
methodVisitor.push(((Double) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(double.class, methodVisitor);
}
} else if (value instanceof Float) {
methodVisitor.push(((Float) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(float.class, methodVisitor);
}
} else if (value instanceof Byte) {
methodVisitor.push(((Byte) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(byte.class, methodVisitor);
}
} else if (value instanceof Short) {
methodVisitor.push(((Short) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(short.class, methodVisitor);
}
} else if (value instanceof Character) {
methodVisitor.push(((Character) value));
if (boxValue) {
pushBoxPrimitiveIfNecessary(char.class, methodVisitor);
}
} else if (value instanceof Number) {
methodVisitor.push(((Number) value).intValue());
if (boxValue) {
pushBoxPrimitiveIfNecessary(ReflectionUtils.getPrimitiveType(value.getClass()), methodVisitor);
}
} else if (value instanceof io.micronaut.core.annotation.AnnotationValue) {
io.micronaut.core.annotation.AnnotationValue data = (io.micronaut.core.annotation.AnnotationValue) value;
String annotationName = data.getAnnotationName();
Map<CharSequence, Object> values = data.getValues();
Type annotationValueType = Type.getType(io.micronaut.core.annotation.AnnotationValue.class);
methodVisitor.newInstance(annotationValueType);
methodVisitor.dup();
methodVisitor.push(annotationName);
pushStringMapOf(methodVisitor, values, true, null, v -> pushValue(declaringType, declaringClassWriter, methodVisitor, v, defaultsStorage, loadTypeMethods, true));
Integer defaultIndex = defaultsStorage.get(annotationName);
if (defaultIndex == null) {
methodVisitor.push(annotationName);
methodVisitor.invokeStatic(Type.getType(AnnotationMetadataSupport.class), METHOD_GET_DEFAULT_VALUES);
methodVisitor.dup();
int localIndex = methodVisitor.newLocal(Type.getType(Map.class));
methodVisitor.storeLocal(localIndex);
defaultsStorage.put(annotationName, localIndex);
} else {
methodVisitor.loadLocal(defaultIndex);
}
methodVisitor.invokeConstructor(annotationValueType, CONSTRUCTOR_ANNOTATION_VALUE_AND_MAP);
} else {
methodVisitor.visitInsn(ACONST_NULL);
}
}
use of io.micronaut.core.annotation.AnnotationClassValue in project micronaut-core by micronaut-projects.
the class EnvironmentConvertibleValuesMap method get.
@Override
public <T> Optional<T> get(CharSequence name, ArgumentConversionContext<T> conversionContext) {
V value = map.get(name);
if (value instanceof AnnotationClassValue) {
AnnotationClassValue acv = (AnnotationClassValue) value;
return environment.convert(acv, conversionContext);
} else if (value instanceof CharSequence) {
PropertyPlaceholderResolver placeholderResolver = environment.getPlaceholderResolver();
String str = doResolveIfNecessary((CharSequence) value, placeholderResolver);
return environment.convert(str, conversionContext);
} else if (value instanceof String[]) {
PropertyPlaceholderResolver placeholderResolver = environment.getPlaceholderResolver();
String[] resolved = Arrays.stream((String[]) value).flatMap(val -> {
try {
String[] values = placeholderResolver.resolveRequiredPlaceholder(val, String[].class);
return Arrays.stream(values);
} catch (ConfigurationException e) {
return Stream.of(doResolveIfNecessary(val, placeholderResolver));
}
}).toArray(String[]::new);
return environment.convert(resolved, conversionContext);
} else if (value instanceof io.micronaut.core.annotation.AnnotationValue[]) {
io.micronaut.core.annotation.AnnotationValue[] annotationValues = (io.micronaut.core.annotation.AnnotationValue[]) value;
io.micronaut.core.annotation.AnnotationValue[] b = new AnnotationValue[annotationValues.length];
for (int i = 0; i < annotationValues.length; i++) {
io.micronaut.core.annotation.AnnotationValue annotationValue = annotationValues[i];
b[i] = new EnvironmentAnnotationValue(environment, annotationValue);
}
return environment.convert(b, conversionContext);
} else if (value instanceof io.micronaut.core.annotation.AnnotationValue) {
io.micronaut.core.annotation.AnnotationValue av = (io.micronaut.core.annotation.AnnotationValue) value;
av = new EnvironmentAnnotationValue(environment, av);
return environment.convert(av, conversionContext);
} else {
return super.get(name, conversionContext);
}
}
Aggregations