Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get rid of indexes in ObserverGenerator and AnnotationLiteralProcessor #743

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@

import static org.jboss.shamrock.deployment.annotations.ExecutionTime.STATIC_INIT;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Singleton;

Expand All @@ -52,15 +55,15 @@
import org.jboss.protean.gizmo.MethodCreator;
import org.jboss.protean.gizmo.MethodDescriptor;
import org.jboss.protean.gizmo.ResultHandle;
import org.jboss.shamrock.deployment.annotations.BuildProducer;
import org.jboss.shamrock.deployment.annotations.BuildStep;
import org.jboss.shamrock.deployment.annotations.Record;
import org.jboss.shamrock.arc.deployment.AdditionalBeanBuildItem;
import org.jboss.shamrock.arc.deployment.AnnotationsTransformerBuildItem;
import org.jboss.shamrock.arc.deployment.BeanContainerBuildItem;
import org.jboss.shamrock.arc.deployment.BeanDeploymentValidatorBuildItem;
import org.jboss.shamrock.arc.deployment.UnremovableBeanBuildItem.BeanClassAnnotationExclusion;
import org.jboss.shamrock.arc.deployment.UnremovableBeanBuildItem;
import org.jboss.shamrock.arc.deployment.UnremovableBeanBuildItem.BeanClassAnnotationExclusion;
import org.jboss.shamrock.deployment.annotations.BuildProducer;
import org.jboss.shamrock.deployment.annotations.BuildStep;
import org.jboss.shamrock.deployment.annotations.Record;
import org.jboss.shamrock.deployment.builditem.FeatureBuildItem;
import org.jboss.shamrock.deployment.builditem.GeneratedClassBuildItem;
import org.jboss.shamrock.deployment.builditem.substrate.ReflectiveClassBuildItem;
Expand Down Expand Up @@ -92,8 +95,6 @@ public class SchedulerProcessor {

static final String INVOKER_SUFFIX = "_ScheduledInvoker";

private static final AtomicInteger INVOKER_INDEX = new AtomicInteger();

@BuildStep
List<AdditionalBeanBuildItem> beans() {
List<AdditionalBeanBuildItem> beans = new ArrayList<>();
Expand Down Expand Up @@ -235,8 +236,13 @@ private String generateInvoker(BeanInfo bean, MethodInfo method, ProcessorClassO
} else {
baseName = DotNames.simpleName(bean.getImplClazz().name());
}
StringBuilder sigBuilder = new StringBuilder();
sigBuilder.append(method.name()).append("_").append(method.returnType().name().toString());
for (Type i : method.parameters()) {
sigBuilder.append(i.name().toString());
}
String targetPackage = DotNames.packageName(bean.getImplClazz().name());
String generatedName = targetPackage.replace('.', '/') + "/" + baseName + INVOKER_SUFFIX + INVOKER_INDEX.incrementAndGet();
String generatedName = targetPackage.replace('.', '/') + "/" + baseName + INVOKER_SUFFIX + "_" + method.name() + "_" + sha1(sigBuilder.toString());

ClassCreator invokerCreator = ClassCreator.builder().classOutput(processorClassOutput).className(generatedName).interfaces(ScheduledInvoker.class)
.build();
Expand Down Expand Up @@ -266,6 +272,16 @@ private String generateInvoker(BeanInfo bean, MethodInfo method, ProcessorClassO
invokerCreator.close();
return generatedName.replace('/', '.');
}

static String sha1(String value) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
return Base64.getUrlEncoder()
.encodeToString(md.digest(value.getBytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}

private Object getValue(AnnotationValue annotationValue) {
switch (annotationValue.kind()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class AnnotationLiteralGenerator extends AbstractGenerator {

static final String ANNOTATION_LITERAL_SUFFIX = "_AnnotationLiteral";

static final String SHARED_SUFFIX = "_Shared";

private static final Logger LOGGER = Logger.getLogger(AnnotationLiteralGenerator.class);

/**
Expand Down Expand Up @@ -292,15 +294,14 @@ static String componentType(MethodInfo method) {
return arrayType.component().name().toString();
}

static String generatedSharedName(DotName annotationName, AtomicInteger index) {
// com.foo.MyQualifier -> com.foo.MyQualifier1_AnnotationLiteral
return DotNames.packageName(annotationName) + "." + DotNames.simpleName(annotationName) + index.incrementAndGet()
+ AnnotationLiteralGenerator.ANNOTATION_LITERAL_SUFFIX;
static String generatedSharedName(DotName annotationName) {
// com.foo.MyQualifier -> com.foo.MyQualifier1_Shared_AnnotationLiteral
return DotNames.packageName(annotationName) + "." + DotNames.simpleName(annotationName) + SHARED_SUFFIX + ANNOTATION_LITERAL_SUFFIX;
}

static String generatedLocalName(String targetPackage, String simpleName, AtomicInteger index) {
// com.foo.MyQualifier -> com.bar.MyQualifier1_AnnotationLiteral
return targetPackage + "." + simpleName + index.incrementAndGet() + AnnotationLiteralGenerator.ANNOTATION_LITERAL_SUFFIX;
static String generatedLocalName(String targetPackage, String simpleName, String hash) {
// com.foo.MyQualifier -> com.bar.MyQualifier_somehashvalue_AnnotationLiteral
return targetPackage + "." + simpleName + hash + AnnotationLiteralGenerator.ANNOTATION_LITERAL_SUFFIX;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
Expand All @@ -42,14 +41,11 @@
*/
class AnnotationLiteralProcessor {

private final AtomicInteger index;

private final ComputingCache<Key, Literal> cache;

AnnotationLiteralProcessor(boolean shared, Predicate<DotName> applicationClassPredicate) {
this.index = new AtomicInteger(1);
this.cache = shared ? new ComputingCache<>(key -> {
return new Literal(AnnotationLiteralGenerator.generatedSharedName(key.annotationName, index), applicationClassPredicate.test(key.annotationName),
return new Literal(AnnotationLiteralGenerator.generatedSharedName(key.annotationName), applicationClassPredicate.test(key.annotationName),
key.annotationClass.methods()
.stream()
.filter(m -> !m.name().equals(Methods.CLINIT) && !m.name().equals(Methods.INIT))
Expand All @@ -72,7 +68,7 @@ ComputingCache<Key, Literal> getCache() {
* @param annotationClass
* @param annotationInstance
* @param targetPackage
* @return an annotation literal class name
* @return an annotation literal result handle
*/
ResultHandle process(BytecodeCreator bytecode, ClassOutput classOutput, ClassInfo annotationClass, AnnotationInstance annotationInstance,
String targetPackage) {
Expand All @@ -99,9 +95,9 @@ ResultHandle process(BytecodeCreator bytecode, ClassOutput classOutput, ClassInf
return bytecode
.newInstance(MethodDescriptor.ofConstructor(literal.className,
literal.constructorParams.stream().map(m -> m.returnType().name().toString()).toArray()), constructorParams);

} else {
String literalClassName = AnnotationLiteralGenerator.generatedLocalName(targetPackage, DotNames.simpleName(annotationClass.name()), index);
String literalClassName = AnnotationLiteralGenerator.generatedLocalName(targetPackage, DotNames.simpleName(annotationClass.name()),
Hashes.sha1(annotationInstance.toString()));
AnnotationLiteralGenerator.createAnnotationLiteral(classOutput, annotationClass, annotationInstance, literalClassName);
return bytecode.newInstance(MethodDescriptor.ofConstructor(literalClassName));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import org.jboss.protean.arc.InjectableBean;
import org.jboss.protean.arc.InjectableContext;
import org.jboss.protean.arc.processor.ResourceOutput.Resource;
import org.jboss.protean.gizmo.AssignableResultHandle;
import org.jboss.protean.gizmo.BytecodeCreator;
import org.jboss.protean.gizmo.ClassCreator;
import org.jboss.protean.gizmo.DescriptorUtils;
import org.jboss.protean.gizmo.FieldCreator;
Expand Down Expand Up @@ -178,10 +180,13 @@ void implementDelegate(ClassCreator clientProxy, String providerTypeName, FieldD
// getContext()
ResultHandle context = creator.invokeInterfaceMethod(MethodDescriptor.ofMethod(ArcContainer.class, "getContext", InjectableContext.class, Class.class),
container, scope);
// new CreationalContextImpl<>()
ResultHandle creationContext = creator.newInstance(MethodDescriptor.ofConstructor(CreationalContextImpl.class));
ResultHandle result = creator.invokeInterfaceMethod(MethodDescriptors.CONTEXT_GET, context, bean, creationContext);
creator.returnValue(result);
AssignableResultHandle ret = creator.createVariable(Object.class);
creator.assign(ret, creator.invokeInterfaceMethod(MethodDescriptors.CONTEXT_GET_IF_PRESENT, context, bean));
BytecodeCreator isNullBranch = creator.ifNull(ret).trueBranch();
// Create a new contextual instance - new CreationalContextImpl<>()
ResultHandle creationContext = isNullBranch.newInstance(MethodDescriptor.ofConstructor(CreationalContextImpl.class));
isNullBranch.assign(ret, isNullBranch.invokeInterfaceMethod(MethodDescriptors.CONTEXT_GET, context, bean, creationContext));
creator.returnValue(ret);
}

void implementGetContextualInstance(ClassCreator clientProxy, String providerTypeName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

import javax.enterprise.inject.spi.EventContext;
Expand Down Expand Up @@ -67,8 +66,6 @@ public class ObserverGenerator extends AbstractGenerator {

private static final Logger LOGGER = Logger.getLogger(ObserverGenerator.class);

private static final AtomicInteger OBSERVER_INDEX = new AtomicInteger();

private final AnnotationLiteralProcessor annotationLiterals;

private final Predicate<DotName> applicationClassPredicate;
Expand Down Expand Up @@ -97,13 +94,20 @@ Collection<Resource> generate(ObserverInfo observer, ReflectionRegistration refl
declaringClassBase = DotNames.simpleName(declaringClass.name());
}

String baseName = declaringClassBase + OBSERVER_SUFFIX + OBSERVER_INDEX.incrementAndGet();
StringBuilder sigBuilder = new StringBuilder();
sigBuilder.append(observer.getObserverMethod().name())
.append("_")
.append(observer.getObserverMethod().returnType().name().toString());
for(org.jboss.jandex.Type paramType : observer.getObserverMethod().parameters()) {
sigBuilder.append(paramType.name().toString());
}
String baseName = declaringClassBase + OBSERVER_SUFFIX + "_" + observer.getObserverMethod().name() + "_" + Hashes.sha1(sigBuilder.toString());
String generatedName = DotNames.packageName(declaringClass.name()).replace('.', '/') + "/" + baseName;

boolean isApplicationClass = applicationClassPredicate.test(observer.getObserverMethod().declaringClass().name());
ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass, name -> name.equals(generatedName) ? SpecialType.OBSERVER : null);

// Foo_Observer1 implements ObserverMethod<T>
// Foo_Observer_fooMethod_hash implements ObserverMethod<T>
ClassCreator observerCreator = ClassCreator.builder().classOutput(classOutput).className(generatedName).interfaces(InjectableObserverMethod.class)
.build();

Expand Down Expand Up @@ -176,7 +180,10 @@ protected void implementNotify(ObserverInfo observer, ClassCreator observerCreat

ResultHandle declaringProviderHandle = notify
.readInstanceField(FieldDescriptor.of(observerCreator.getClassName(), "declaringProvider", InjectableBean.class.getName()), notify.getThis());
ResultHandle ctxHandle = notify.newInstance(MethodDescriptor.ofConstructor(CreationalContextImpl.class));

// It is safe to skip CreationalContext.release() for normal scoped declaring provider and no injection points
boolean skipRelease = observer.getDeclaringBean().getScope().isNormal() && observer.getInjection().injectionPoints.isEmpty();
ResultHandle ctxHandle = skipRelease ? notify.loadNull() : notify.newInstance(MethodDescriptor.ofConstructor(CreationalContextImpl.class));
ResultHandle declaringProviderInstanceHandle = notify.invokeInterfaceMethod(MethodDescriptors.INJECTABLE_REF_PROVIDER_GET, declaringProviderHandle,
ctxHandle);

Expand Down Expand Up @@ -222,7 +229,9 @@ protected void implementNotify(ObserverInfo observer, ClassCreator observerCreat
}

// Destroy @Dependent instances injected into method parameters of an observer method
notify.invokeInterfaceMethod(MethodDescriptors.CREATIONAL_CTX_RELEASE, ctxHandle);
if (!skipRelease) {
notify.invokeInterfaceMethod(MethodDescriptors.CREATIONAL_CTX_RELEASE, ctxHandle);
}

// If the declaring bean is @Dependent we must destroy the instance afterwards
if (ScopeInfo.DEPENDENT.equals(observer.getDeclaringBean().getScope())) {
Expand Down