Skip to content

Commit

Permalink
[EJBCLIENT-253] Emulate org.jboss.ejb.client.EJBClientContext.registe…
Browse files Browse the repository at this point in the history
…rInterceptor(ILorg/jboss/ejb/client/EJBClientInterceptor;)
  • Loading branch information
gaol committed Aug 23, 2017
1 parent 21864c9 commit 66a5d2c
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 1 deletion.
92 changes: 91 additions & 1 deletion src/main/java/org/jboss/ejb/client/EJBClientContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Supplier;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -73,6 +74,10 @@ public final class EJBClientContext extends Attachable implements Contextual<EJB

private static final EJBTransportProvider[] NO_TRANSPORT_PROVIDERS = new EJBTransportProvider[0];

private static final EJBClientInterceptor.Registration[] NO_INTERCEPTORS = new EJBClientInterceptor.Registration[0];
private static final AtomicReferenceFieldUpdater<EJBClientContext, EJBClientInterceptor.Registration[]> registrationsUpdater = AtomicReferenceFieldUpdater.newUpdater(EJBClientContext.class, EJBClientInterceptor.Registration[].class, "registrations");
private volatile EJBClientInterceptor.Registration[] registrations = NO_INTERCEPTORS;

/**
* The discovery attribute name which contains the application and module name of the located EJB.
*/
Expand Down Expand Up @@ -329,6 +334,82 @@ static InterceptorList getClassPathInterceptorList() {
}
}

/**
* Register a client interceptor with this client context.
* <p/>
* If the passed <code>clientInterceptor</code> is already added to this context with the same <code>priority</code>
* then this method just returns the old {@link org.jboss.ejb.client.EJBClientInterceptor.Registration}. If however,
* the <code>clientInterceptor</code> is already registered in this context with a different priority then this method
* throws an {@link IllegalArgumentException}
*
* @param priority the absolute priority of this interceptor (lower runs earlier; higher runs later)
* @param clientInterceptor the interceptor to register
* @return a handle which may be used to later remove this registration
* @throws IllegalArgumentException if the given interceptor is {@code null}, the priority is less than 0, or the
* given interceptor is already registered with a different priority
* @deprecated
*/
public EJBClientInterceptor.Registration registerInterceptor(final int priority, final EJBClientInterceptor clientInterceptor) throws IllegalArgumentException {
Assert.checkNotNullParam("clientInterceptor", clientInterceptor);
final EJBClientInterceptor.Registration newRegistration = new EJBClientInterceptor.Registration(this, clientInterceptor, priority);
EJBClientInterceptor.Registration[] oldRegistrations, newRegistrations;
do {
oldRegistrations = registrations;
for (EJBClientInterceptor.Registration oldRegistration : oldRegistrations) {
if (oldRegistration.getInterceptor() == clientInterceptor) {
if (oldRegistration.compareTo(newRegistration) == 0) {
// This means that a client interceptor which has already been added to this context,
// is being added with the same priority. In such cases, this new registration request
// is effectively a no-op and we just return the old registration
return oldRegistration;
}
// else {
// // This means that a client interceptor which has been added to this context, is being added
// // again with a different priority. We don't allow that to happen
// throw Logs.MAIN.ejbClientInterceptorAlreadyRegistered(clientInterceptor);
// }
}
}
final int length = oldRegistrations.length;
newRegistrations = Arrays.copyOf(oldRegistrations, length + 1);
newRegistrations[length] = newRegistration;
Arrays.sort(newRegistrations);
} while (!registrationsUpdater.compareAndSet(this, oldRegistrations, newRegistrations));
return newRegistration;
}

void removeInterceptor(final EJBClientInterceptor.Registration registration) {
EJBClientInterceptor.Registration[] oldRegistrations, newRegistrations;
do {
oldRegistrations = registrations;
newRegistrations = null;
final int length = oldRegistrations.length;
final int newLength = length - 1;
if (length == 1) {
if (oldRegistrations[0] == registration) {
newRegistrations = NO_INTERCEPTORS;
}
} else {
for (int i = 0; i < length; i++) {
if (oldRegistrations[i] == registration) {
if (i == newLength) {
newRegistrations = Arrays.copyOf(oldRegistrations, newLength);
break;
} else {
newRegistrations = new EJBClientInterceptor.Registration[newLength];
if (i > 0) System.arraycopy(oldRegistrations, 0, newRegistrations, 0, i);
System.arraycopy(oldRegistrations, i + 1, newRegistrations, i, newLength - i);
break;
}
}
}
}
if (newRegistrations == null) {
return;
}
} while (!registrationsUpdater.compareAndSet(this, oldRegistrations, newRegistrations));
}

/**
* Get the context manager. Simply calls the {@code static} method {@link #getContextManager()}.
*
Expand Down Expand Up @@ -740,7 +821,16 @@ InterceptorList getClassPathInterceptors() {
}

InterceptorList getGlobalInterceptors() {
return globalInterceptors;
return globalInterceptors.combine(registeredInterceptors());
}

private InterceptorList registeredInterceptors() {
final EJBClientInterceptor.Registration[] currentRegistrations = this.registrations.clone();
ArrayList<EJBClientInterceptorInformation> al = new ArrayList<>();
for (EJBClientInterceptor.Registration r: currentRegistrations) {
al.add(EJBClientInterceptorInformation.forInstance(r.getInterceptor()));
}
return InterceptorList.ofList(al);
}

Map<String, InterceptorList> getConfiguredPerClassInterceptors() {
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/org/jboss/ejb/client/EJBClientInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,36 @@ default void handleInvocationAsyncFailure(EJBClientInvocationContext context, Ex
default SessionID handleSessionCreation(EJBSessionCreationInvocationContext context) throws Exception {
return context.proceed();
}

/**
* An interceptor registration handle.
* @deprecated
*/
@Deprecated
class Registration implements Comparable<Registration> {
private final EJBClientContext clientContext;
private final EJBClientInterceptor interceptor;
private final int priority;

Registration(final EJBClientContext clientContext, final EJBClientInterceptor interceptor, final int priority) {
this.clientContext = clientContext;
this.interceptor = interceptor;
this.priority = priority;
}

/**
* Remove this registration.
*/
public void remove() {
clientContext.removeInterceptor(this);
}

EJBClientInterceptor getInterceptor() {
return interceptor;
}

public int compareTo(final Registration o) {
return Integer.signum(priority - o.priority);
}
}
}

0 comments on commit 66a5d2c

Please sign in to comment.