You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by em...@apache.org on 2018/01/19 06:11:09 UTC

[cxf] branch master updated: [CXF-7520]:Put CharacterEscapeHandler in jaxb marshaller to make it work with jdk9

This is an automated email from the ASF dual-hosted git repository.

ema pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 6e0eed5  [CXF-7520]:Put CharacterEscapeHandler in jaxb marshaller to make it work with jdk9
6e0eed5 is described below

commit 6e0eed5065021446b7956db5e78cab8a9128d974
Author: Jim Ma <em...@apache.org>
AuthorDate: Wed Jan 17 16:56:58 2018 +0800

    [CXF-7520]:Put CharacterEscapeHandler in jaxb marshaller to make it work with jdk9
---
 .../jaxb/EscapeHandlerInvocationHandler.java       | 45 ++++++++++++++++++++++
 .../java/org/apache/cxf/common/jaxb/JAXBUtils.java | 43 +++++++++++++++++++++
 .../org/apache/cxf/jaxb/io/DataWriterImpl.java     |  2 +
 .../cxf/jaxrs/provider/AbstractJAXBProvider.java   |  1 +
 .../cxf/jaxrs/provider/json/JSONProviderTest.java  | 10 ++---
 5 files changed, 94 insertions(+), 7 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/common/jaxb/EscapeHandlerInvocationHandler.java b/core/src/main/java/org/apache/cxf/common/jaxb/EscapeHandlerInvocationHandler.java
