You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2015/07/23 19:11:46 UTC

incubator-johnzon git commit: JOHNZON-49 avoid cycling by default for throwable

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master bd3e07e53 -> 73b2fd63e


JOHNZON-49 avoid cycling by default for throwable


Project: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/commit/73b2fd63
Tree: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/tree/73b2fd63
Diff: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/diff/73b2fd63

Branch: refs/heads/master
Commit: 73b2fd63e9dbc01c454419baae3f510897738890
Parents: bd3e07e
Author: Romain Manni-Bucau <rm...@starbucks.com>
Authored: Thu Jul 23 10:11:33 2015 -0700
Committer: Romain Manni-Bucau <rm...@starbucks.com>
Committed: Thu Jul 23 10:11:33 2015 -0700

----------------------------------------------------------------------
 .../jaxrs/ConfigurableJohnzonProvider.java      | 17 ++++++
 .../java/org/apache/johnzon/mapper/Mapper.java  | 22 +++----
 .../apache/johnzon/mapper/MapperBuilder.java    | 14 +++++
 .../johnzon/mapper/access/AccessMode.java       |  6 +-
 .../johnzon/mapper/access/BaseAccessMode.java   | 61 ++++++++++++++++++++
 .../johnzon/mapper/access/FieldAccessMode.java  |  6 +-
 .../mapper/access/FieldAndMethodAccessMode.java | 12 +++-
 .../johnzon/mapper/access/MethodAccessMode.java |  6 +-
 .../johnzon/mapper/CircularExceptionTest.java   | 35 +++++++++++
 9 files changed, 156 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
index 3e08eb5..4d23374 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -100,6 +100,23 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
         instance().writeTo(t, rawType, genericType, annotations, mediaType, httpHeaders, entityStream);
     }
 
