diff --git a/core/src/main/java/org/apache/cxf/feature/transform/AbstractXSLTInterceptor.java b/core/src/main/java/org/apache/cxf/feature/transform/AbstractXSLTInterceptor.java index 1dc91c8d76c..d50af90fb1c 100644 --- a/core/src/main/java/org/apache/cxf/feature/transform/AbstractXSLTInterceptor.java +++ b/core/src/main/java/org/apache/cxf/feature/transform/AbstractXSLTInterceptor.java @@ -21,6 +21,7 @@ import java.io.InputStream; +import java.nio.charset.StandardCharsets; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Templates; @@ -31,6 +32,7 @@ import org.w3c.dom.Document; import org.apache.cxf.common.classloader.ClassLoaderUtils; +import org.apache.cxf.message.Exchange; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.AbstractPhaseInterceptor; @@ -88,4 +90,19 @@ protected boolean checkContextProperty(Message message) { protected Templates getXSLTTemplate() { return xsltTemplate; } + + protected String getEncoding(Message message) { + String encoding = (String) message.get(Message.ENCODING); + if (encoding == null) { + Exchange ex = message.getExchange(); + if (ex != null && ex.getInMessage() != null) { + encoding = + (String) ex.getInMessage().get(Message.ENCODING); + } + } + if (encoding == null) { + encoding = StandardCharsets.UTF_8.name(); + } + return encoding; + } } diff --git a/core/src/main/java/org/apache/cxf/feature/transform/XSLTInInterceptor.java b/core/src/main/java/org/apache/cxf/feature/transform/XSLTInInterceptor.java index 5e98493ffd2..6ffd9e29ed4 100644 --- a/core/src/main/java/org/apache/cxf/feature/transform/XSLTInInterceptor.java +++ b/core/src/main/java/org/apache/cxf/feature/transform/XSLTInInterceptor.java @@ -79,9 +79,12 @@ public void handleMessage(Message message) { protected void transformXReader(Message message, XMLStreamReader xReader) { CachedOutputStream cachedOS = new CachedOutputStream(); try { + String encoding = getEncoding(message); StaxUtils.copy(xReader, cachedOS); - InputStream transformedIS = XSLTUtils.transform(getXSLTTemplate(), cachedOS.getInputStream()); - XMLStreamReader transformedReader = StaxUtils.createXMLStreamReader(transformedIS); + InputStream transformedIS = XSLTUtils.transform( + getXSLTTemplate(), cachedOS.getInputStream(), encoding); + XMLStreamReader transformedReader = + StaxUtils.createXMLStreamReader(transformedIS, encoding); message.setContent(XMLStreamReader.class, transformedReader); } catch (XMLStreamException e) { throw new Fault("STAX_COPY", LOG, e, e.getMessage()); @@ -103,9 +106,12 @@ protected void transformXReader(Message message, XMLStreamReader xReader) { protected void transformIS(Message message, InputStream is) { try (InputStream inputStream = is) { - message.setContent(InputStream.class, XSLTUtils.transform(getXSLTTemplate(), inputStream)); + String encoding = getEncoding(message); + message.setContent(InputStream.class, + XSLTUtils.transform(getXSLTTemplate(), inputStream, encoding)); } catch (IOException e) { - LOG.warning("Cannot close stream after transformation: " + e.getMessage()); + LOG.warning("Cannot close stream after transformation: " + + e.getMessage()); } } diff --git a/core/src/main/java/org/apache/cxf/feature/transform/XSLTOutInterceptor.java b/core/src/main/java/org/apache/cxf/feature/transform/XSLTOutInterceptor.java index a7f54c80f0b..c4508cda7a2 100644 --- a/core/src/main/java/org/apache/cxf/feature/transform/XSLTOutInterceptor.java +++ b/core/src/main/java/org/apache/cxf/feature/transform/XSLTOutInterceptor.java @@ -94,7 +94,10 @@ protected void transformXWriter(Message message, XMLStreamWriter xWriter) { protected void transformOS(Message message, OutputStream out) { CachedOutputStream wrapper = new CachedOutputStream(); - CachedOutputStreamCallback callback = new XSLTCachedOutputStreamCallback(getXSLTTemplate(), out); + String encoding = getEncoding(message); + CachedOutputStreamCallback callback = + new XSLTCachedOutputStreamCallback(getXSLTTemplate(), + out, encoding); wrapper.registerCallback(callback); message.setContent(OutputStream.class, wrapper); } @@ -144,10 +147,14 @@ public void close() { public static class XSLTCachedOutputStreamCallback implements CachedOutputStreamCallback { private final Templates xsltTemplate; private final OutputStream origStream; + private final String encoding; - public XSLTCachedOutputStreamCallback(Templates xsltTemplate, OutputStream origStream) { + public XSLTCachedOutputStreamCallback(Templates xsltTemplate, + OutputStream origStream, + String encoding) { this.xsltTemplate = xsltTemplate; this.origStream = origStream; + this.encoding = encoding; } @Override @@ -159,7 +166,8 @@ public void onClose(CachedOutputStream wrapper) { InputStream transformedStream; Exception exceptionOnClose = null; try { - transformedStream = XSLTUtils.transform(xsltTemplate, wrapper.getInputStream()); + transformedStream = XSLTUtils.transform( + xsltTemplate, wrapper.getInputStream(), encoding); IOUtils.copyAndCloseInput(transformedStream, origStream); } catch (IOException e) { throw new Fault("STREAM_COPY", LOG, e, e.getMessage()); diff --git a/core/src/main/java/org/apache/cxf/feature/transform/XSLTUtils.java b/core/src/main/java/org/apache/cxf/feature/transform/XSLTUtils.java index 4b35b2ffb95..1b70ab3cf2b 100644 --- a/core/src/main/java/org/apache/cxf/feature/transform/XSLTUtils.java +++ b/core/src/main/java/org/apache/cxf/feature/transform/XSLTUtils.java @@ -50,8 +50,18 @@ private XSLTUtils() { } public static InputStream transform(Templates xsltTemplate, InputStream in) { - try (InputStream inputStream = in; CachedOutputStream out = new CachedOutputStream()) { - Source beforeSource = new StaxSource(StaxUtils.createXMLStreamReader(inputStream)); + return transform(xsltTemplate, in, null); + } + + public static InputStream transform(Templates xsltTemplate, + InputStream in, + String encoding) { + try (InputStream inputStream = in; + CachedOutputStream out = new CachedOutputStream()) { + Source beforeSource = new StaxSource( + encoding != null + ? StaxUtils.createXMLStreamReader(inputStream, encoding) + : StaxUtils.createXMLStreamReader(inputStream)); Transformer trans = xsltTemplate.newTransformer(); trans.transform(beforeSource, new StreamResult(out)); diff --git a/core/src/main/java/org/apache/cxf/interceptor/transform/TransformInInterceptor.java b/core/src/main/java/org/apache/cxf/interceptor/transform/TransformInInterceptor.java index 1c0eb847b57..cb69d1bebc1 100644 --- a/core/src/main/java/org/apache/cxf/interceptor/transform/TransformInInterceptor.java +++ b/core/src/main/java/org/apache/cxf/interceptor/transform/TransformInInterceptor.java @@ -21,12 +21,14 @@ import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import javax.xml.stream.XMLStreamReader; import org.apache.cxf.interceptor.StaxInInterceptor; +import org.apache.cxf.message.Exchange; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.AbstractPhaseInterceptor; @@ -71,26 +73,51 @@ public TransformInInterceptor(String phase, List before, List af public void handleMessage(Message message) { if (contextPropertyName != null - && !MessageUtils.getContextualBoolean(message, contextPropertyName, false)) { + && !MessageUtils.getContextualBoolean(message, + contextPropertyName, false)) { return; } - XMLStreamReader reader = message.getContent(XMLStreamReader.class); + XMLStreamReader reader = + message.getContent(XMLStreamReader.class); InputStream is = message.getContent(InputStream.class); - XMLStreamReader transformReader = createTransformReaderIfNeeded(reader, is); + String encoding = getEncoding(message); + XMLStreamReader transformReader = + createTransformReaderIfNeeded(reader, is, encoding); if (transformReader != null) { message.setContent(XMLStreamReader.class, transformReader); } } - protected XMLStreamReader createTransformReaderIfNeeded(XMLStreamReader reader, InputStream is) { - return TransformUtils.createTransformReaderIfNeeded(reader, is, - inDropElements, - inElementsMap, - inAppendMap, - inAttributesMap, - blockOriginalReader); + protected XMLStreamReader createTransformReaderIfNeeded( + XMLStreamReader reader, + InputStream is, + String encoding) { + return TransformUtils.createTransformReaderIfNeeded( + reader, is, + inDropElements, + inElementsMap, + inAppendMap, + inAttributesMap, + blockOriginalReader, + encoding); + } + + private String getEncoding(Message message) { + String encoding = + (String) message.get(Message.ENCODING); + if (encoding == null) { + Exchange ex = message.getExchange(); + if (ex != null && ex.getInMessage() != null) { + encoding = (String) ex.getInMessage() + .get(Message.ENCODING); + } + } + if (encoding == null) { + encoding = StandardCharsets.UTF_8.name(); + } + return encoding; } public void setInAppendElements(Map inElements) { diff --git a/core/src/main/java/org/apache/cxf/staxutils/transform/TransformUtils.java b/core/src/main/java/org/apache/cxf/staxutils/transform/TransformUtils.java index dfe6051b1d0..0bbe966e96b 100644 --- a/core/src/main/java/org/apache/cxf/staxutils/transform/TransformUtils.java +++ b/core/src/main/java/org/apache/cxf/staxutils/transform/TransformUtils.java @@ -42,6 +42,17 @@ public static XMLStreamReader createNewReaderIfNeeded(XMLStreamReader reader, In return reader == null ? StaxUtils.createXMLStreamReader(is) : reader; } + public static XMLStreamReader createNewReaderIfNeeded( + XMLStreamReader reader, InputStream is, String encoding) { + if (reader != null) { + return reader; + } + if (encoding != null) { + return StaxUtils.createXMLStreamReader(is, encoding); + } + return StaxUtils.createXMLStreamReader(is); + } + public static XMLStreamWriter createNewWriterIfNeeded(XMLStreamWriter writer, OutputStream os) { return createNewWriterIfNeeded(writer, os, null); } @@ -106,15 +117,30 @@ public static XMLStreamReader createTransformReaderIfNeeded(XMLStreamReader read Map inAppendMap, Map inAttributesMap, boolean blockOriginalReader) { + return createTransformReaderIfNeeded(reader, is, + inDropElements, inElementsMap, inAppendMap, + inAttributesMap, blockOriginalReader, null); + } + + //CHECKSTYLE:OFF ParameterNumber + public static XMLStreamReader createTransformReaderIfNeeded(XMLStreamReader reader, + InputStream is, + List inDropElements, + Map inElementsMap, + Map inAppendMap, + Map inAttributesMap, + boolean blockOriginalReader, + String encoding) { if (inElementsMap != null || inAppendMap != null || inDropElements != null || inAttributesMap != null) { - reader = new InTransformReader(createNewReaderIfNeeded(reader, is), + reader = new InTransformReader(createNewReaderIfNeeded(reader, is, encoding), inElementsMap, inAppendMap, inDropElements, inAttributesMap, blockOriginalReader); } return reader; } + //CHECKSTYLE:ON ParameterNumber protected static void convertToQNamesMap(Map map, QNamesMap elementsMap, diff --git a/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java b/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java index 72f6b2b7863..8f40071fc9b 100644 --- a/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java +++ b/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java @@ -144,6 +144,40 @@ public void outWriterStreamTest() throws Exception { Assert.assertTrue("Message was not transformed", checkTransformedXML(doc)); } + @Test + public void inStreamWithEncodingTest() throws Exception { + InputStream iso88591IS = ClassLoaderUtils + .getResourceAsStream("message-iso-8859-1.xml", + this.getClass()); + message.setContent(InputStream.class, iso88591IS); + message.put(Message.ENCODING, "ISO-8859-1"); + inInterceptor.handleMessage(message); + InputStream transformedIS = + message.getContent(InputStream.class); + Document doc = StaxUtils.read(transformedIS); + Assert.assertTrue("Message was not transformed", + checkTransformedXML(doc)); + } + + @Test + public void outStreamWithEncodingTest() throws Exception { + CachedOutputStream cos = new CachedOutputStream(); + cos.holdTempFile(); + message.setContent(OutputStream.class, cos); + message.put(Message.ENCODING, "ISO-8859-1"); + outInterceptor.handleMessage(message); + InputStream iso88591IS = ClassLoaderUtils + .getResourceAsStream("message-iso-8859-1.xml", + this.getClass()); + OutputStream os = message.getContent(OutputStream.class); + IOUtils.copy(iso88591IS, os); + os.close(); + cos.releaseTempFileHold(); + Document doc = StaxUtils.read(cos.getInputStream()); + Assert.assertTrue("Message was not transformed", + checkTransformedXML(doc)); + } + private boolean checkTransformedXML(Document doc) { NodeList list = doc.getDocumentElement() .getElementsByTagNameNS("http://customerservice.example.com/", "getCustomersByName1"); diff --git a/core/src/test/java/org/apache/cxf/feature/transform/message-iso-8859-1.xml b/core/src/test/java/org/apache/cxf/feature/transform/message-iso-8859-1.xml new file mode 100644 index 00000000000..e13197d89e8 --- /dev/null +++ b/core/src/test/java/org/apache/cxf/feature/transform/message-iso-8859-1.xml @@ -0,0 +1,8 @@ + + + + + Müller + + +