new file mode 100644
index 0000000..64f1385
--- /dev/null
+++ b/core/src/main/java/org/apache/cxf/common/jaxb/EscapeHandlerInvocationHandler.java
@@ -0,0 +1,45 @@
+/**
+ * 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.cxf.common.jaxb;
+
+import java.io.Writer;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public final class EscapeHandlerInvocationHandler implements InvocationHandler {
+
+    private Object target; 
+    public EscapeHandlerInvocationHandler(Object obj) {
+        target = obj;
+    }
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        Object result = null;
+        if (method.getName().equals("escape") && args.length == 5) {
+            if ((Integer)args[1] == 0 && (Integer)args[2] == 0) {
+                Writer writer = (Writer)args[4];
+                writer.write("");
+                return null;
+            }
+            result =  method.invoke(target, args);
+        } 
+        return result;
+    }
+    
+}
diff --git a/core/src/main/java/org/apache/cxf/common/jaxb/JAXBUtils.java b/core/src/main/java/org/apache/cxf/common/jaxb/JAXBUtils.java
index e33a121..685cb07 100644
--- a/core/src/main/java/org/apache/cxf/common/jaxb/JAXBUtils.java
+++ b/core/src/main/java/org/apache/cxf/common/jaxb/JAXBUtils.java
@@ -30,6 +30,7 @@ import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Target;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
@@ -85,6 +86,7 @@ import org.apache.cxf.common.util.ASMHelper.MethodVisitor;
 import org.apache.cxf.common.util.ASMHelper.Opcodes;
 import org.apache.cxf.common.util.CachedClass;
 import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.common.util.ProxyHelper;
 import org.apache.cxf.common.util.ReflectionInvokationHandler;
 import org.apache.cxf.common.util.ReflectionInvokationHandler.WrapReturn;
 import org.apache.cxf.common.util.ReflectionUtil;
@@ -123,6 +125,7 @@ public final class JAXBUtils {
     private static final Map<String, String> BUILTIN_DATATYPES_MAP;
     private static final Map<String, Class<?>> HOLDER_TYPES_MAP;
     private static ClassLoader jaxbXjcLoader;
+    private static Object jaxbEscapeHandler;
 
     static {
         BUILTIN_DATATYPES_MAP = new HashMap<>();
@@ -1531,4 +1534,44 @@ public final class JAXBUtils {
         return ReflectionInvokationHandler.createProxyWrapper(o, JAXBBeanInfo.class);
     }
 
+    public static void setMinimumEscapeHandler(Marshaller marshaller) {
+        String postFix = "";
+        if (marshaller.getClass().getName().contains("com.sun.xml.internal")
+            || marshaller.getClass().getName().contains("eclipse")) {
+            //eclipse moxy accepts sun package CharacterEscapeHandler 
+            postFix = ".internal";
+        } else if (marshaller.getClass().getName().contains("com.sun.xml.bind")) {
+            postFix = "";
+        } else {
+            LOG.log(Level.WARNING, "Failed to set MinumEscapeHandler for unknown jaxb marshaller:"
+                                   + marshaller);
+            return;
+        }
+        try {
+            Class<?> handlerClass = ClassLoaderUtils.loadClass("com.sun.xml" + postFix
+                                                                   + ".bind.marshaller.MinimumEscapeHandler",
+                                                               marshaller.getClass());
+            Class<?> handlerInterface = ClassLoaderUtils
+                .loadClass("com.sun.xml" + postFix + ".bind.marshaller.CharacterEscapeHandler",
+                           marshaller.getClass());
+            Object targetHandler = ReflectionUtil.getDeclaredField(handlerClass, "theInstance").get(null);
+            Object escapeHandler = getEscapeHandlerInstance(marshaller.getClass().getClassLoader(),
+                                                            new Class[] {handlerInterface},
+                                                            new EscapeHandlerInvocationHandler(targetHandler));
+            marshaller.setProperty("com.sun.xml" + postFix + ".bind.characterEscapeHandler", escapeHandler);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.INFO, "Failed to set MinumEscapeHandler to jaxb marshaller", e);
+        }
+    }
+
+    private static synchronized Object getEscapeHandlerInstance(ClassLoader loader, Class<?>[] interfaces,
+                                                                InvocationHandler handler) {
+        if (jaxbEscapeHandler == null) {
+            jaxbEscapeHandler = ProxyHelper.getProxy(loader, interfaces, handler);
+        }
+        return jaxbEscapeHandler;
+    }
+    
+
 }
diff --git a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
index 5ca0a36..992e292 100644
--- a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
+++ b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
@@ -130,6 +130,8 @@ public class DataWriterImpl<T> extends JAXBDataBase implements DataWriter<T> {
             marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
             marshaller.setListener(databinding.getMarshallerListener());
+            JAXBUtils.setMinimumEscapeHandler(marshaller);
+
             if (setEventHandler) {
                 ValidationEventHandler h = veventHandler;
                 if (veventHandler == null) {
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
index eed4744..c9ae400 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
@@ -627,6 +627,7 @@ public abstract class AbstractJAXBProvider<T> extends AbstractConfigurableProvid
         if (marshallerListener != null) {
             marshaller.setListener(marshallerListener);
         }
+        JAXBUtils.setMinimumEscapeHandler(marshaller);
         validateObjectIfNeeded(marshaller, cls, obj);
         return marshaller;
     }
diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/JSONProviderTest.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/JSONProviderTest.java
index 02e0ae8..49dbd95 100644
--- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/JSONProviderTest.java
+++ b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/JSONProviderTest.java
@@ -325,15 +325,11 @@ public class JSONProviderTest extends Assert {
 
     @Test
     public void testWriteNullValueAsString() throws Exception {
-        if (!System.getProperty("java.version").startsWith("9")) {
-            doTestWriteNullValue(true);
-        }
+        doTestWriteNullValue(true);
     }
     @Test
     public void testWriteNullValueAsNull() throws Exception {
-        if (!System.getProperty("java.version").startsWith("9")) {
-            doTestWriteNullValue(false);
-        }
+        doTestWriteNullValue(false);
     }
 
     private void doTestWriteNullValue(boolean nullAsString) throws Exception {
@@ -1952,7 +1948,7 @@ public class JSONProviderTest extends Assert {
         public void writeCharacters(char[] text, int arg1, int arg2) throws XMLStreamException {
             String str = new String(text);
             if (StringUtils.isEmpty(str.trim())) {
-                super.writeCharacters(null, arg1, arg2);
+                super.writeCharacters(null);
             } else {
                 super.writeCharacters(text, arg1, arg2);
             }

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <co...@cxf.apache.org>'].