/* * JBoss, Home of Professional Open Source. * Copyright 2013, 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 org.jboss.jbossts.txbridge.outbound; import java.util.Iterator; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.xml.soap.Name; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPHeaderElement; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.Handler; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPMessageContext; import com.arjuna.ats.jta.TransactionManager; import com.arjuna.mw.wst.common.SOAPUtil; import com.arjuna.webservices.wsarj.ArjunaConstants; /** * * @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * */ public abstract class AbstractJTAOverWSATHandler<C extends MessageContext> implements Handler<C> { /** * Delegate handler does all the work if context propagation is enabled. */ private final JaxWSTxOutboundBridgeHandler delegateHandler = new JaxWSTxOutboundBridgeHandler(); /** * Delegates message handling to the JaxWSTxOutboundBridgeHandler if either JTAOverWSATFeature or default context * propagation is enabled. * * @see org.jboss.jbossts.txbridge.outbound.JaxWSTxOutboundBridgeHandler#handleMessage(MessageContext) * * @param context * @return true on success, false on error */ @Override public boolean handleMessage(C context) { if (isContextPropagationEnabled(context) && isJTATransactionOnThread() && !isWSATContext(context)) { return delegateHandler.handleMessage(context); } return true; } /** * Delegates fault handling to the JaxWSTxOutboundBridgeHandler if either JTAOverWSATFeature or default context propagation * is enabled. * * @see org.jboss.jbossts.txbridge.outbound.JaxWSTxOutboundBridgeHandler#handleFault(MessageContext) * * @param context * @return true on success, false on error */ @Override public boolean handleFault(C context) { if (isContextPropagationEnabled(context) && isJTATransactionOnThread() && !isWSATContext(context)) { return delegateHandler.handleFault(context); } return true; } /** * Delegates to the JaxWSTxOutboundBridgeHandler. * * @see org.jboss.jbossts.txbridge.outbound.JaxWSTxOutboundBridgeHandler#close(MessageContext) * * @param context */ @Override public void close(MessageContext context) { delegateHandler.close(context); } /** * Checks if current thread is already associated with JTA transaction. * * @return true if thread has a transaction and false if not. */ private boolean isJTATransactionOnThread() { boolean isJTATransaction = false; try { final Transaction transaction = TransactionManager.transactionManager().getTransaction(); isJTATransaction = transaction != null; } catch (SystemException e) { } return isJTATransaction; } /** * Checks if message context contains WS-AT header element. * * @param context * @return true if WS-AT header element exists and false if not. */ private boolean isWSATContext(final MessageContext context) { boolean isWSATContext = false; if (context instanceof SOAPMessageContext) { final SOAPMessageContext soapMessageContext = (SOAPMessageContext) context; final SOAPHeaderElement soapHeaderElement = getHeaderElement(soapMessageContext, ArjunaConstants.WSARJ_NAMESPACE, ArjunaConstants.WSARJ_ELEMENT_INSTANCE_IDENTIFIER); isWSATContext = soapHeaderElement != null; } return isWSATContext; } /** * Extracts and returns SOAP header element from the SOAP message context based on <code>uri</code> and <code>name</code>. * * @param soapMessageContext * @param uri * @param name * @return SOAP header element if such element existed and <code>null</code> if not. */ private SOAPHeaderElement getHeaderElement(final SOAPMessageContext soapMessageContext, final String uri, final String name) { SOAPHeaderElement soapHeaderElement = null; try { final SOAPMessage soapMessage = soapMessageContext.getMessage(); final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope(); final SOAPHeader soapHeader = soapEnvelope.getHeader(); if (soapHeader != null) { soapHeaderElement = getHeaderElement(soapHeader, uri, name); } } catch (SOAPException e) { } return soapHeaderElement; } /** * Extracts and returns SOAP header element from the SOAP header based on <code>uri</code> and <code>name</code>. * * @param soapHeader * @param uri * @param name * @return SOAP header element if such element existed and <code>null</code> if not. */ private SOAPHeaderElement getHeaderElement(final SOAPHeader soapHeader, final String uri, final String name) throws SOAPException { @SuppressWarnings("unchecked") final Iterator<SOAPHeaderElement> iterator = SOAPUtil.getChildElements(soapHeader); while (iterator.hasNext()) { final SOAPHeaderElement current = iterator.next(); final Name currentName = current.getElementName(); if ((currentName != null) && match(name, currentName.getLocalName()) && match(uri, currentName.getURI())) { return current; } } return null; } /** * Compares two objects. * * @param lhs * @param rhs * @return true|false */ private boolean match(final Object lhs, final Object rhs) { if (lhs == null) { return rhs == null; } return lhs.equals(rhs); } /** * Checks if JTAOverWSATHandler should propagate JTA context over WS-AT. * * @param context * @return true|false */ protected abstract boolean isContextPropagationEnabled(C context); }