You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2007/04/24 10:57:59 UTC

svn commit: r531838 - in /incubator/openejb/trunk/openejb3/container/openejb-core/src: main/java/org/apache/openejb/assembler/classic/ main/java/org/apache/openejb/config/ main/java/org/apache/openejb/core/stateless/ test/java/org/apache/openejb/core/s...

Author: jlaskowski
Date: Tue Apr 24 01:57:57 2007
New Revision: 531838

URL: http://svn.apache.org/viewvc?view=rev&rev=531838
Log:
OPENEJB-569 @Resource WebServiceContext injection

Thanks Jarek Gawor!

Added:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java   (with props)
Modified:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/JaxWsWebServiceInvocationTest.java

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java?view=diff&rev=531838&r1=531837&r2=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java Tue Apr 24 01:57:57 2007
@@ -45,6 +45,8 @@
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionSynchronizationRegistry;
 import javax.transaction.UserTransaction;
+import javax.xml.ws.WebServiceContext;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Iterator;
@@ -241,6 +243,11 @@
                 Class<?> type = Class.forName(referenceInfo.resourceEnvRefType, true, EJBContext.class.getClassLoader());
                 if (EJBContext.class.isAssignableFrom(type)) {
                     String jndiName = "java:comp/EJBContext";
+                    linkRef = new LinkRef(jndiName);
+                    bindings.put(normalize(referenceInfo.resourceEnvRefName), linkRef);
+                    continue;
+                } else if (WebServiceContext.class.equals(type)) {
+                    String jndiName = "java:comp/WebServiceContext";
                     linkRef = new LinkRef(jndiName);
                     bindings.put(normalize(referenceInfo.resourceEnvRefName), linkRef);
                     continue;

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?view=diff&rev=531838&r1=531837&r2=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java Tue Apr 24 01:57:57 2007
@@ -127,7 +127,8 @@
             "javax.ejb.MessageDrivenContext",
             "javax.transaction.UserTransaction",
             "javax.jms.Queue",
-            "javax.jms.Topic"
+            "javax.jms.Topic",
+            "javax.xml.ws.WebServiceContext"
     ));
 
     public static final Set<String> knownEnvironmentEntries = new TreeSet<String>(Arrays.asList(

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java?view=auto&rev=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java Tue Apr 24 01:57:57 2007
@@ -0,0 +1,55 @@
+/**
+ * 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.stateless;
+
+import java.security.Principal;
+
+import javax.ejb.SessionContext;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.handler.MessageContext;
+
+import org.apache.openejb.core.ThreadContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class EjbWebServiceContext implements WebServiceContext {
+
+    private SessionContext context;
+    
+    public EjbWebServiceContext(SessionContext context) {
+        this.context = context;
+    }
+    
+    public MessageContext getMessageContext() {
+        ThreadContext threadContext = ThreadContext.getThreadContext();
+        MessageContext messageContext = threadContext.get(MessageContext.class);
+        if (messageContext == null) {
+            throw new IllegalStateException("Only calls on the service-endpoint have a MessageContext.");
+        }
+        return messageContext;
+    }
+
+    public Principal getUserPrincipal() {
+        return this.context.getCallerPrincipal();
+    }
+
+    public boolean isUserInRole(String roleName) {
+        return this.context.isCallerInRole(roleName);
+    }
+
+}

Propchange: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/EjbWebServiceContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?view=diff&rev=531838&r1=531837&r2=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java Tue Apr 24 01:57:57 2007
@@ -257,6 +257,7 @@
             ThreadContext.getThreadContext().set(javax.xml.rpc.handler.MessageContext.class, (javax.xml.rpc.handler.MessageContext) messageContext);
             returnValue = interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, params);
         } else if (messageContext instanceof javax.xml.ws.handler.MessageContext) {
+            ThreadContext.getThreadContext().set(javax.xml.ws.handler.MessageContext.class, (javax.xml.ws.handler.MessageContext) messageContext);
             returnValue = interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, params);
         }
         return returnValue;

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?view=diff&rev=531838&r1=531837&r2=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Tue Apr 24 01:57:57 2007
@@ -28,6 +28,7 @@
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.transaction.TransactionManager;
+import javax.xml.ws.WebServiceContext;
 
 import org.apache.openejb.Injection;
 import org.apache.openejb.OpenEJBException;
@@ -100,7 +101,7 @@
             BaseContext.State[] originalAllowedStates = callContext.getCurrentAllowedStates();
 
             try {
-                Context ctx = deploymentInfo.getJndiEnc();
+                Context ctx = deploymentInfo.getJndiEnc();                
                 SessionContext sessionContext;
                 try {
                     sessionContext = (SessionContext) ctx.lookup("java:comp/EJBContext");
@@ -108,15 +109,24 @@
                     sessionContext = createSessionContext();
                     // TODO: This should work
                     ctx.bind("java:comp/EJBContext", sessionContext);
-                }
+                }                              
                 if (javax.ejb.SessionBean.class.isAssignableFrom(beanClass) || hasSetSessionContext(beanClass)) {
                     callContext.setCurrentOperation(Operation.INJECTION);
                     callContext.setCurrentAllowedStates(StatelessContext.getStates());                    
                     objectRecipe.setProperty("sessionContext", new StaticRecipe(sessionContext));
+                }     
+                
+                WebServiceContext wsContext;
+                try {
+                    wsContext = (WebServiceContext) ctx.lookup("java:comp/WebServiceContext");
+                } catch (NamingException e) {
+                    wsContext = new EjbWebServiceContext(sessionContext);
+                    ctx.bind("java:comp/WebServiceContext", wsContext);
                 }
+                
                 for (Injection injection : deploymentInfo.getInjections()) {
                     try {
-                        String jndiName = injection.getJndiName();
+                        String jndiName = injection.getJndiName();    
                         Object object = ctx.lookup("java:comp/env/" + jndiName);
                         if (object instanceof String) {
                             String string = (String) object;

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/JaxWsWebServiceInvocationTest.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/JaxWsWebServiceInvocationTest.java?view=diff&rev=531838&r1=531837&r2=531838
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/JaxWsWebServiceInvocationTest.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/JaxWsWebServiceInvocationTest.java Tue Apr 24 01:57:57 2007
@@ -1,376 +1,376 @@
-/**
- * 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.stateless;
-
-import junit.framework.TestCase;
-import org.apache.openejb.core.ivm.naming.InitContextFactory;
-import org.apache.openejb.config.ConfigurationFactory;
-import org.apache.openejb.config.EjbModule;
-import org.apache.openejb.assembler.classic.Assembler;
-import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
-import org.apache.openejb.assembler.classic.TransactionServiceInfo;
-import org.apache.openejb.assembler.classic.SecurityServiceInfo;
-import org.apache.openejb.assembler.classic.ConnectionManagerInfo;
-import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
-import org.apache.openejb.assembler.classic.EjbJarInfo;
-import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.jee.StatelessBean;
-import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.spi.ContainerSystem;
-import org.apache.openejb.DeploymentInfo;
-import org.apache.openejb.RpcContainer;
-
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.InvocationContext;
-import javax.interceptor.Interceptors;
-import javax.jws.WebService;
-import javax.xml.ws.handler.MessageContext;
-import javax.xml.ws.WebServiceContext;
-import javax.annotation.Resource;
-import javax.ejb.SessionContext;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.Collection;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.lang.reflect.Method;
-
-/**
- * The point of this test case is to verify that OpenEJB is accurately performing
- * it's part of a WebServiceProvider to OpenEJB invocation as it relates to JAX-RPC.
- *
- * In the agreement between OpenEJB and the Web Service Provider, the Web Service Provider
- * must supply the MessageContext and an Interceptor as the arguments of the standard
- * container.invoke method call.
- *
- * OpenEJB must ensure the MessageContext is exposed via the SessionContext.getMessageContext
- * and ensure that the interceptor is added to the chain just after the other interceptors and
- * before the bean method itself is invoked.
- *
- * @version $Rev$ $Date$
- */
-public class JaxWsWebServiceInvocationTest extends TestCase {
-
-    public void testWebServiceInvocations() throws Exception {
-        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
-
-        ConfigurationFactory config = new ConfigurationFactory();
-        Assembler assembler = new Assembler();
-
-        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
-        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
-        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class,"PseudoSecurityService",null,"PseudoSecurityService",null));
-
-        assembler.createConnectionManager(config.configureService(ConnectionManagerInfo.class));
-
-        assembler.createContainer(config.configureService(StatelessSessionContainerInfo.class));
-
-
-        EjbJarInfo ejbJar = config.configureApplication(buildTestApp());
-
-        assembler.createApplication(ejbJar);
-
-        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
-
-        DeploymentInfo deploymentInfo = containerSystem.getDeploymentInfo("EchoBean");
-
-        assertNotNull(deploymentInfo);
-
-        assertEquals("ServiceEndpointInterface", EchoServiceEndpoint.class, deploymentInfo.getServiceEndpointInterface());
-
-
-        // OK, Now let's fake a web serivce invocation coming from any random
-        // web service provider.  The web serivce provider needs supply
-        // the MessageContext and an interceptor to do the marshalling as
-        // the arguments of the standard container.invoke signature.
-
-        // So let's create a fake message context.
-        MessageContext messageContext = new FakeMessageContext();
-
-        // Now let's create a fake interceptor as would be supplied by the
-        // web service provider.  Instead of writing "fake" marshalling
-        // code that would pull the arguments from the soap message, we'll
-        // just give it the argument values directly.
-        Object webServiceProviderInterceptor = new FakeWebServiceProviderInterceptor("Hello world");
-
-        // Ok, now we have the two arguments expected on a JAX-RPC Web Service
-        // invocation as per the OpenEJB-specific agreement between OpenEJB
-        // and the Web Service Provider
-        Object[] args = new Object[]{messageContext, webServiceProviderInterceptor};
-
-        // Let's grab the container as the Web Service Provider would do and
-        // perform an invocation
-        RpcContainer container = (RpcContainer) deploymentInfo.getContainer();
-
-        Method echoMethod = EchoServiceEndpoint.class.getMethod("echo", String.class);
-
-        String value = (String)container.invoke("EchoBean", echoMethod, args, null);
-
-        assertCalls(Call.values());
-        calls.clear();
-        assertEquals("Hello world" , value);
-        
-    }
-
-    private void assertCalls(Call... expectedCalls) {
-        List expected = Arrays.asList(expectedCalls);
-        assertEquals(join("\n", expected) , join("\n", calls));
-    }
-
-    public static enum Call {
-        EjbInterceptor_Invoke_BEFORE,
-        Bean_Invoke_BEFORE,
-        WebServiceProvider_Invoke_BEFORE,
-        Bean_Invoke,
-        WebServiceProvider_Invoke_AFTER,
-        Bean_Invoke_AFTER,
-        EjbInterceptor_Invoke_AFTER,
-    }
-
-    public static List<Call> calls = new ArrayList<Call>();
-
-    public EjbModule buildTestApp() {
-        EjbJar ejbJar = new EjbJar();
-
-        StatelessBean bean = ejbJar.addEnterpriseBean(new StatelessBean(EchoBean.class));
-        bean.setServiceEndpoint(EchoServiceEndpoint.class.getName());
-
-        return new EjbModule(this.getClass().getClassLoader(), this.getClass().getSimpleName(), "test", ejbJar, null);
-    }
-
-    @Interceptors({PlainEjbInterceptor.class})
-    public static class EchoBean {
-
-        @Resource
-        private SessionContext ctx;
-
-        @Resource
-        private WebServiceContext wsContext;
-
-        @AroundInvoke
-        public Object invoke(InvocationContext context) throws Exception {
-
-            /**
-             * For JAX-WS invocations context.getContextData() must return the 
-             * JAX-WS MessageContex. As per the agreement between OpenEJB and the Web Service Provider
-             * the MessageContex should have been passed into the container.invoke method
-             * and the container should then ensure it's available via getContextData()
-             * for the duration of this call.
-             */
-            MessageContext messageContext = (MessageContext)context.getContextData();
-            
-            junit.framework.Assert.assertNotNull("message context should not be null", messageContext);
-            junit.framework.Assert.assertTrue("the Web Service Provider's message context should be used", messageContext instanceof FakeMessageContext);
-
-            // Try to get JAX-RPC context, should throw an exception since it's JAX-WS
-            try {
-                ctx.getMessageContext();
-                junit.framework.Assert.fail("Did not throw exception");
-            } catch (IllegalStateException e) {
-                // that's expected since it's JAX-WS
-            }
-            
-            // TODO: this is not implemented yet
-            /*
-            junit.framework.Assert.assertNotNull("web service context should not be null", wsContext);
-            */
-
-            calls.add(Call.Bean_Invoke_BEFORE);
-            Object o = context.proceed();
-            calls.add(Call.Bean_Invoke_AFTER);
-            return o;
-        }
-        
-        public String echo(String data){
-            calls.add(Call.Bean_Invoke);
-            return data;
-        }
-    }
-
-    @WebService
-    public static interface EchoServiceEndpoint { 
-        String echo(String data);
-    }
-
-    /**
-     * This interceptor is here to ensure that the container
-     * still invokes interceptors normally for web serivce
-     * invocations and to also guarantee that the Web Service
-     * Provider's interceptor (which is a special OpenEJB concept)
-     * is invoked *after* all the normal ejb interceptors.
-     */
-    public static class PlainEjbInterceptor {
-
-        @AroundInvoke
-        public Object invoke(InvocationContext context) throws Exception {
-            // Track this call so we can assert proper interceptor order
-            calls.add(Call.EjbInterceptor_Invoke_BEFORE);
-            Object o = context.proceed();
-            calls.add(Call.EjbInterceptor_Invoke_AFTER);
-            return o;
-        }
-    }
-
-
-    private static String join(String delimeter, List items) {
-        StringBuffer sb = new StringBuffer();
-        for (Object item : items) {
-            sb.append(item.toString()).append(delimeter);
-        }
-        return sb.toString();
-    }
-
-
-    /**
-     * This object would be implemented by the Web Service Provider per
-     * the JAX-WS spec and supplied to us in the container.invoke method
-     * per the OpenEJB-WebServiceProvider agreement
-     */
-    public static class FakeMessageContext implements MessageContext {
-
-        private Map map = new HashMap();
-
-        public void clear() {
-            map.clear();      
-        }
-
-        public boolean containsKey(Object key) {
-            return map.containsKey(key);
-        }
-
-        public boolean containsValue(Object value) {
-            return map.containsValue(value);
-        }
-
-        public Set<Entry<String, Object>> entrySet() {
-            return map.entrySet();
-        }
-
-        public Object get(Object key) {
-            return map.get(key);
-        }
-
-        public boolean isEmpty() {
-            return map.isEmpty();
-        }
-
-        public Set<String> keySet() {
-            return map.keySet();
-        }
-
-        public Object put(String key, Object value) {
-            return map.put(key, value);
-        }
-
-        public void putAll(Map<? extends String, ? extends Object> t) {
-            map.putAll(t);
-        }
-
-        public Object remove(Object key) {
-            return map.remove(key);
-        }
-
-        public int size() {
-            return map.size();
-        }
-
-        public Collection<Object> values() {
-            return map.values();
-        }
-
-        public Scope getScope(String arg0) {
-            return null;
-        }
-
-        public void setScope(String arg0, Scope arg1) {
-        }
-
-    }
-
-    /**
-     * This object would be supplied by the Web Service Provider
-     * as per the OpenEJB-WebServiceProvider agreement and serves
-     * two purposes:
-     *
-     * 1. Executing the Handler Chain (as required by
-     * the JAX-RPC specification) in the context of the EJB Container
-     * (as required by the EJB and J2EE WebServices specifications)
-     *
-     * 2. Unmarshalling the method arguments from the SOAP message
-     * after the handlers in the Handler Chain have had a chance
-     * to modify the argument values via the SAAJ tree.
-     *
-     * The Interceptor instance given to OpenEJB is constructed
-     * and created by the Web Service Provider and should contain
-     * all the data it requires to complete it's part of the agreement.
-     *
-     * OpenEJB will not perform any injection on this object and
-     * the interceptor will be discarded so that the Web Service
-     * Provider may pass in a new Interceptor instance on every
-     * web service invocation.
-     *
-     * The Web Service Provider may pass in any object to serve
-     * the roll of the Interceptor as long as it has an @AroundInvoke
-     * method using the method signature:
-     *
-     * public Object <METHOD-NAME> (InvocationContext ctx) throws Exception
-     *
-     * Unlike typical EJB Interceptor around invoke methods, the @AroundInvoke
-     * annotation must be used and is not optional, and the method must be public.
-     */
-    public static class FakeWebServiceProviderInterceptor {
-
-        /**
-         * These would normally come from the soap message
-         */
-        private final Object[] args;
-
-        public FakeWebServiceProviderInterceptor(Object... args) {
-            this.args = args;
-        }
-
-        @AroundInvoke
-        public Object invoke(InvocationContext invocationContext) throws Exception {
-            // The interceptor of the web serivce must set the
-            // arguments it marshalls from the soap message into
-            // the InvocationContext so we can invoke the bean.
-            invocationContext.setParameters(args);
-
-            Object returnValue;
-            try {
-
-                // Track this call so we can assert proper interceptor order
-                calls.add(Call.WebServiceProvider_Invoke_BEFORE);
-
-                // handler chain "before advice" would happen here
-                returnValue = invocationContext.proceed();
-                // handler chain "after advice" would happen here
-
-                // Track this call so we can assert proper interceptor order
-                calls.add(Call.WebServiceProvider_Invoke_AFTER);
-
-            } catch (Exception e) {
-                // handler chain fault processing would happen here
-                throw e;
-            }
-            return returnValue;
-        }
-    }
-}
+/**
+ * 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.stateless;
+
+import junit.framework.TestCase;
+import org.apache.openejb.core.ivm.naming.InitContextFactory;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.ConnectionManagerInfo;
+import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
+import org.apache.openejb.assembler.classic.EjbJarInfo;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.RpcContainer;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+import javax.interceptor.Interceptors;
+import javax.jws.WebService;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.WebServiceContext;
+import javax.annotation.Resource;
+import javax.ejb.SessionContext;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.Collection;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.lang.reflect.Method;
+
+/**
+ * The point of this test case is to verify that OpenEJB is accurately performing
+ * it's part of a WebServiceProvider to OpenEJB invocation as it relates to JAX-RPC.
+ *
+ * In the agreement between OpenEJB and the Web Service Provider, the Web Service Provider
+ * must supply the MessageContext and an Interceptor as the arguments of the standard
+ * container.invoke method call.
+ *
+ * OpenEJB must ensure the MessageContext is exposed via the SessionContext.getMessageContext
+ * and ensure that the interceptor is added to the chain just after the other interceptors and
+ * before the bean method itself is invoked.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JaxWsWebServiceInvocationTest extends TestCase {
+
+    public void testWebServiceInvocations() throws Exception {
+        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
+
+        ConfigurationFactory config = new ConfigurationFactory();
+        Assembler assembler = new Assembler();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class,"PseudoSecurityService",null,"PseudoSecurityService",null));
+
+        assembler.createConnectionManager(config.configureService(ConnectionManagerInfo.class));
+
+        assembler.createContainer(config.configureService(StatelessSessionContainerInfo.class));
+
+
+        EjbJarInfo ejbJar = config.configureApplication(buildTestApp());
+
+        assembler.createApplication(ejbJar);
+
+        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+
+        DeploymentInfo deploymentInfo = containerSystem.getDeploymentInfo("EchoBean");
+
+        assertNotNull(deploymentInfo);
+
+        assertEquals("ServiceEndpointInterface", EchoServiceEndpoint.class, deploymentInfo.getServiceEndpointInterface());
+
+
+        // OK, Now let's fake a web serivce invocation coming from any random
+        // web service provider.  The web serivce provider needs supply
+        // the MessageContext and an interceptor to do the marshalling as
+        // the arguments of the standard container.invoke signature.
+
+        // So let's create a fake message context.
+        MessageContext messageContext = new FakeMessageContext();
+
+        // Now let's create a fake interceptor as would be supplied by the
+        // web service provider.  Instead of writing "fake" marshalling
+        // code that would pull the arguments from the soap message, we'll
+        // just give it the argument values directly.
+        Object webServiceProviderInterceptor = new FakeWebServiceProviderInterceptor("Hello world");
+
+        // Ok, now we have the two arguments expected on a JAX-RPC Web Service
+        // invocation as per the OpenEJB-specific agreement between OpenEJB
+        // and the Web Service Provider
+        Object[] args = new Object[]{messageContext, webServiceProviderInterceptor};
+
+        // Let's grab the container as the Web Service Provider would do and
+        // perform an invocation
+        RpcContainer container = (RpcContainer) deploymentInfo.getContainer();
+
+        Method echoMethod = EchoServiceEndpoint.class.getMethod("echo", String.class);
+
+        String value = (String)container.invoke("EchoBean", echoMethod, args, null);
+
+        assertCalls(Call.values());
+        calls.clear();
+        assertEquals("Hello world" , value);
+        
+    }
+
+    private void assertCalls(Call... expectedCalls) {
+        List expected = Arrays.asList(expectedCalls);
+        assertEquals(join("\n", expected) , join("\n", calls));
+    }
+
+    public static enum Call {
+        EjbInterceptor_Invoke_BEFORE,
+        Bean_Invoke_BEFORE,
+        WebServiceProvider_Invoke_BEFORE,
+        Bean_Invoke,
+        WebServiceProvider_Invoke_AFTER,
+        Bean_Invoke_AFTER,
+        EjbInterceptor_Invoke_AFTER,
+    }
+
+    public static List<Call> calls = new ArrayList<Call>();
+
+    public EjbModule buildTestApp() {
+        EjbJar ejbJar = new EjbJar();
+
+        StatelessBean bean = ejbJar.addEnterpriseBean(new StatelessBean(EchoBean.class));
+        bean.setServiceEndpoint(EchoServiceEndpoint.class.getName());
+
+        return new EjbModule(this.getClass().getClassLoader(), this.getClass().getSimpleName(), "test", ejbJar, null);
+    }
+
+    @Interceptors({PlainEjbInterceptor.class})
+    public static class EchoBean {
+
+        @Resource
+        private SessionContext ctx;
+
+        @Resource
+        private WebServiceContext wsContext;
+
+        @AroundInvoke
+        public Object invoke(InvocationContext context) throws Exception {
+
+            /**
+             * For JAX-WS invocations context.getContextData() must return the 
+             * JAX-WS MessageContex. As per the agreement between OpenEJB and the Web Service Provider
+             * the MessageContex should have been passed into the container.invoke method
+             * and the container should then ensure it's available via getContextData()
+             * for the duration of this call.
+             */
+            MessageContext messageContext = (MessageContext)context.getContextData();
+            
+            junit.framework.Assert.assertNotNull("message context should not be null", messageContext);
+            junit.framework.Assert.assertTrue("the Web Service Provider's message context should be used", messageContext instanceof FakeMessageContext);
+
+            // Try to get JAX-RPC context, should throw an exception since it's JAX-WS
+            try {
+                ctx.getMessageContext();
+                junit.framework.Assert.fail("Did not throw exception");
+            } catch (IllegalStateException e) {
+                // that's expected since it's JAX-WS
+            }
+            
+            // TODO: this is not implemented yet
+            /*
+            junit.framework.Assert.assertNotNull("web service context should not be null", wsContext);
+            */
+
+            calls.add(Call.Bean_Invoke_BEFORE);
+            Object o = context.proceed();
+            calls.add(Call.Bean_Invoke_AFTER);
+            return o;
+        }
+        
+        public String echo(String data){
+            calls.add(Call.Bean_Invoke);
+            return data;
+        }
+    }
+
+    @WebService
+    public static interface EchoServiceEndpoint { 
+        String echo(String data);
+    }
+
+    /**
+     * This interceptor is here to ensure that the container
+     * still invokes interceptors normally for web serivce
+     * invocations and to also guarantee that the Web Service
+     * Provider's interceptor (which is a special OpenEJB concept)
+     * is invoked *after* all the normal ejb interceptors.
+     */
+    public static class PlainEjbInterceptor {
+
+        @AroundInvoke
+        public Object invoke(InvocationContext context) throws Exception {
+            // Track this call so we can assert proper interceptor order
+            calls.add(Call.EjbInterceptor_Invoke_BEFORE);
+            Object o = context.proceed();
+            calls.add(Call.EjbInterceptor_Invoke_AFTER);
+            return o;
+        }
+    }
+
+
+    private static String join(String delimeter, List items) {
+        StringBuffer sb = new StringBuffer();
+        for (Object item : items) {
+            sb.append(item.toString()).append(delimeter);
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * This object would be implemented by the Web Service Provider per
+     * the JAX-WS spec and supplied to us in the container.invoke method
+     * per the OpenEJB-WebServiceProvider agreement
+     */
+    public static class FakeMessageContext implements MessageContext {
+
+        private Map map = new HashMap();
+
+        public void clear() {
+            map.clear();      
+        }
+
+        public boolean containsKey(Object key) {
+            return map.containsKey(key);
+        }
+
+        public boolean containsValue(Object value) {
+            return map.containsValue(value);
+        }
+
+        public Set<Entry<String, Object>> entrySet() {
+            return map.entrySet();
+        }
+
+        public Object get(Object key) {
+            return map.get(key);
+        }
+
+        public boolean isEmpty() {
+            return map.isEmpty();
+        }
+
+        public Set<String> keySet() {
+            return map.keySet();
+        }
+
+        public Object put(String key, Object value) {
+            return map.put(key, value);
+        }
+
+        public void putAll(Map<? extends String, ? extends Object> t) {
+            map.putAll(t);
+        }
+
+        public Object remove(Object key) {
+            return map.remove(key);
+        }
+
+        public int size() {
+            return map.size();
+        }
+
+        public Collection<Object> values() {
+            return map.values();
+        }
+
+        public Scope getScope(String arg0) {
+            return null;
+        }
+
+        public void setScope(String arg0, Scope arg1) {
+        }
+
+    }
+
+    /**
+     * This object would be supplied by the Web Service Provider
+     * as per the OpenEJB-WebServiceProvider agreement and serves
+     * two purposes:
+     *
+     * 1. Executing the Handler Chain (as required by
+     * the JAX-RPC specification) in the context of the EJB Container
+     * (as required by the EJB and J2EE WebServices specifications)
+     *
+     * 2. Unmarshalling the method arguments from the SOAP message
+     * after the handlers in the Handler Chain have had a chance
+     * to modify the argument values via the SAAJ tree.
+     *
+     * The Interceptor instance given to OpenEJB is constructed
+     * and created by the Web Service Provider and should contain
+     * all the data it requires to complete it's part of the agreement.
+     *
+     * OpenEJB will not perform any injection on this object and
+     * the interceptor will be discarded so that the Web Service
+     * Provider may pass in a new Interceptor instance on every
+     * web service invocation.
+     *
+     * The Web Service Provider may pass in any object to serve
+     * the roll of the Interceptor as long as it has an @AroundInvoke
+     * method using the method signature:
+     *
+     * public Object <METHOD-NAME> (InvocationContext ctx) throws Exception
+     *
+     * Unlike typical EJB Interceptor around invoke methods, the @AroundInvoke
+     * annotation must be used and is not optional, and the method must be public.
+     */
+    public static class FakeWebServiceProviderInterceptor {
+
+        /**
+         * These would normally come from the soap message
+         */
+        private final Object[] args;
+
+        public FakeWebServiceProviderInterceptor(Object... args) {
+            this.args = args;
+        }
+
+        @AroundInvoke
+        public Object invoke(InvocationContext invocationContext) throws Exception {
+            // The interceptor of the web serivce must set the
+            // arguments it marshalls from the soap message into
+            // the InvocationContext so we can invoke the bean.
+            invocationContext.setParameters(args);
+
+            Object returnValue;
+            try {
+
+                // Track this call so we can assert proper interceptor order
+                calls.add(Call.WebServiceProvider_Invoke_BEFORE);
+
+                // handler chain "before advice" would happen here
+                returnValue = invocationContext.proceed();
+                // handler chain "after advice" would happen here
+
+                // Track this call so we can assert proper interceptor order
+                calls.add(Call.WebServiceProvider_Invoke_AFTER);
+
+            } catch (Exception e) {
+                // handler chain fault processing would happen here
+                throw e;
+            }
+            return returnValue;
+        }
+    }
+}