diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/ServerBeanCustomizer.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/ServerBeanCustomizer.java index f2a39b300..817c0b392 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/ServerBeanCustomizer.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/ServerBeanCustomizer.java @@ -24,15 +24,15 @@ import org.apache.cxf.annotations.UseAsyncMethod; import org.apache.cxf.frontend.ServerFactoryBean; +import org.apache.cxf.jaxws.handler.logical.LogicalHandlerInInterceptor; +import org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor; import org.apache.cxf.jaxws.support.JaxWsEndpointImpl; import org.apache.cxf.message.Message; import org.apache.cxf.service.ServiceImpl; import org.apache.cxf.transport.http.DestinationRegistry; import org.apache.cxf.transport.http.HTTPTransportFactory; -import org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean; import org.jboss.ws.api.util.ServiceLoader; import org.jboss.ws.common.configuration.BasicConfigResolver; -import org.jboss.ws.common.deployment.DefaultHttpEndpoint; import org.jboss.wsf.spi.classloading.ClassLoaderProvider; import org.jboss.wsf.spi.deployment.AnnotationsInfo; import org.jboss.wsf.spi.deployment.ArchiveDeployment; @@ -43,6 +43,7 @@ import org.jboss.wsf.stack.cxf.deployment.EndpointImpl; import org.jboss.wsf.stack.cxf.deployment.WSDLFilePublisher; import org.jboss.wsf.stack.cxf.i18n.Loggers; +import org.jboss.wsf.stack.cxf.interceptor.JBossWSSOAPHandlerInterceptor; import org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingPolicyInterceptor; import org.jboss.wsf.stack.cxf.transport.JBossWSDestinationRegistryImpl; @@ -64,6 +65,22 @@ public void customize(Object beanInstance) { configureEndpoint((EndpointImpl) beanInstance); } + + if (beanInstance instanceof JaxWsEndpointImpl) + { + JaxWsEndpointImpl jaxwsEndpoint = (JaxWsEndpointImpl)beanInstance; + if (jaxwsEndpoint.getInInterceptors().removeIf(item ->item instanceof SOAPHandlerInterceptor)) { + jaxwsEndpoint.getInInterceptors().add(new JBossWSSOAPHandlerInterceptor(jaxwsEndpoint.getJaxwsBinding())); + } + + if(jaxwsEndpoint.getOutInterceptors().removeIf(item ->item instanceof SOAPHandlerInterceptor)) { + jaxwsEndpoint.getOutInterceptors().add(new JBossWSSOAPHandlerInterceptor(jaxwsEndpoint.getJaxwsBinding())); + } + jaxwsEndpoint.getInInterceptors().forEach(n -> { if (n instanceof LogicalHandlerInInterceptor) { + ((LogicalHandlerInInterceptor)n).addAfter(JBossWSSOAPHandlerInterceptor.class.getName()); + }}); + } + if (beanInstance instanceof ServerFactoryBean) { ServerFactoryBean factory = (ServerFactoryBean) beanInstance; diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java index 4eea7dd10..a12952758 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java @@ -23,8 +23,10 @@ import java.lang.reflect.Method; import java.security.Principal; import java.util.List; +import java.util.logging.Level; import jakarta.xml.ws.handler.Handler; +import jakarta.xml.ws.handler.LogicalHandler; import jakarta.xml.ws.handler.LogicalMessageContext; import jakarta.xml.ws.handler.MessageContext; @@ -63,6 +65,7 @@ public HandlerConfigInterceptor() { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); + addBefore(JBossWSSOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); skipAuth = false; } @@ -78,6 +81,7 @@ public HandlerConfigInterceptor(boolean skipAuth) { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); + addBefore(JBossWSSOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); this.skipAuth = skipAuth; } @@ -196,6 +200,20 @@ public boolean invokeProtocolHandlersHandleFault(boolean requestor, MessageConte } } + public void mepComplete(Message message) { + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + super.mepComplete(message); + } finally { + SecurityActions.setContextClassLoader(original); + } + } + + protected void checkAuthorization(MessageContext ctx) { if ((Boolean) ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/JBossWSSOAPHandlerInterceptor.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/JBossWSSOAPHandlerInterceptor.java new file mode 100644 index 000000000..adc215919 --- /dev/null +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/JBossWSSOAPHandlerInterceptor.java @@ -0,0 +1,66 @@ +/* + * 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.jboss.wsf.stack.cxf.interceptor; + +import jakarta.xml.ws.Binding; +import jakarta.xml.ws.handler.Handler; +import jakarta.xml.ws.handler.soap.SOAPHandler; +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor; +import org.jboss.wsf.stack.cxf.JAXPDelegateClassLoader; + +import javax.xml.namespace.QName; +import java.util.HashSet; +import java.util.Set; +/** + * SOAPHandlerInterceptor uses correct Thread Context Class Loader + * to getHeaders() from {@code SOAPHandler} + * This customized JBossWSSOAPHandlerInterceptor is to fix JBWS-4444 + * @author ema@redhat.com + */ +public class JBossWSSOAPHandlerInterceptor extends SOAPHandlerInterceptor { + public JBossWSSOAPHandlerInterceptor(Binding binding) { + super(binding); + } + + @Override + public Set getUnderstoodHeaders() { + Set understood = new HashSet<>(); + for (Handler h : getBinding().getHandlerChain()) { + if (h instanceof SOAPHandler) { + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + Set headers = CastUtils.cast(((SOAPHandler) h).getHeaders()); + if (headers != null) { + understood.addAll(headers); + } + } finally { + SecurityActions.setContextClassLoader(original); + } + + } + } + return understood; + } + +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java index ed1ca7aa3..4ef59f0ae 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java @@ -31,6 +31,9 @@ public HelloBean() { @jakarta.jws.WebMethod public String hello(String name) { + if (name.isEmpty()) { + throw new IllegalArgumentException("Empty name"); + } return "Hello " + name; } } diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java index 6a85c7055..a4438ee94 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java @@ -22,6 +22,8 @@ import java.io.File; import java.net.URL; import javax.xml.namespace.QName; + +import jakarta.xml.ws.soap.SOAPFaultException; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit5.ArquillianExtension; @@ -66,6 +68,12 @@ public void testWS() throws Exception { Service service = Service.create(wsdlURL, serviceName); Hello proxy = (Hello) service.getPort(portName, Hello.class); Assertions.assertEquals("Hello jbossws", proxy.hello("jbossws")); + try { + proxy.hello(""); + fail("An exception is expected to test the LoggingHandler.handleFault()"); + } catch(Exception e) { + Assertions.assertInstanceOf(SOAPFaultException.class, e, "unexpected exception"); + } } diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java index 2e36558fc..48e198f8b 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java @@ -37,16 +37,19 @@ public boolean handleMessage(SOAPMessageContext soapMessageContext) { @Override public Set getHeaders() { + new DelegateBean(); return Collections.emptySet(); } @Override public boolean handleFault(SOAPMessageContext soapMessageContext) { + new DelegateBean(); return true; } @Override public void close(MessageContext messageContext) { // no-operation + new DelegateBean(); } }