+    // type=a,b,c|type2=d,e
+    public void setIgnoreFieldsForType(final String mapping) {
+        for (final String config : mapping.split(" *| *")) {
+            final String[] parts = config.split(" *= *");
+            try {
+                final Class<?> type = Thread.currentThread().getContextClassLoader().loadClass(parts[0]);
+                if (parts.length == 1) {
+                    builder.setIgnoreFieldsForType(type);
+                } else {
+                    builder.setIgnoreFieldsForType(type, parts[1].split(" *, *"));
+                }
+            } catch (final ClassNotFoundException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+    }
+
     public void setSupportConstructors(final boolean supportConstructors) {
         builder.setSupportConstructors(supportConstructors);
     }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index 485677d..fb2ec78 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -24,6 +24,17 @@ import org.apache.johnzon.mapper.reflection.JohnzonCollectionType;
 import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;
 import org.apache.johnzon.mapper.reflection.Mappings;
 
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonReaderFactory;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.JsonValue.ValueType;
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
+import javax.xml.bind.DatatypeConverter;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -54,17 +65,6 @@ import java.util.TreeSet;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import javax.json.JsonArray;
-import javax.json.JsonNumber;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.JsonReaderFactory;
-import javax.json.JsonString;
-import javax.json.JsonValue;
-import javax.json.JsonValue.ValueType;
-import javax.json.stream.JsonGenerator;
-import javax.json.stream.JsonGeneratorFactory;
-import javax.xml.bind.DatatypeConverter;
 
 import static java.util.Arrays.asList;
 

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 90afc74..4f7e68c 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -32,6 +32,7 @@ import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonGeneratorFactory;
 
 import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.access.BaseAccessMode;
 import org.apache.johnzon.mapper.access.FieldAccessMode;
 import org.apache.johnzon.mapper.access.FieldAndMethodAccessMode;
 import org.apache.johnzon.mapper.access.MethodAccessMode;
@@ -141,6 +142,19 @@ public class MapperBuilder {
                 encoding);
     }
 
+    public MapperBuilder setIgnoreFieldsForType(final Class<?> type, final String... fields) {
+        if (BaseAccessMode.class.isInstance(accessMode)) {
+            if (fields == null || fields.length == 0) {
+                BaseAccessMode.class.cast(accessMode).getFieldsToRemove().remove(type);
+            } else {
+                BaseAccessMode.class.cast(accessMode).getFieldsToRemove().put(type, fields);
+            }
+        } else {
+            throw new IllegalStateException("AccessMode is not an BaseAccessMode");
+        }
+        return this;
+    }
+
     public MapperBuilder setSupportGetterForCollections(final boolean useGetterForCollections) {
         accessMode = new MethodAccessMode(useGetterForCollections);
         return this;

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
index 4fc9fdb..37b675b 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
@@ -23,16 +23,16 @@ import java.lang.reflect.Type;
 import java.util.Map;
 
 public interface AccessMode {
-    public static interface DecoratedType {
+    interface DecoratedType {
         Type getType();
         <T extends Annotation> T getAnnotation(Class<T> clazz);
     }
 
-    public static interface Writer extends DecoratedType {
+    interface Writer extends DecoratedType {
         void write(Object instance, Object value);
     }
 
-    public static interface Reader extends DecoratedType {
+    interface Reader extends DecoratedType {
         Object read(Object instance);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
new file mode 100644
index 0000000..d8be3df
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
@@ -0,0 +1,61 @@
+/*
+ * 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.johnzon.mapper.access;
+
+import java.util.HashMap;
+import java.util.Map;
+
+// handle some specific types
+public abstract class BaseAccessMode implements AccessMode {
+    private final Map<Class<?>, String[]> fieldsToRemove = new HashMap<Class<?>, String[]>();
+
+    public BaseAccessMode() { // mainly built it in the JVM types == user cant handle them
+        fieldsToRemove.put(Throwable.class, new String[]{"suppressedExceptions", "cause"});
+    }
+
+    protected abstract Map<String,Reader> doFindReaders(Class<?> clazz);
+    protected abstract Map<String,Writer> doFindWriters(Class<?> clazz);
+
+    @Override
+    public Map<String, Reader> findReaders(final Class<?> clazz) {
+        return sanitize(clazz, doFindReaders(clazz));
+    }
+
+    @Override
+    public Map<String, Writer> findWriters(final Class<?> clazz) {
+        return sanitize(clazz, doFindWriters(clazz));
+    }
+
+    // editable during builder time, dont do it at runtime or you get no guarantee
+    public Map<Class<?>, String[]> getFieldsToRemove() {
+        return fieldsToRemove;
+    }
+
+    private <T> Map<String, T> sanitize(final Class<?> type, final Map<String, T> delegate) {
+        for (final Map.Entry<Class<?>, String[]> entry : fieldsToRemove.entrySet()) {
+            if (entry.getKey().isAssignableFrom(type)) {
+                for (final String field : entry.getValue()) {
+                    delegate.remove(field);
+                }
+                return delegate;
+            }
+        }
+        return delegate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
index 5bf9f0c..fb85a69 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
@@ -28,9 +28,9 @@ import java.lang.reflect.Type;
 import java.util.HashMap;
 import java.util.Map;
 
-public class FieldAccessMode implements AccessMode {
+public class FieldAccessMode extends BaseAccessMode {
     @Override
-    public Map<String, Reader> findReaders(final Class<?> clazz) {
+    public Map<String, Reader> doFindReaders(final Class<?> clazz) {
         final Map<String, Reader> readers = new HashMap<String, Reader>();
         for (final Map.Entry<String, Field> f : fields(clazz).entrySet()) {
             final String key = f.getKey();
@@ -44,7 +44,7 @@ public class FieldAccessMode implements AccessMode {
     }
 
     @Override
-    public Map<String, Writer> findWriters(final Class<?> clazz) {
+    public Map<String, Writer> doFindWriters(final Class<?> clazz) {
         final Map<String, Writer> writers = new HashMap<String, Writer>();
         for (final Map.Entry<String, Field> f : fields(clazz).entrySet()) {
             final String key = f.getKey();

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
index f108616..f2a7ee1 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
@@ -22,19 +22,25 @@ import java.util.HashMap;
 import java.util.Map;
 
 // methods override fields
-public class FieldAndMethodAccessMode implements AccessMode {
+public class FieldAndMethodAccessMode extends BaseAccessMode {
     private final FieldAccessMode fields = new FieldAccessMode();
     private final MethodAccessMode methods = new MethodAccessMode(false);
 
     @Override
-    public Map<String, Reader> findReaders(final Class<?> clazz) {
+    public Map<String, Reader> doFindReaders(final Class<?> clazz) {
         final Map<String, Reader> readers = new HashMap<String, Reader>(fields.findReaders(clazz));
         readers.putAll(methods.findReaders(clazz));
         return readers;
     }
 
     @Override
-    public Map<String, Writer> findWriters(final Class<?> clazz) {
+    public Map<String, Writer> doFindWriters(final Class<?> clazz) {
+        {
+            final Map<String, Writer> specific = super.findWriters(clazz);
+            if (specific != null) {
+                return specific;
+            }
+        }
         final Map<String, Writer> writers = new HashMap<String, Writer>(fields.findWriters(clazz));
         writers.putAll(methods.findWriters(clazz));
         return writers;

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
index 4318a17..d9cee8a 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
@@ -31,7 +31,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
-public class MethodAccessMode implements AccessMode {
+public class MethodAccessMode extends BaseAccessMode {
     private final boolean supportGetterAsWritter;
 
     public MethodAccessMode(final boolean supportGetterAsWritter) {
@@ -39,7 +39,7 @@ public class MethodAccessMode implements AccessMode {
     }
 
     @Override
-    public Map<String, Reader> findReaders(final Class<?> clazz) {
+    public Map<String, Reader> doFindReaders(final Class<?> clazz) {
         final Map<String, Reader> readers = new HashMap<String, Reader>();
         final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
         for (final PropertyDescriptor descriptor : propertyDescriptors) {
@@ -55,7 +55,7 @@ public class MethodAccessMode implements AccessMode {
     }
 
     @Override
-    public Map<String, Writer> findWriters(final Class<?> clazz) {
+    public Map<String, Writer> doFindWriters(final Class<?> clazz) {
         final Map<String, Writer> writers = new HashMap<String, Writer>();
         final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
         for (final PropertyDescriptor descriptor : propertyDescriptors) {

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/73b2fd63/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/CircularExceptionTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/CircularExceptionTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/CircularExceptionTest.java
new file mode 100644
index 0000000..846e469
--- /dev/null
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/CircularExceptionTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.johnzon.mapper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+public class CircularExceptionTest {
+    @Test
+    public void dontStackOverFlow() {
+        final Throwable oopsImVicous = new Exception("circular");
+        oopsImVicous.getStackTrace(); // fill it
+        oopsImVicous.initCause(new IllegalArgumentException(oopsImVicous));
+        final String serialized = new MapperBuilder().setAccessModeName("field").build().writeObjectAsString(oopsImVicous);
+        assertTrue(serialized.contains("\"detailMessage\":\"circular\""));
+        assertTrue(serialized.contains("\"stackTrace\":[{"));
+    }
+}