/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.jersey.tests.e2e.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import org.junit.runner.RunWith;
/**
* @author Pavel Bucek (pavel.bucek at oracle.com)
*/
@RunWith(ConcurrentRunner.class)
public class XmlMoxyTest extends AbstractTypeTester {
@Path("JaxbBeanResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JaxbBeanResource extends AResource<JaxbBean> {
}
@Test
public void testJaxbBeanRepresentation() {
_test(new JaxbBean("CONTENT"), JaxbBeanResource.class, MediaType.APPLICATION_XML_TYPE);
}
@Path("JaxbBeanResourceMediaType")
@Produces("application/foo+xml")
@Consumes("application/foo+xml")
public static class JaxbBeanResourceMediaType extends AResource<JaxbBean> {
}
@Test
public void testJaxbBeanRepresentationMediaType() {
_test(new JaxbBean("CONTENT"), JaxbBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
}
@Test
public void testJaxbBeanRepresentationError() {
final WebTarget target = target("JaxbBeanResource");
final String xml = "<root>foo</root>";
final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
assertEquals(400, cr.getStatus());
}
@Path("JaxbBeanTextResource")
@Produces("text/xml")
@Consumes("text/xml")
public static class JaxbBeanTextResource extends AResource<JaxbBean> {
}
@Test
public void testJaxbBeanTextRepresentation() {
_test(new JaxbBean("CONTENT"), JaxbBeanTextResource.class, MediaType.TEXT_XML_TYPE);
}
@Path("JAXBElementBeanResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JAXBElementBeanResource extends AResource<JAXBElement<JaxbBeanType>> {
}
@Test
public void testJAXBElementBeanRepresentation() {
_test(new JaxbBean("CONTENT"), JAXBElementBeanResource.class, MediaType.APPLICATION_XML_TYPE);
}
@Path("JAXBElementListResource")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public static class JAXBElementListResource extends AResource<List<JAXBElement<String>>> {
}
private List<JAXBElement<String>> getJAXBElementList() {
return Arrays.asList(getJAXBElementArray());
}
@Test
public void testJAXBElementListXMLRepresentation() {
_testListOrArray(true, MediaType.APPLICATION_XML_TYPE);
}
@SuppressWarnings("unchecked")
public void _testListOrArray(final boolean isList, final MediaType mt) {
final Object in = isList ? getJAXBElementList() : getJAXBElementArray();
final GenericType gt = isList ? new GenericType<List<JAXBElement<String>>>() {
} : new GenericType<JAXBElement<String>[]>() {
};
final WebTarget target = target(isList ? "JAXBElementListResource" : "JAXBElementArrayResource");
final Object out = target.request(mt).post(Entity.entity(new GenericEntity(in, gt.getType()), mt), gt);
final List<JAXBElement<String>> inList =
isList ? ((List<JAXBElement<String>>) in) : Arrays.asList((JAXBElement<String>[]) in);
final List<JAXBElement<String>> outList = isList ? ((List<JAXBElement<String>>) out) : Arrays
.asList((JAXBElement<String>[]) out);
assertEquals("Lengths differ", inList.size(), outList.size());
for (int i = 0; i < inList.size(); i++) {
assertEquals("Names of elements at index " + i + " differ", inList.get(i).getName(), outList.get(i).getName());
assertEquals("Values of elements at index " + i + " differ", inList.get(i).getValue(), outList.get(i).getValue());
}
}
@Path("JAXBElementArrayResource")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public static class JAXBElementArrayResource extends AResource<JAXBElement<String>[]> {
}
private JAXBElement<String>[] getJAXBElementArray() {
//noinspection unchecked
return new JAXBElement[] {
new JAXBElement(QName.valueOf("element1"), String.class, "ahoj"),
new JAXBElement(QName.valueOf("element2"), String.class, "nazdar")
};
}
@Test
public void testJAXBElementArrayXMLRepresentation() {
_testListOrArray(false, MediaType.APPLICATION_XML_TYPE);
}
@Path("JAXBElementBeanResourceMediaType")
@Produces("application/foo+xml")
@Consumes("application/foo+xml")
public static class JAXBElementBeanResourceMediaType extends AResource<JAXBElement<JaxbBeanType>> {
}
@Test
public void testJAXBElementBeanRepresentationMediaType() {
_test(new JaxbBean("CONTENT"), JAXBElementBeanResourceMediaType.class, MediaType.valueOf("application/foo+xml"));
}
@Test
public void testJAXBElementBeanRepresentationError() {
final WebTarget target = target("JAXBElementBeanResource");
final String xml = "<root><value>foo";
final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
assertEquals(400, cr.getStatus());
}
@Path("JAXBElementBeanTextResource")
@Produces("text/xml")
@Consumes("text/xml")
public static class JAXBElementBeanTextResource extends AResource<JAXBElement<JaxbBeanType>> {
}
@Test
public void testJAXBElementBeanTextRepresentation() {
_test(new JaxbBean("CONTENT"), JAXBElementBeanTextResource.class, MediaType.TEXT_XML_TYPE);
}
@Path("JAXBTypeResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JAXBTypeResource {
@POST
public JaxbBean post(final JaxbBeanType t) {
return new JaxbBean(t.value);
}
}
@Override
protected Application configure() {
return ((ResourceConfig) super.configure()).register(new MoxyXmlFeature(SimpleBean.class));
}
@Override
protected void configureClient(final ClientConfig config) {
super.configureClient(config);
config.register(new MoxyXmlFeature(SimpleBean.class));
}
@Test
public void testJAXBTypeRepresentation() {
final WebTarget target = target("JAXBTypeResource");
final JaxbBean in = new JaxbBean("CONTENT");
final JaxbBeanType out = target.request().post(Entity.entity(in, "application/xml"), JaxbBeanType.class);
assertEquals(in.value, out.value);
}
@Path("JAXBTypeResourceMediaType")
@Produces("application/foo+xml")
@Consumes("application/foo+xml")
public static class JAXBTypeResourceMediaType extends JAXBTypeResource {
}
@Test
public void testJAXBTypeRepresentationMediaType() {
final WebTarget target = target("JAXBTypeResourceMediaType");
final JaxbBean in = new JaxbBean("CONTENT");
final JaxbBeanType out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBeanType.class);
assertEquals(in.value, out.value);
}
@Path("JAXBObjectResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JAXBObjectResource {
@POST
public Object post(final Object o) {
return o;
}
}
@Provider
public static class JAXBObjectResolver implements ContextResolver<JAXBContext> {
public JAXBContext getContext(final Class<?> c) {
if (Object.class == c) {
try {
return JAXBContext.newInstance(JaxbBean.class);
} catch (final JAXBException ex) {
// NOOP.
}
}
return null;
}
}
@Test
public void testJAXBObjectRepresentation() {
final WebTarget target = target("JAXBObjectResource");
final Object in = new JaxbBean("CONTENT");
final JaxbBean out = target.request().post(Entity.entity(in, "application/xml"), JaxbBean.class);
assertEquals(in, out);
}
@Path("JAXBObjectResourceMediaType")
@Produces("application/foo+xml")
@Consumes("application/foo+xml")
public static class JAXBObjectResourceMediaType extends JAXBObjectResource {
}
@Test
public void testJAXBObjectRepresentationMediaType() {
final WebTarget target = target("JAXBObjectResourceMediaType");
final Object in = new JaxbBean("CONTENT");
final JaxbBean out = target.request().post(Entity.entity(in, "application/foo+xml"), JaxbBean.class);
assertEquals(in, out);
}
@Test
public void testJAXBObjectRepresentationError() {
final WebTarget target = target("JAXBObjectResource");
final String xml = "<root>foo</root>";
final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
assertEquals(400, cr.getStatus());
}
@Path("JAXBListResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JAXBListResource {
@POST
public List<JaxbBean> post(final List<JaxbBean> l) {
return l;
}
@POST
@Path("set")
public Set<JaxbBean> postSet(final Set<JaxbBean> l) {
return l;
}
@POST
@Path("queue")
public Queue<JaxbBean> postQueue(final Queue<JaxbBean> l) {
return l;
}
@POST
@Path("stack")
public Stack<JaxbBean> postStack(final Stack<JaxbBean> l) {
return l;
}
@POST
@Path("custom")
public MyArrayList<JaxbBean> postCustom(final MyArrayList<JaxbBean> l) {
return l;
}
@GET
public Collection<JaxbBean> get() {
final ArrayList<JaxbBean> l = new ArrayList<>();
l.add(new JaxbBean("one"));
l.add(new JaxbBean("two"));
l.add(new JaxbBean("three"));
return l;
}
@POST
@Path("type")
public List<JaxbBean> postType(final Collection<JaxbBeanType> l) {
final List<JaxbBean> beans = new ArrayList<>();
for (final JaxbBeanType t : l) {
beans.add(new JaxbBean(t.value));
}
return beans;
}
}
@Path("JAXBArrayResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class JAXBArrayResource {
@POST
public JaxbBean[] post(final JaxbBean[] l) {
return l;
}
@GET
public JaxbBean[] get() {
final ArrayList<JaxbBean> l = new ArrayList<>();
l.add(new JaxbBean("one"));
l.add(new JaxbBean("two"));
l.add(new JaxbBean("three"));
return l.toArray(new JaxbBean[l.size()]);
}
@POST
@Path("type")
public JaxbBean[] postType(final JaxbBeanType[] l) {
final List<JaxbBean> beans = new ArrayList<>();
for (final JaxbBeanType t : l) {
beans.add(new JaxbBean(t.value));
}
return beans.toArray(new JaxbBean[beans.size()]);
}
}
@Test
public void testJAXBArrayRepresentation() {
final WebTarget target = target("JAXBArrayResource");
final JaxbBean[] a = target.request().get(JaxbBean[].class);
JaxbBean[] b = target.request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
assertEquals(a.length, b.length);
for (int i = 0; i < a.length; i++) {
assertEquals(a[i], b[i]);
}
b = target.path("type").request().post(Entity.entity(a, "application/xml"), JaxbBean[].class);
assertEquals(a.length, b.length);
for (int i = 0; i < a.length; i++) {
assertEquals(a[i], b[i]);
}
}
@Path("JAXBListResourceMediaType")
@Produces("application/foo+xml")
@Consumes("application/foo+xml")
public static class JAXBListResourceMediaType extends JAXBListResource {
}
@Test
public void testJAXBListRepresentationMediaType() {
final WebTarget target = target("JAXBListResourceMediaType");
Collection<JaxbBean> a = target.request().get(
new GenericType<Collection<JaxbBean>>() {
});
Collection<JaxbBean> b = target.request()
.post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {}, "application/foo+xml"),
new GenericType<Collection<JaxbBean>>() {});
assertEquals(a, b);
b = target.path("type").request().post(Entity.entity(new GenericEntity<Collection<JaxbBean>>(a) {
}, "application/foo+xml"), new GenericType<Collection<JaxbBean>>() {
});
assertEquals(a, b);
a = new LinkedList<>(a);
b = target.path("queue").request().post(Entity.entity(new GenericEntity<Queue<JaxbBean>>((Queue<JaxbBean>) a) {
}, "application/foo+xml"), new GenericType<Queue<JaxbBean>>() {
});
assertEquals(a, b);
a = new HashSet<>(a);
b = target.path("set").request().post(Entity.entity(new GenericEntity<Set<JaxbBean>>((Set<JaxbBean>) a) {
}, "application/foo+xml"), new GenericType<Set<JaxbBean>>() {
});
final Comparator<JaxbBean> c = new Comparator<JaxbBean>() {
@Override
public int compare(final JaxbBean t, final JaxbBean t1) {
return t.value.compareTo(t1.value);
}
};
final TreeSet<JaxbBean> t1 = new TreeSet<>(c);
final TreeSet<JaxbBean> t2 = new TreeSet<>(c);
t1.addAll(a);
t2.addAll(b);
assertEquals(t1, t2);
final Stack<JaxbBean> s = new Stack<>();
s.addAll(a);
b = target.path("stack").request().post(Entity.entity(new GenericEntity<Stack<JaxbBean>>(s) {
}, "application/foo+xml"), new GenericType<Stack<JaxbBean>>() {
});
assertEquals(s, b);
a = new MyArrayList<>(a);
b = target.path("custom").request()
.post(Entity.entity(new GenericEntity<MyArrayList<JaxbBean>>((MyArrayList<JaxbBean>) a) {
}, "application/foo+xml"), new GenericType<MyArrayList<JaxbBean>>() {
});
assertEquals(a, b);
}
@Test
public void testJAXBListRepresentationError() {
final WebTarget target = target("JAXBListResource");
final String xml = "<root><value>foo";
final Response cr = target.request().post(Entity.entity(xml, "application/xml"));
assertEquals(400, cr.getStatus());
}
@SuppressWarnings("UnusedDeclaration")
public static class SimpleBean {
private String value;
public SimpleBean() {
}
public SimpleBean(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
}
@SuppressWarnings("UnusedDeclaration")
@XmlRootElement
public static class ComplexJaxbBean {
private Object simpleBean;
public ComplexJaxbBean() {
}
public ComplexJaxbBean(final Object simpleBean) {
this.simpleBean = simpleBean;
}
public Object getSimpleBean() {
return simpleBean;
}
public void setSimpleBean(final Object simpleBean) {
this.simpleBean = simpleBean;
}
}
@Path("AdditionalClassesResource")
@Produces("application/xml")
@Consumes("application/xml")
public static class AdditionalClassesResource {
@GET
public ComplexJaxbBean get() {
return new ComplexJaxbBean(new SimpleBean("foo"));
}
}
@Test
public void testAdditionalClasses() throws Exception {
final ComplexJaxbBean nonJaxbBean = target("AdditionalClassesResource").request().get(ComplexJaxbBean.class);
final Object simpleBean = nonJaxbBean.getSimpleBean();
assertThat(simpleBean, notNullValue());
assertThat(simpleBean, instanceOf(SimpleBean.class));
assertThat("foo", equalTo(((SimpleBean) simpleBean).getValue()));
}
}