Author: scheu Date: Fri Aug 6 12:31:05 2010 New Revision: 982938 URL: http://svn.apache.org/viewvc?rev=982938&view=rev Log: AXIS2-4791 Contributor:Rich Scheuerle Axis2 changes to enable the illegal character filtering during JAX-WS processing. Also added a verification test
Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ResourceInjectionTests.java axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/resourceinjection/ResourceInjectionPortTypeImpl.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/context/utils/ContextUtils.java Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ResourceInjectionTests.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ResourceInjectionTests.java?rev=982938&r1=982937&r2=982938&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ResourceInjectionTests.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/ResourceInjectionTests.java Fri Aug 6 12:31:05 2010 @@ -59,6 +59,10 @@ public class ResourceInjectionTests exte assertTrue("The response was null", response != null); assertTrue("The response was not succesful: " + response, response.indexOf("SUCCESS") >= 0); + char[] chars = new char[] {0x15}; // 0x15 is not a valid xml character..and should be filtered + String insert = new String(chars); + assertTrue("Illegal characters were not filtered: " + response, + response.indexOf(insert) < 0); } Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/resourceinjection/ResourceInjectionPortTypeImpl.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/resourceinjection/ResourceInjectionPortTypeImpl.java?rev=982938&r1=982937&r2=982938&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/resourceinjection/ResourceInjectionPortTypeImpl.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/resourceinjection/ResourceInjectionPortTypeImpl.java Fri Aug 6 12:31:05 2010 @@ -19,6 +19,7 @@ package org.apache.axis2.jaxws.sample.resourceinjection; +import org.apache.axis2.jaxws.Constants; import org.apache.axis2.jaxws.TestLogger; import org.apache.axis2.jaxws.sample.resourceinjection.sei.ResourceInjectionPortType; @@ -69,7 +70,18 @@ import javax.xml.ws.handler.MessageConte return "FAILURE: The WebServiceContext's MessageContext " + "does not have the correct wsdlOperation"; } - return "SUCCESS: " + wsdlOperation.getLocalPart(); + + String response = "SUCCESS: " + wsdlOperation.getLocalPart(); + + // Set a flag to force filtering of JAXB data. + // Also set a illegal characters in the response string + // to verify that the illegal character is removed. + msgContext.put(Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS, Boolean.TRUE); + char[] chars = new char[] {0x15}; // 0x15 is not a valid xml character + String insert = new String(chars); + response = insert + response + insert; + + return response; } @PostConstruct Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java?rev=982938&r1=982937&r2=982938&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java Fri Aug 6 12:31:05 2010 @@ -21,12 +21,14 @@ package org.apache.axis2.datasource.jaxb import org.apache.axiom.om.OMException; import org.apache.axiom.om.impl.MTOMXMLStreamWriter; +import org.apache.axiom.om.util.XMLStreamWriterRemoveIllegalChars; import org.apache.axiom.util.stax.XMLStreamReaderUtils; import org.apache.axiom.util.stax.xop.MimePartProvider; import org.apache.axiom.util.stax.xop.XOPEncodedStream; import org.apache.axiom.util.stax.xop.XOPUtils; import org.apache.axis2.context.MessageContext; import org.apache.axis2.java.security.AccessController; +import org.apache.axis2.jaxws.context.utils.ContextUtils; import org.apache.axis2.jaxws.message.OccurrenceArray; import org.apache.axis2.jaxws.message.databinding.JAXBUtils; import org.apache.axis2.jaxws.message.util.XMLStreamWriterWithOS; @@ -368,23 +370,26 @@ public class JAXBDSContext { * @param am AttachmentMarshaller, optional Attachment */ public void marshal(Object obj, - XMLStreamWriter writer) throws JAXBException { - if (log.isDebugEnabled()) { - log.debug("enter marshal"); - } + XMLStreamWriter writer) throws JAXBException { + if (log.isDebugEnabled()) { + log.debug("enter marshal"); + } + boolean installedFilter = false; + + try { // There may be a preferred classloader that should be used ClassLoader cl = getClassLoader(); - - + + // Very easy, use the Context to get the Marshaller. // Use the marshaller to write the object. JAXBContext jbc = getJAXBContext(cl); Marshaller m = JAXBUtils.getJAXBMarshaller(jbc); if (writer instanceof MTOMXMLStreamWriter && ((MTOMXMLStreamWriter) writer).getOutputFormat() != null) { String encoding = ((MTOMXMLStreamWriter) writer).getOutputFormat().getCharSetEncoding(); - + String marshallerEncoding = (String) m.getProperty(Marshaller.JAXB_ENCODING); - + // Make sure that the marshaller respects the encoding of the message. // This is accomplished by setting the encoding on the Marshaller's JAXB_ENCODING property. if (encoding == null && marshallerEncoding == null) { @@ -394,7 +399,7 @@ public class JAXBDSContext { } else { // Must set the encoding to an actual String to set it on the Marshaller if (encoding == null) { - encoding = "UTF-8"; + encoding = "UTF-8"; } if (!encoding.equalsIgnoreCase(marshallerEncoding)) { if (log.isDebugEnabled()) { @@ -406,12 +411,12 @@ public class JAXBDSContext { } else { if (log.isDebugEnabled()) { log.debug("The encoding and the marshaller's JAXB_ENCODING are both set to:" + - marshallerEncoding); + marshallerEncoding); } } } } - + AttachmentMarshaller am = createAttachmentMarshaller(writer); if (am != null) { if (DEBUG_ENABLED) { @@ -420,29 +425,40 @@ public class JAXBDSContext { m.setAttachmentMarshaller(am); } + MessageContext mc = getMessageContext(); + + // If requested install a filter to remove illegal characters + installedFilter = installFilter(mc, writer); + // Marshal the object if (getProcessType() == null) { marshalByElement(obj, - m, - writer, - true); - //!am.isXOPPackage()); + m, + writer, + true); + //!am.isXOPPackage()); } else { marshalByType(obj, - m, - writer, - getProcessType(), - isxmlList(), - getConstructionType(), - true); // Attempt to optimize by writing to OutputStream + m, + writer, + getProcessType(), + isxmlList(), + getConstructionType(), + true); // Attempt to optimize by writing to OutputStream } - + JAXBUtils.releaseJAXBMarshaller(jbc, m); - + if (log.isDebugEnabled()) { log.debug("exit marshal"); } + } finally { + // Make sure the filter is uninstalled + if (installedFilter) { + uninstallFilter(writer); + } + } } @@ -1073,4 +1089,37 @@ public class JAXBDSContext { throw new OMException(t); } } + + + /** + * Install a JAXB filter if requested + * @param mc + * @param writer + * @return true if filter installed + */ + private boolean installFilter(MessageContext mc, XMLStreamWriter writer) { + if (!(writer instanceof MTOMXMLStreamWriter)) { + return false; + } + if (!ContextUtils.isJAXBRemoveIllegalChars(mc)) { + return false; + } + + + MTOMXMLStreamWriter mtomWriter = (MTOMXMLStreamWriter) writer; + mtomWriter.setFilter(new XMLStreamWriterRemoveIllegalChars()); + return true; + } + + /** + * UninstallInstall a JAXB filter if requested + * @param mc + * @param writer + * @return true if filter installed + */ + private void uninstallFilter(XMLStreamWriter writer) { + MTOMXMLStreamWriter mtomWriter = (MTOMXMLStreamWriter) writer; + mtomWriter.removeFilter(); + } + } Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java?rev=982938&r1=982937&r2=982938&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java Fri Aug 6 12:31:05 2010 @@ -161,4 +161,33 @@ public interface Constants { * This constant will be used to store the location of JAX-WS generated artifacts cache. */ public static final String WS_CACHE="wsCache"; + + /** + * Context Property: + * Name: jaxws.jaxb.write.remove.illegal.chars + * Value: Boolean.TRUE or Boolean.FALSE + * Default: null, which is interpreted as FALSE. + * + * Configuration Parameter + * Name: jaxws.jaxb.write.remove.illegal.chars + * Value: String or Boolean representing true or false + * Default: null, which is interpreted as FALSE + * + * Description: + * If the value is false, the jax-ws engine will detect and remove + * illegal characters (characters not supported in xml) when writing + * a JAXB data bean associated with a jaxws web method + * http://www.w3.org/TR/2008/REC-xml-20081126/#NT-Char + * This extra filter may degrade performance. + * + * Customers should accept the default behavior (false), and only set the value to true if the + * character data produced by their web service is invalid and cannot be filtered by some + * other mechanism. + * + * The engine will first examine the Context property. If not set, the value of the Configuration + * property is used. + */ + public static final String JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS = + "jaxws.jaxb.write.remove.illegal.chars"; + } Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/context/utils/ContextUtils.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/context/utils/ContextUtils.java?rev=982938&r1=982937&r2=982938&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/context/utils/ContextUtils.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/context/utils/ContextUtils.java Fri Aug 6 12:31:05 2010 @@ -20,7 +20,11 @@ package org.apache.axis2.jaxws.context.utils; import org.apache.axiom.soap.SOAPHeader; +import org.apache.axis2.AxisFault; +import org.apache.axis2.context.OperationContext; import org.apache.axis2.context.ServiceContext; +import org.apache.axis2.description.Parameter; +import org.apache.axis2.jaxws.Constants; import org.apache.axis2.jaxws.addressing.util.ReferenceParameterList; import org.apache.axis2.jaxws.context.WebServiceContextImpl; import org.apache.axis2.jaxws.core.MessageContext; @@ -33,6 +37,7 @@ import org.apache.axis2.jaxws.i18n.Messa import org.apache.axis2.jaxws.server.endpoint.lifecycle.impl.EndpointLifecycleManagerImpl; import org.apache.axis2.jaxws.utility.JavaUtils; import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.axis2.wsdl.WSDLConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; @@ -279,4 +284,145 @@ public class ContextUtils { } } } + + /** + * isJAXBRemoveIllegalChars + * + * Determine if illegal characters should be removed when JAXB beans are written + * + * @see Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS + * + * @param mc + * @return true if the property is set + */ + public static boolean isJAXBRemoveIllegalChars(org.apache.axis2.context.MessageContext mc) { + boolean rc = _isJAXBRemoveIllegalChars(mc); + + // If not true, check the related MessageContext + if (!rc) { + if (mc != null && mc != null) { + rc = _isJAXBRemoveIllegalChars(getRelatedMessageContext(mc)); + } + } + return rc; + } + + /** + * getRelatedMessageContext + * @param mc Axis2 MessageContext + * @return related MessageContext + */ + private static org.apache.axis2.context.MessageContext + getRelatedMessageContext(org.apache.axis2.context.MessageContext mc) { + if (log.isDebugEnabled()) { + log.debug("Enter getRelatedMessageContext for:" + mc); + } + org.apache.axis2.context.MessageContext relatedMC = null; + if (mc != null) { + OperationContext oc = mc.getOperationContext(); + if (oc != null) { + try { + relatedMC = oc.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE); + if (relatedMC == mc) { + relatedMC = oc.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE); + } + } catch (AxisFault e) { + // TODO This should never occur in this scenario, swallow and continue + } + } + } + if (log.isDebugEnabled()) { + log.debug("Exit getRelatedMessageContext related messageContext is" + relatedMC); + } + return relatedMC; + } + + /** + * _isJAXBRemoveIllegalChars + * + * Determine if illegal characters should be removed when JAXB beans are written + * + * @see Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS + * + * @param mc + * @return true if property is set + */ + private static boolean _isJAXBRemoveIllegalChars(MessageContext mc) { + + boolean value = false; + if (mc == null) { + if (log.isDebugEnabled()) { + log.debug("_isJAXBRemoveIllegalChars returns false due to missing MessageContext"); + } + return false; + } + + // First examine the property on the jaxws MessageContext + Boolean property = (Boolean) mc.getProperty( + Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + if (property != null) { + value = property.booleanValue(); + if (log.isDebugEnabled()) { + log.debug("_isJAXBRemoveIllegalChars returns " + value + " per jaxws MessageContext property " + + Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + } + return value; + } + + // If not found, delegate to the Axis2 MessageContext + if (mc.getAxisMessageContext() != null) { + return _isJAXBRemoveIllegalChars(mc.getAxisMessageContext()); + } + return value; + } + + /** + * _isJAXBRemoveIllegalChars + * + * Determine if illegal characters should be removed when JAXB beans are written + * + * @see Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS + * + * @param mc + * @return true if property is set + */ + private static boolean _isJAXBRemoveIllegalChars(org.apache.axis2.context.MessageContext mc) { + + boolean value = false; + if (mc == null) { + if (log.isDebugEnabled()) { + log.debug("_isJAXBRemoveIllegalChars returns false due to missing MessageContext"); + } + return false; + } + + // First examine the property on the axis2 MessageContext hierarchy + Boolean property = (Boolean) mc.getProperty( + Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + if (property != null) { + value = property.booleanValue(); + if (log.isDebugEnabled()) { + log.debug("_isJAXBRemoveIllegalChars returns " + value + " per axis2 MessageContext property " + + Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + } + return value; + } + + + // Now look at the configuration parameter + Parameter p = mc.getParameter(Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + if (p != null) { + value = JavaUtils.isTrue(p.getValue()); + if (log.isDebugEnabled()) { + log.debug("isJAXBRemoveIllegalChars returns " + value + " per inspection of Configuration property " + + Constants.JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS); + } + return value; + } + + if (log.isDebugEnabled()) { + log.debug("isJAXBRemoveIllegalChars returns the default: false"); + } + return false; + } }