forked from jbosstm/narayana
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LRACDIExtension.java
135 lines (120 loc) · 5.92 KB
/
LRACDIExtension.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* JBoss, Home of Professional Open Source.
* Copyright 2019, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package io.narayana.lra.client.internal.proxy.nonjaxrs;
import io.narayana.lra.client.internal.proxy.nonjaxrs.jandex.DotNames;
import io.narayana.lra.client.internal.proxy.nonjaxrs.jandex.JandexAnnotationResolver;
import io.narayana.lra.logging.LRALogger;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.util.AnnotationLiteral;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This CDI extension collects all LRA participants that contain
* one or more non-JAX-RS participant methods. The collected classes are stored
* in {@link LRAParticipantRegistry}.
*/
public class LRACDIExtension implements Extension {
private ClassPathIndexer classPathIndexer = new ClassPathIndexer();
private Index index;
private final Map<String, LRAParticipant> participants = new HashMap<>();
public void observe(@Observes AfterBeanDiscovery event, BeanManager beanManager) throws IOException, ClassNotFoundException {
index = classPathIndexer.createIndex();
List<AnnotationInstance> annotations = index.getAnnotations(DotName.createSimple("javax.ws.rs.Path"));
for (AnnotationInstance annotation : annotations) {
ClassInfo classInfo;
AnnotationTarget target = annotation.target();
if (target.kind().equals(AnnotationTarget.Kind.CLASS)) {
classInfo = target.asClass();
} else if (target.kind().equals(AnnotationTarget.Kind.METHOD)) {
classInfo = target.asMethod().declaringClass();
} else {
continue;
}
LRAParticipant participant = getAsParticipant(classInfo);
if (participant != null) {
participants.put(participant.getJavaClass().getName(), participant);
Set<Bean<?>> participantBeans = beanManager.getBeans(participant.getJavaClass(), new AnnotationLiteral<Any>() {});
if (participantBeans.isEmpty()) {
// resource is not registered as managed bean so register a custom managed instance
try {
participant.setInstance(participant.getJavaClass().newInstance());
} catch (InstantiationException | IllegalAccessException e) {
LRALogger.i18NLogger.error_cannotProcessParticipant(e);
}
}
}
}
event.addBean()
.read(beanManager.createAnnotatedType(LRAParticipantRegistry.class))
.beanClass(LRAParticipantRegistry.class)
.scope(ApplicationScoped.class)
.createWith(context -> new LRAParticipantRegistry(participants));
}
/**
* Collects all non-JAX-RS participant methods in the defined Java class
*
* @param classInfo a Jandex class info of the class to be scanned
* @return Collected methods wrapped in {@link LRAParticipant} class or null if no non-JAX-RS methods have been found
*/
private LRAParticipant getAsParticipant(ClassInfo classInfo) throws ClassNotFoundException {
if (!isLRAParticipant(classInfo)) {
return null;
}
Class<?> javaClass = getClass().getClassLoader().loadClass(classInfo.name().toString());
LRAParticipant participant = new LRAParticipant(javaClass);
return participant.hasNonJaxRsMethods() ? participant : null;
}
/**
* Returns whether the classinfo represents an LRA participant --
* Class contains LRA method and either one or both of Compensate and/or AfterLRA methods.
*
* @param classInfo Jandex class object to scan for annotations
*
* @return true if the class is a valid LRA participant, false otherwise
* @throws IllegalStateException if there is LRA annotation but no Compensate or AfterLRA is found
*/
private boolean isLRAParticipant(ClassInfo classInfo) {
Map<DotName, List<AnnotationInstance>> annotations = JandexAnnotationResolver.getAllAnnotationsFromClassInfoHierarchy(classInfo.name(), index);
if (!annotations.containsKey(DotNames.LRA)) {
return false;
} else if (!annotations.containsKey(DotNames.COMPENSATE) && !annotations.containsKey(DotNames.AFTER_LRA)) {
throw new IllegalStateException(String.format("%s: %s",
classInfo.name(), "The class contains an LRA method and no Compensate or AfterLRA method was found."));
} else {
return true;
}
}
}