/*
* 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.json;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.JSONP;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
/**
* @author Michal Gajdos
*/
@RunWith(Parameterized.class)
public class JsonWithPaddingTest extends JerseyTest {
@SuppressWarnings("UnusedDeclaration")
@XmlRootElement
public static class JsonBean {
private String attribute;
public JsonBean() {
}
public JsonBean(final String attr) {
this.attribute = attr;
}
public static JsonBean createTestInstance() {
return new JsonBean("attr");
}
public String getAttribute() {
return attribute;
}
public void setAttribute(final String attribute) {
this.attribute = attribute;
}
}
@Path("jsonp")
@Produces({"application/x-javascript", "application/json"})
public static class JsonResource {
@GET
@Path("PureJson")
public JsonBean getPureJson() {
return JsonBean.createTestInstance();
}
@GET
@JSONP
@Path("JsonWithPaddingDefault")
public JsonBean getJsonWithPaddingDefault() {
return JsonBean.createTestInstance();
}
@GET
@JSONP(queryParam = "eval")
@Path("JsonWithPaddingQueryCallbackParam")
public JsonBean getJsonWithPaddingQueryCallbackParam() {
return JsonBean.createTestInstance();
}
@GET
@JSONP(callback = "parse", queryParam = "eval")
@Path("JsonWithPaddingCallbackAndQueryCallbackParam")
public JsonBean getJsonWithPaddingCallbackAndQueryCallbackParam() {
return JsonBean.createTestInstance();
}
@GET
@JSONP(callback = "eval")
@Path("JsonWithPaddingCallback")
public JsonBean getJsonWithPaddingCallback() {
return JsonBean.createTestInstance();
}
}
@Parameterized.Parameters(name = "{0}")
public static Collection<JsonTestProvider[]> getJsonProviders() throws Exception {
final List<JsonTestProvider[]> testProviders = new LinkedList<>();
for (final JsonTestProvider jsonProvider : JsonTestProvider.JAXB_PROVIDERS) {
testProviders.add(new JsonTestProvider[] {jsonProvider});
}
return testProviders;
}
private final JsonTestProvider jsonTestProvider;
private final String errorMessage;
public JsonWithPaddingTest(final JsonTestProvider jsonTestProvider) throws Exception {
super(configureJaxrsApplication(jsonTestProvider));
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
this.jsonTestProvider = jsonTestProvider;
this.errorMessage = String.format("%s: Received JSON entity content does not match expected JSON entity content.",
jsonTestProvider.getClass().getSimpleName());
}
@Override
protected void configureClient(final ClientConfig config) {
config.register(jsonTestProvider.getFeature());
}
private static Application configureJaxrsApplication(final JsonTestProvider jsonTestProvider) {
final ResourceConfig resourceConfig = new ResourceConfig()
.registerClasses(JsonResource.class)
.register(jsonTestProvider.getFeature());
if (jsonTestProvider.getProviders() != null) {
resourceConfig.registerInstances(jsonTestProvider.getProviders());
}
return resourceConfig;
}
@Test
public void testJson() throws Exception {
final Response response = target("jsonp").path("PureJson").request("application/json").get();
assertThat(response.getStatus(), equalTo(200));
assertThat(response.getMediaType().toString(), equalTo("application/json"));
final String entity = response.readEntity(String.class);
assertThat(errorMessage, entity, allOf(not(startsWith("callback(")), not(endsWith(")"))));
}
@Test
public void testJsonWithJavaScriptMediaType() throws Exception {
final Response response = target("jsonp").path("PureJson").request("application/x-javascript").get();
// Method is invoked but we do not have a MBW for application/x-javascript.
if (jsonTestProvider.getFeature().getClass() == JacksonFeature.class) {
assertThat(response.getStatus(), equalTo(200));
} else {
assertThat(response.getStatus(), equalTo(500));
}
}
@Test
public void testJsonWithPaddingDefault() throws Exception {
test("JsonWithPaddingDefault", "callback");
}
@Test
public void testJsonWithPaddingQueryCallbackParam() throws Exception {
test("JsonWithPaddingQueryCallbackParam", "eval", "parse");
}
@Test
public void testJsonWithPaddingQueryCallbackParamDefaultQueryParam() throws Exception {
test("JsonWithPaddingQueryCallbackParam", "callback", "parse", "callback");
}
@Test
public void testJsonWithPaddingQueryCallbackParamDefaultCallback() throws Exception {
test("JsonWithPaddingQueryCallbackParam", null, "callback");
}
@Test
public void testJsonWithPaddingQueryCallbackParamNegative() throws Exception {
test("JsonWithPaddingQueryCallbackParam", "call", "parse", true);
}
@Test
public void testJsonWithPaddingCallbackAndQueryCallbackParam() throws Exception {
test("JsonWithPaddingCallbackAndQueryCallbackParam", "eval", "run");
}
@Test
public void testJsonWithPaddingCallbackAndQueryCallbackParamNegative() throws Exception {
test("JsonWithPaddingCallbackAndQueryCallbackParam", "eval", "run", "parse", true);
}
@Test
public void testJsonWithPaddingCallbackAndQueryCallbackParamDefault() throws Exception {
test("JsonWithPaddingCallbackAndQueryCallbackParam", "evalx", "parse");
}
@Test
public void testJsonWithPaddingCallbackAndQueryCallbackParamDefaultNegative() throws Exception {
test("JsonWithPaddingCallbackAndQueryCallbackParam", "evalx", "xlave", "eval", true);
}
@Test
public void testJsonWithPaddingCallback() throws Exception {
test("JsonWithPaddingCallback", "eval", "eval");
}
@Test
public void testJsonWithPaddingCallbackNegative() throws Exception {
test("JsonWithPaddingCallback", "eval", "lave", true);
}
private void test(final String path, final String callback) {
test(path, null, null, callback);
}
private void test(final String path, final String queryParamName, final String callback) {
test(path, queryParamName, callback, callback, false);
}
private void test(final String path, final String queryParamName, final String callback, final boolean isNegative) {
test(path, queryParamName, callback, callback, isNegative);
}
private void test(final String path, final String queryParamName, final String queryParamValue, final String callback) {
test(path, queryParamName, queryParamValue, callback, false);
}
private void test(final String path, final String queryParamName, final String queryParamValue, final String callback,
final boolean isNegative) {
WebTarget tempTarget = target("jsonp").path(path);
if (queryParamName != null) {
tempTarget = tempTarget.queryParam(queryParamName, queryParamValue);
}
final Response response = tempTarget.request("application/x-javascript").get();
assertThat(response.getStatus(), equalTo(200));
assertThat(response.getMediaType().toString(), equalTo("application/x-javascript"));
final String entity = response.readEntity(String.class);
// Check the entity.
final Matcher<String> startsWith = startsWith(callback + "(");
final Matcher<String> endsWith = endsWith(")");
final Matcher<String> callbackMatcher = isNegative ? not(startsWith) : startsWith;
assertThat(errorMessage, entity, allOf(callbackMatcher, endsWith));
}
}