You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2016/12/06 10:19:57 UTC
tomee git commit: TOMEE-1982 @RunAs for nested calls only
Repository: tomee
Updated Branches:
refs/heads/master 61c6522b3 -> 0711ccbc6
TOMEE-1982 @RunAs for nested calls only
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/0711ccbc
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/0711ccbc
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/0711ccbc
Branch: refs/heads/master
Commit: 0711ccbc6cfc680534c9d76d6a915830283b28c7
Parents: 61c6522
Author: rmannibucau <rm...@apache.org>
Authored: Tue Dec 6 11:19:49 2016 +0100
Committer: rmannibucau <rm...@apache.org>
Committed: Tue Dec 6 11:19:49 2016 +0100
----------------------------------------------------------------------
.../core/security/AbstractSecurityService.java | 35 ++++-----
.../core/singleton/SingletonContainer.java | 16 ++++
.../core/stateful/StatefulContainer.java | 50 +++++++++++-
.../core/stateless/StatelessContainer.java | 16 ++++
.../org/apache/openejb/threads/task/CUTask.java | 14 +++-
.../core/security/RoleAllowedAndRunAsTest.java | 80 ++++++++++++++++++++
.../apache/openejb/core/security/RunAsTest.java | 23 ++++--
.../threads/SecurityPropagationTest.java | 31 +++++---
8 files changed, 223 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
index 1c6e9dd..17b2585 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
@@ -151,34 +151,31 @@ public abstract class AbstractSecurityService implements DestroyableResource, Se
final String moduleID = newContext.getBeanContext().getModuleID();
PolicyContext.setContextID(moduleID);
- Subject runAsSubject = getRunAsSubject(newContext.getBeanContext());
- if (oldContext != null && runAsSubject == null) {
- runAsSubject = getRunAsSubject(oldContext.getBeanContext());
- }
-
final ProvidedSecurityContext providedSecurityContext = newContext.get(ProvidedSecurityContext.class);
SecurityContext securityContext = oldContext != null ? oldContext.get(SecurityContext.class) :
(providedSecurityContext != null ? providedSecurityContext.context : null);
- if (providedSecurityContext == null) {
- if (runAsSubject != null) {
-
- securityContext = new SecurityContext(runAsSubject);
-
- } else if (securityContext == null) {
-
- final Identity identity = clientIdentity.get();
- if (identity != null) {
- securityContext = new SecurityContext(identity.subject);
- } else {
- securityContext = defaultContext;
- }
+ if (providedSecurityContext == null && (securityContext == null || securityContext == defaultContext)) {
+ final Identity identity = clientIdentity.get();
+ if (identity != null) {
+ securityContext = new SecurityContext(identity.subject);
+ } else {
+ securityContext = defaultContext;
}
}
newContext.set(SecurityContext.class, securityContext);
}
- protected Subject getRunAsSubject(final BeanContext callingBeanContext) {
+ public UUID overrideWithRunAsContext(final ThreadContext ctx, final BeanContext newContext, final BeanContext oldContext) {
+ Subject runAsSubject = getRunAsSubject(newContext);
+ if (oldContext != null && runAsSubject == null) {
+ runAsSubject = getRunAsSubject(oldContext);
+ }
+ ctx.set(SecurityContext.class, new SecurityContext(runAsSubject));
+ return disassociate();
+ }
+
+ public Subject getRunAsSubject(final BeanContext callingBeanContext) {
if (callingBeanContext == null) {
return null;
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java b/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
index b6551b0..87775ac 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
@@ -29,6 +29,7 @@ import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
+import org.apache.openejb.core.security.AbstractSecurityService;
import org.apache.openejb.core.timer.EjbTimerService;
import org.apache.openejb.core.transaction.TransactionPolicy;
import org.apache.openejb.core.webservices.AddressingSupport;
@@ -44,6 +45,7 @@ import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import javax.interceptor.AroundInvoke;
+import javax.security.auth.login.LoginException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
@@ -178,7 +180,14 @@ public class SingletonContainer implements RpcContainer {
final ThreadContext callContext = new ThreadContext(beanContext, primKey);
final ThreadContext oldCallContext = ThreadContext.enter(callContext);
final CurrentCreationalContext currentCreationalContext = beanContext.get(CurrentCreationalContext.class);
+ Object runAs = null;
try {
+ if (oldCallContext != null) {
+ final BeanContext oldBc = oldCallContext.getBeanContext();
+ if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
+ runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(callContext, beanContext, oldBc);
+ }
+ }
final boolean authorized = type == InterfaceType.TIMEOUT || getSecurityService().isCallerAuthorized(callMethod, type);
@@ -212,6 +221,13 @@ public class SingletonContainer implements RpcContainer {
return _invoke(callMethod, runMethod, args, instance, callContext, type);
} finally {
+ if (runAs != null) {
+ try {
+ securityService.associate(runAs);
+ } catch (final LoginException e) {
+ // no-op
+ }
+ }
ThreadContext.exit(oldCallContext);
if (currentCreationalContext != null) {
currentCreationalContext.remove();
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java b/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
index e1f58f8..9eca1d8 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
@@ -35,6 +35,7 @@ import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
+import org.apache.openejb.core.security.AbstractSecurityService;
import org.apache.openejb.core.stateful.Cache.CacheFilter;
import org.apache.openejb.core.stateful.Cache.CacheListener;
import org.apache.openejb.core.transaction.BeanTransactionPolicy;
@@ -74,6 +75,7 @@ import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.SynchronizationType;
+import javax.security.auth.login.LoginException;
import javax.transaction.Transaction;
import java.io.Serializable;
import java.lang.reflect.Method;
@@ -392,7 +394,15 @@ public class StatefulContainer implements RpcContainer {
final ThreadContext createContext = new ThreadContext(beanContext, primaryKey);
final ThreadContext oldCallContext = ThreadContext.enter(createContext);
+ Object runAs = null;
try {
+ if (oldCallContext != null) {
+ final BeanContext oldBc = oldCallContext.getBeanContext();
+ if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
+ runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(createContext, beanContext, oldBc);
+ }
+ }
+
// Security check
checkAuthorization(callMethod, interfaceType);
@@ -471,6 +481,13 @@ public class StatefulContainer implements RpcContainer {
return new ProxyInfo(beanContext, primaryKey);
} finally {
+ if (runAs != null) {
+ try {
+ securityService.associate(runAs);
+ } catch (final LoginException e) {
+ // no-op
+ }
+ }
ThreadContext.exit(oldCallContext);
}
}
@@ -496,7 +513,14 @@ public class StatefulContainer implements RpcContainer {
final ThreadContext callContext = new ThreadContext(beanContext, primKey);
final ThreadContext oldCallContext = ThreadContext.enter(callContext);
+ Object runAs = null;
try {
+ if (oldCallContext != null) {
+ final BeanContext oldBc = oldCallContext.getBeanContext();
+ if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
+ runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(callContext, beanContext, oldBc);
+ }
+ }
// Security check
if (!internalRemove) {
checkAuthorization(callMethod, interfaceType);
@@ -592,6 +616,13 @@ public class StatefulContainer implements RpcContainer {
}
}
} finally {
+ if (runAs != null) {
+ try {
+ securityService.associate(runAs);
+ } catch (final LoginException e) {
+ // no-op
+ }
+ }
if (!retain) {
try {
callContext.setCurrentOperation(Operation.PRE_DESTROY);
@@ -642,7 +673,15 @@ public class StatefulContainer implements RpcContainer {
final ThreadContext callContext = new ThreadContext(beanContext, primKey);
final ThreadContext oldCallContext = ThreadContext.enter(callContext);
final CurrentCreationalContext currentCreationalContext = beanContext.get(CurrentCreationalContext.class);
+ Object runAs = null;
try {
+ if (oldCallContext != null) {
+ final BeanContext oldBc = oldCallContext.getBeanContext();
+ if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
+ runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(callContext, beanContext, oldBc);
+ }
+ }
+
// Security check
checkAuthorization(callMethod, interfaceType);
@@ -699,6 +738,13 @@ public class StatefulContainer implements RpcContainer {
}
return returnValue;
} finally {
+ if (runAs != null) {
+ try {
+ securityService.associate(runAs);
+ } catch (final LoginException e) {
+ // no-op
+ }
+ }
ThreadContext.exit(oldCallContext);
if (currentCreationalContext != null) {
currentCreationalContext.remove();
@@ -732,7 +778,7 @@ public class StatefulContainer implements RpcContainer {
throw new InvalidateReferenceException(new NoSuchObjectException("Not Found"));
}
- // remember instance until it is returned to the cache
+ // remember instance until it is returned to the cache
checkedOutInstances.put(primaryKey, instance);
}
}
@@ -749,7 +795,7 @@ public class StatefulContainer implements RpcContainer {
// concurrent calls are not allowed, lock only once
lockAcquired = currLock.tryLock();
} else {
- // try to get a lock within the specified period.
+ // try to get a lock within the specified period.
try {
lockAcquired = currLock.tryLock(accessTimeout.getTime(), accessTimeout.getUnit());
} catch (final InterruptedException e) {
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
index 11f43e0..ea44ea4 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
@@ -30,6 +30,7 @@ import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
+import org.apache.openejb.core.security.AbstractSecurityService;
import org.apache.openejb.core.timer.EjbTimerService;
import org.apache.openejb.core.transaction.TransactionPolicy;
import org.apache.openejb.core.webservices.AddressingSupport;
@@ -51,6 +52,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import javax.interceptor.AroundInvoke;
+import javax.security.auth.login.LoginException;
import static org.apache.openejb.core.transaction.EjbTransactionUtil.afterInvoke;
import static org.apache.openejb.core.transaction.EjbTransactionUtil.createTransactionPolicy;
@@ -171,7 +173,14 @@ public class StatelessContainer implements org.apache.openejb.RpcContainer, Dest
Instance bean = null;
final CurrentCreationalContext currentCreationalContext = beanContext.get(CurrentCreationalContext.class);
+ Object runAs = null;
try {
+ if (oldCallContext != null) {
+ final BeanContext oldBc = oldCallContext.getBeanContext();
+ if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
+ runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(callContext, beanContext, oldBc);
+ }
+ }
//Check auth before overriding context
final boolean authorized = type == InterfaceType.TIMEOUT || this.securityService.isCallerAuthorized(callMethod, type);
@@ -202,6 +211,13 @@ public class StatelessContainer implements org.apache.openejb.RpcContainer, Dest
}
return _invoke(callMethod, runMethod, args, bean, callContext, type);
} finally {
+ if (runAs != null) {
+ try {
+ securityService.associate(runAs);
+ } catch (final LoginException e) {
+ // no-op
+ }
+ }
if (bean != null) {
if (callContext.isDiscardInstance()) {
this.instanceManager.discardInstance(callContext, bean);
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/main/java/org/apache/openejb/threads/task/CUTask.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/threads/task/CUTask.java b/container/openejb-core/src/main/java/org/apache/openejb/threads/task/CUTask.java
index e3bef03..e2270a6 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/threads/task/CUTask.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/threads/task/CUTask.java
@@ -32,6 +32,7 @@ import java.util.Collection;
import java.util.concurrent.Callable;
public abstract class CUTask<T> extends ManagedTaskListenerTask implements Comparable<Object> {
+ // TODO: get rid of it as a static thing, make it owned by the executor probably
private static final SecurityService SECURITY_SERVICE = SystemInstance.get().getComponent(SecurityService.class);
// only updated in container startup phase, no concurrency possible, don't use it at runtime!
@@ -61,9 +62,16 @@ public abstract class CUTask<T> extends ManagedTaskListenerTask implements Compa
associate = false;
}
final ThreadContext threadContext = ThreadContext.getThreadContext();
- initialContext = new Context(
- associate, stateTmp, threadContext == null ? null : threadContext.get(AbstractSecurityService.SecurityContext.class),
- threadContext, Thread.currentThread().getContextClassLoader(), null);
+ final AbstractSecurityService.SecurityContext sc = threadContext == null ? null : threadContext.get(AbstractSecurityService.SecurityContext.class);
+ if (threadContext != null && threadContext.getBeanContext() != null &&
+ (threadContext.getBeanContext().getRunAs() != null || threadContext.getBeanContext().getRunAsUser() != null)) {
+ initialContext = new Context(
+ associate, stateTmp,
+ new AbstractSecurityService.SecurityContext(AbstractSecurityService.class.cast(SECURITY_SERVICE).getRunAsSubject(threadContext.getBeanContext())),
+ threadContext, Thread.currentThread().getContextClassLoader(), null);
+ } else {
+ initialContext = new Context(associate, stateTmp, sc, threadContext, Thread.currentThread().getContextClassLoader(), null);
+ }
if (CONTAINER_LISTENERS.length > 0) {
containerListenerStates = new Object[CONTAINER_LISTENERS.length];
for (int i = 0; i < CONTAINER_LISTENERS.length; i++) {
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/test/java/org/apache/openejb/core/security/RoleAllowedAndRunAsTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/security/RoleAllowedAndRunAsTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/security/RoleAllowedAndRunAsTest.java
new file mode 100644
index 0000000..c131c8d
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/core/security/RoleAllowedAndRunAsTest.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.core.security;
+
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.SecurityService;
+import org.apache.openejb.testing.Classes;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import javax.annotation.security.RolesAllowed;
+import javax.annotation.security.RunAs;
+import javax.ejb.EJB;
+import javax.ejb.EJBContext;
+import javax.ejb.Singleton;
+import javax.security.auth.login.LoginException;
+
+import static org.junit.Assert.assertEquals;
+
+@Classes(innerClassesAsBean = true)
+@RunWith(ApplicationComposer.class)
+public class RoleAllowedAndRunAsTest {
+ @EJB
+ private DefaultRoles bean;
+
+ @Test
+ public void run() throws LoginException {
+ final SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class);
+ final Object id = securityService.login("jonathan", "secret");
+ securityService.associate(id);
+ try {
+ assertEquals("jonathan > role1", bean.stack());
+ } finally {
+ securityService.disassociate();
+ securityService.logout(id);
+ }
+ }
+
+ @Singleton
+ public static class Identity {
+ @Resource
+ private EJBContext context;
+
+ @RolesAllowed("role1")
+ public String name() {
+ return context.getCallerPrincipal().getName();
+ }
+ }
+
+ @Singleton
+ @RunAs("role1")
+ @RolesAllowed("committer")
+ public static class DefaultRoles {
+ @Resource
+ private EJBContext context;
+
+ @EJB
+ private Identity identity;
+
+ public String stack() {
+ return context.getCallerPrincipal().getName() + " > " + identity.name();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/test/java/org/apache/openejb/core/security/RunAsTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/security/RunAsTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/security/RunAsTest.java
index fffa829..db4ee2a 100644
--- a/container/openejb-core/src/test/java/org/apache/openejb/core/security/RunAsTest.java
+++ b/container/openejb-core/src/test/java/org/apache/openejb/core/security/RunAsTest.java
@@ -17,7 +17,7 @@
package org.apache.openejb.core.security;
import org.apache.openejb.junit.ApplicationComposer;
-import org.apache.openejb.testing.Module;
+import org.apache.openejb.testing.Classes;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,13 +30,9 @@ import javax.ejb.Singleton;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+@Classes(innerClassesAsBean = true)
@RunWith(ApplicationComposer.class)
public class RunAsTest {
- @Module
- public Class<?>[] beans() {
- return new Class<?>[]{MyRunAsBean.class};
- }
-
@EJB
private MyRunAsBean bean;
@@ -49,6 +45,21 @@ public class RunAsTest {
@RunAs("foo")
@Singleton
public static class MyRunAsBean {
+ @EJB
+ private Delegate delegate;
+
+ public String principal() {
+ return delegate.principal();
+ }
+
+ public boolean isInRole() {
+ return delegate.isInRole();
+ }
+ }
+
+ @RunAs("foo")
+ @Singleton
+ public static class Delegate {
@Resource
private SessionContext ctx;
http://git-wip-us.apache.org/repos/asf/tomee/blob/0711ccbc/container/openejb-core/src/test/java/org/apache/openejb/threads/SecurityPropagationTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/threads/SecurityPropagationTest.java b/container/openejb-core/src/test/java/org/apache/openejb/threads/SecurityPropagationTest.java
index b96797b..f2fcafe 100644
--- a/container/openejb-core/src/test/java/org/apache/openejb/threads/SecurityPropagationTest.java
+++ b/container/openejb-core/src/test/java/org/apache/openejb/threads/SecurityPropagationTest.java
@@ -16,10 +16,8 @@
*/
package org.apache.openejb.threads;
-import org.apache.openejb.jee.EnterpriseBean;
-import org.apache.openejb.jee.StatelessBean;
import org.apache.openejb.junit.ApplicationComposer;
-import org.apache.openejb.testing.Module;
+import org.apache.openejb.testing.Classes;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -33,28 +31,35 @@ import javax.enterprise.concurrent.ManagedExecutorService;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.security.Principal;
+import java.util.concurrent.Callable;
import java.util.concurrent.Future;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+@Classes(innerClassesAsBean = true)
@RunWith(ApplicationComposer.class)
public class SecurityPropagationTest {
- @Module
- public EnterpriseBean bean() {
- return new StatelessBean(ExecutorBean.class).localBean();
- }
-
@EJB
private ExecutorBean bean;
@Test
public void checkItIsTrue() throws Exception {
- bean.submit(new RunnableTest()).get();
+ assertEquals("tomee", bean.submit(new RunnableTest()).get());
}
@Stateless
@RunAs("tomee")
public static class ExecutorBean {
+ @EJB
+ private Delegate delegate;
+
+ public Future<?> submit(final RunnableTest task) throws NamingException {
+ return delegate.submit(task);
+ }
+ }
+
+ @Stateless
+ public static class Delegate {
@Resource
private ManagedExecutorService executorService;
@@ -68,7 +73,7 @@ public class SecurityPropagationTest {
}
}
- public static class RunnableTest implements Runnable {
+ public static class RunnableTest implements Callable<String> {
private Principal expectedPrincipal;
public void setExpectedPrincipal(final Principal expectedPrincipal) {
@@ -76,7 +81,7 @@ public class SecurityPropagationTest {
}
@Override
- public void run() {
+ public String call() throws Exception {
try {
Thread.sleep(200);
} catch (final InterruptedException e) {
@@ -106,6 +111,8 @@ public class SecurityPropagationTest {
throw new IllegalStateException("the caller principal " + callerPrincipal + " is not the expected " + expectedPrincipal);
}
}
+
+ return callerPrincipal.getName();
}
}