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 2014/11/12 11:38:43 UTC

incubator-johnzon git commit: JOHNZON-24 ConfigurableJohnzonProvider

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master 222c5df80 -> e45db5c6a


JOHNZON-24 ConfigurableJohnzonProvider


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

Branch: refs/heads/master
Commit: e45db5c6a492ee6c4c9238d987bb90f57238db71
Parents: 222c5df
Author: Romain Manni-Bucau <rm...@apache.org>
Authored: Wed Nov 12 11:38:28 2014 +0100
Committer: Romain Manni-Bucau <rm...@apache.org>
Committed: Wed Nov 12 11:38:28 2014 +0100

----------------------------------------------------------------------
 .../jaxrs/ConfigurableJohnzonProvider.java      | 146 +++++++++++++++++
 .../apache/johnzon/jaxrs/IgnorableTypes.java    |  34 ++++
 .../johnzon/jaxrs/JohnzonMessageBodyReader.java |  11 +-
 .../johnzon/jaxrs/JohnzonMessageBodyWriter.java |   8 +-
 .../apache/johnzon/jaxrs/JohnzonProvider.java   |   8 +-
 .../jaxrs/ConfigurableJohnzonProviderTest.java  | 161 +++++++++++++++++++
 6 files changed, 358 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/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
new file mode 100644
index 0000000..5937f3e
--- /dev/null
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -0,0 +1,146 @@
+/*
+ * 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.jaxrs;
+
+import org.apache.johnzon.mapper.MapperBuilder;
+import org.apache.johnzon.mapper.access.AccessMode;
+
+import javax.json.JsonReaderFactory;
+import javax.json.stream.JsonGeneratorFactory;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static java.util.Arrays.asList;
+import static javax.ws.rs.core.MediaType.WILDCARD;
+
+@Provider
+@Produces(WILDCARD)
+@Consumes(WILDCARD)
+public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, MessageBodyReader<T> {
+    // build/configuration
+    private MapperBuilder builder = new MapperBuilder();
+    private List<String> ignores;
+
+    // runtime
+    private AtomicReference<JohnzonProvider<T>> delegate = new AtomicReference<JohnzonProvider<T>>();
+
+    private JohnzonProvider<T> instance() {
+        JohnzonProvider<T> instance;
+        do {
+            instance = delegate.get();
+            if (builder != null && delegate.compareAndSet(null, new JohnzonProvider<T>(builder.build(), ignores))) {
+                // reset build instances
+                builder = null;
+                ignores = null;
+            }
+        } while (instance == null);
+        return instance;
+    }
+
+    @Override
+    public boolean isReadable(final Class<?> rawType, final Type genericType,
+                              final Annotation[] annotations, final MediaType mediaType) {
+        return instance().isReadable(rawType, genericType, annotations, mediaType);
+    }
+
+    @Override
+    public T readFrom(final Class<T> rawType, final Type genericType,
+                      final Annotation[] annotations, final MediaType mediaType,
+                      final MultivaluedMap<String, String> httpHeaders,
+                      final InputStream entityStream) throws IOException {
+        return instance().readFrom(rawType, genericType, annotations, mediaType, httpHeaders, entityStream);
+    }
+
+    @Override
+    public long getSize(final T t, final Class<?> rawType, final Type genericType,
+                        final Annotation[] annotations, final MediaType mediaType) {
+        return instance().getSize(t, rawType, genericType, annotations, mediaType);
+    }
+
+    @Override
+    public boolean isWriteable(final Class<?> rawType, final Type genericType,
+                               final Annotation[] annotations, final MediaType mediaType) {
+        return instance().isWriteable(rawType, genericType, annotations, mediaType);
+    }
+
+    @Override
+    public void writeTo(final T t, final Class<?> rawType, final Type genericType,
+                        final Annotation[] annotations, final MediaType mediaType,
+                        final MultivaluedMap<String, Object> httpHeaders,
+                        final OutputStream entityStream) throws IOException {
+        instance().writeTo(t, rawType, genericType, annotations, mediaType, httpHeaders, entityStream);
+    }
+
+    public void setIgnores(final String ignores) {
+        this.ignores = ignores == null ? null : asList(ignores.split(" *, *"));
+    }
+
+    public void setAccessMode(final AccessMode mode) {
+        builder.setAccessMode(mode);
+    }
+
+    public void setAccessModeName(final String mode) {
+        builder.setAccessModeName(mode);
+    }
+
+    public void setSupportHiddenAccess(final boolean supportHiddenAccess) {
+        builder.setSupportHiddenAccess(supportHiddenAccess);
+    }
+
+    public void setAttributeOrder(final Comparator<String> attributeOrder) {
+        builder.setAttributeOrder(attributeOrder);
+    }
+
+    public void setReaderFactory(final JsonReaderFactory readerFactory) {
+        builder.setReaderFactory(readerFactory);
+    }
+
+    public void setGeneratorFactory(final JsonGeneratorFactory generatorFactory) {
+        builder.setGeneratorFactory(generatorFactory);
+    }
+
+    public void setDoCloseOnStreams(final boolean doCloseOnStreams) {
+        builder.setDoCloseOnStreams(doCloseOnStreams);
+    }
+
+    public void setVersion(final int version) {
+        builder.setVersion(version);
+    }
+
+    public void setSkipNull(final boolean skipNull) {
+        builder.setSkipNull(skipNull);
+    }
+
+    public void setSkipEmptyArray(final boolean skipEmptyArray) {
+        builder.setSkipEmptyArray(skipEmptyArray);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/IgnorableTypes.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/IgnorableTypes.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/IgnorableTypes.java
new file mode 100644
index 0000000..938256f
--- /dev/null
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/IgnorableTypes.java
@@ -0,0 +1,34 @@
+/*
+ * 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.jaxrs;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+public class IgnorableTypes {
+    private final Collection<String> ignores;
+
+    protected IgnorableTypes(final Collection<String> ignores) {
+        this.ignores = ignores == null ? null : new HashSet<String>(ignores);
+    }
+
+    public boolean isIgnored(final Class<?> type) {
+        return ignores != null && ignores.contains(type.getName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
index d0813d3..c7e7ae6 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
@@ -25,6 +25,7 @@ import javax.json.JsonStructure;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 import java.io.IOException;
@@ -40,14 +41,15 @@ import static org.apache.johnzon.jaxrs.Jsons.isJson;
 
 @Provider
 @Consumes(WILDCARD)
-public class JohnzonMessageBodyReader<T> implements MessageBodyReader<T> {
+public class JohnzonMessageBodyReader<T> extends IgnorableTypes implements MessageBodyReader<T> {
     private final Mapper mapper;
 
     public JohnzonMessageBodyReader() {
-        this(new MapperBuilder().setDoCloseOnStreams(false).build());
+        this(new MapperBuilder().setDoCloseOnStreams(false).build(), null);
     }
 
-    public JohnzonMessageBodyReader(final Mapper mapper) {
+    public JohnzonMessageBodyReader(final Mapper mapper, final Collection<String> ignoredTypes) {
+        super(ignoredTypes);
         this.mapper = mapper;
     }
 
@@ -55,7 +57,8 @@ public class JohnzonMessageBodyReader<T> implements MessageBodyReader<T> {
     public boolean isReadable(final Class<?> rawType, final Type genericType,
                               final Annotation[] annotations, final MediaType mediaType) {
         return isJson(mediaType)
-                && InputStream.class != rawType && Reader.class != rawType
+                && !isIgnored(rawType)
+                && InputStream.class != rawType && Reader.class != rawType && Response.class != rawType
                 && String.class != rawType
                 && !JsonStructure.class.isAssignableFrom(rawType);
     }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
index a540d6d..840d80b 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
@@ -42,14 +42,15 @@ import static javax.ws.rs.core.MediaType.WILDCARD;
 
 @Provider
 @Produces(WILDCARD)
-public class JohnzonMessageBodyWriter<T> implements MessageBodyWriter<T> {
+public class JohnzonMessageBodyWriter<T> extends IgnorableTypes implements MessageBodyWriter<T> {
     private final Mapper mapper;
 
     public JohnzonMessageBodyWriter() {
-        this(new MapperBuilder().setDoCloseOnStreams(false).build());
+        this(new MapperBuilder().setDoCloseOnStreams(false).build(), null);
     }
 
-    public JohnzonMessageBodyWriter(final Mapper mapper) {
+    public JohnzonMessageBodyWriter(final Mapper mapper, final Collection<String> ignoredTypes) {
+        super(ignoredTypes);
         this.mapper = mapper;
     }
 
@@ -63,6 +64,7 @@ public class JohnzonMessageBodyWriter<T> implements MessageBodyWriter<T> {
     public boolean isWriteable(final Class<?> rawType, final Type genericType,
                                final Annotation[] annotations, final MediaType mediaType) {
         return Jsons.isJson(mediaType)
+                && !isIgnored(rawType)
                 && InputStream.class != rawType
                 && OutputStream.class != rawType
                 && Writer.class != rawType

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonProvider.java
index a72e9f1..58ce2e7 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonProvider.java
@@ -25,17 +25,19 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.ext.Provider;
 
+import java.util.Collection;
+
 import static javax.ws.rs.core.MediaType.WILDCARD;
 
 @Provider
 @Produces(WILDCARD)
 @Consumes(WILDCARD)
 public class JohnzonProvider<T> extends DelegateProvider<T> {
-    public JohnzonProvider(final Mapper mapper) {
-        super(new JohnzonMessageBodyReader<T>(mapper), new JohnzonMessageBodyWriter<T>(mapper));
+    public JohnzonProvider(final Mapper mapper, final Collection<String> ignores) {
+        super(new JohnzonMessageBodyReader<T>(mapper, ignores), new JohnzonMessageBodyWriter<T>(mapper, ignores));
     }
 
     public JohnzonProvider() {
-        this(new MapperBuilder().setDoCloseOnStreams(false).build());
+        this(new MapperBuilder().setDoCloseOnStreams(false).build(), null);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e45db5c6/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProviderTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProviderTest.java b/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProviderTest.java
new file mode 100644
index 0000000..e95cb13
--- /dev/null
+++ b/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProviderTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.jaxrs;
+
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.local.LocalConduit;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ConfigurableJohnzonProviderTest {
+    private final static String ENDPOINT_ADDRESS = "local://johnzon";
+    private static Server server;
+
+    @BeforeClass
+    public static void bindEndpoint() throws Exception {
+        final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(JohnzonResource.class);
+        sf.setProviders(asList(new ConfigurableJohnzonProvider()));
+        sf.setResourceProvider(JohnzonResource.class, new SingletonResourceProvider(new JohnzonResource(), false));
+        sf.setAddress(ENDPOINT_ADDRESS);
+        server = sf.create();
+    }
+
+    @AfterClass
+    public static void unbind() throws Exception {
+        server.stop();
+        server.destroy();
+    }
+
+    @Test
+    public void asParam() {
+        final String result = client().path("johnzon").type(MediaType.APPLICATION_JSON_TYPE).post(new Johnzon("client")).readEntity(String.class);
+        assertTrue(Boolean.parseBoolean(result));
+    }
+
+    @Test
+    public void object() {
+        final Johnzon johnzon = client().path("johnzon").get(Johnzon.class);
+        assertEquals("johnzon", johnzon.getName());
+    }
+
+    @Test
+    public void array() {
+        final Johnzon[] johnzon = client().path("johnzon/all1").get(Johnzon[].class);
+        assertEquals(2, johnzon.length);
+        for (int i = 0; i < johnzon.length; i++) {
+            assertEquals("johnzon" + (i + 1), johnzon[i].getName());
+        }
+    }
+
+    @Test
+    public void list() {
+        final ParameterizedType list = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return new Type[]{Johnzon.class};
+            }
+
+            @Override
+            public Type getRawType() {
+                return List.class;
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return null;
+            }
+        };
+        final List<Johnzon> johnzons = client().path("johnzon/all2").get(new GenericType<List<Johnzon>>(list));
+        assertEquals(2, johnzons.size());
+        int i = 1;
+        for (final Johnzon f : johnzons) {
+            assertEquals("johnzon" + i, f.getName());
+            i++;
+        }
+    }
+
+    private static WebClient client() {
+        final WebClient client = WebClient.create(ENDPOINT_ADDRESS, asList(new JohnzonProvider<Object>())).accept(MediaType.APPLICATION_JSON_TYPE);
+        WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
+        return client;
+    }
+
+    public static class Johnzon {
+        private String name;
+
+        public Johnzon(final String name) {
+            this.name = name;
+        }
+
+        public Johnzon() {
+            // no-op
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(final String name) {
+            this.name = name;
+        }
+    }
+
+    @Path("johnzon")
+    public static class JohnzonResource {
+        @GET
+        public Johnzon johnzon() {
+            return new Johnzon("johnzon");
+        }
+
+        @GET
+        @Path("all1")
+        public Johnzon[] johnzons1() {
+            return new Johnzon[] { new Johnzon("johnzon1"), new Johnzon("johnzon2") };
+        }
+
+        @GET
+        @Path("all2")
+        public List<Johnzon> johnzons2() {
+            return asList(johnzons1());
+        }
+
+        @POST
+        public String asParam(final Johnzon f) {
+            return Boolean.toString("client".equals(f.getName()));
+        }
+    }
+}