HeaderDelegateProviderTest.java
/*
* Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.tests.e2e.header;
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.message.internal.HeaderUtils;
import org.glassfish.jersey.message.internal.HeaderValueException;
import org.glassfish.jersey.message.internal.InboundMessageContext;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
import org.glassfish.jersey.spi.HeaderDelegateProvider;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ReaderInterceptor;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.fail;
public class HeaderDelegateProviderTest {
static final String HEADER_NAME = "BEAN_HEADER";
static final String DISABLED_VALUE = new BeanForHeaderDelegateProviderTest().toString();
public static class BeanHeaderDelegateProvider implements HeaderDelegateProvider<BeanForHeaderDelegateProviderTest> {
@Override
public boolean supports(Class type) {
return BeanForHeaderDelegateProviderTest.class == type;
}
@Override
public BeanForHeaderDelegateProviderTest fromString(String value) {
return new BeanForHeaderDelegateProviderTest();
}
@Override
public String toString(BeanForHeaderDelegateProviderTest value) {
return value.getValue();
}
}
public static class EmptyContentTypeHandler implements HeaderDelegateProvider<MediaType> {
@Override
public boolean supports(Class<?> type) {
return MediaType.class == type;
}
@Override
public MediaType fromString(String value) {
return value.isEmpty() ? MediaType.APPLICATION_OCTET_STREAM_TYPE : MediaType.valueOf(value);
}
@Override
public String toString(MediaType value) {
return value.toString();
}
};
public static class BeanForHeaderDelegateProviderTest {
public static String getValue() {
return "CORRECT_VALUE";
}
@Override
public String toString() {
return "INVALID_VALUE";
}
}
@Path("/")
public static final class HeaderSettingResource {
@GET
@Path("/simple")
public Response simple() {
return Response.ok().header(HEADER_NAME, new BeanForHeaderDelegateProviderTest()).build();
}
@GET
@Path("/headers")
public Response headers(@Context HttpHeaders headers) {
return Response.ok()
.header(HeaderSettingResource.class.getSimpleName(), headers.getHeaderString(HEADER_NAME)).build();
}
@GET
@Path("/clientfilter")
public Response clientFilterTest(@Context HttpHeaders headers) {
return Response.ok(headers.getHeaderString(HeaderClientRequestFilter.class.getSimpleName())).build();
}
}
public static final class HeaderContainerResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
String value = responseContext.getHeaderString(HEADER_NAME);
responseContext.getHeaders().putSingle(HeaderContainerResponseFilter.class.getSimpleName(), value);
}
}
public static final class HeaderClientRequestFilter implements ClientRequestFilter {
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.getHeaders().putSingle(
HeaderClientRequestFilter.class.getSimpleName(), new BeanForHeaderDelegateProviderTest()
);
}
}
@Test
public void testTheProviderIsFound() {
int found = 0;
for (HeaderDelegateProvider provider : ServiceFinder.find(HeaderDelegateProvider.class, true)) {
if (provider.getClass() == BeanHeaderDelegateProvider.class
|| provider.getClass() == EmptyContentTypeHandler.class) {
found++;
}
}
Assertions.assertEquals(2, found);
}
@Test
public void testHeaderDelegateIsUsedWhenRuntimeDelegateDecoratorIsUsed() {
MultivaluedHashMap headers = new MultivaluedHashMap();
headers.put(HEADER_NAME, Arrays.asList(new BeanForHeaderDelegateProviderTest()));
MultivaluedMap<String, String> converted = HeaderUtils.asStringHeaders(headers, (Configuration) null);
testMap(converted, BeanForHeaderDelegateProviderTest.getValue());
Client client = ClientBuilder.newClient().property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, false);
converted = HeaderUtils.asStringHeaders(headers, client.getConfiguration());
testMap(converted, BeanForHeaderDelegateProviderTest.getValue());
}
@Test
public void testHeaderDelegateIsNotUsed() {
MultivaluedHashMap headers = new MultivaluedHashMap();
headers.put(HEADER_NAME, Arrays.asList(new BeanForHeaderDelegateProviderTest()));
Client client = ClientBuilder.newClient().property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
MultivaluedMap<String, String> converted = HeaderUtils.asStringHeaders(headers, client.getConfiguration());
testMap(converted, DISABLED_VALUE);
client = ClientBuilder.newClient().property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE_CLIENT, true);
converted = HeaderUtils.asStringHeaders(headers, client.getConfiguration());
testMap(converted, DISABLED_VALUE);
}
@Test
public void testGetMediaTypeInInboundMessageContext() {
ClientConfig config = new ClientConfig().property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
InboundMessageContext inboundMessageContext = new InboundMessageContext(config.getConfiguration()) {
@Override
protected Iterable<ReaderInterceptor> getReaderInterceptors() {
return null;
}
};
inboundMessageContext.header(HttpHeaders.CONTENT_TYPE, "");
try {
inboundMessageContext.getMediaType();
fail("Expected HeaderValueException has not been thrown");
} catch (HeaderValueException ex) {
// expected
}
config.property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, false);
inboundMessageContext = new InboundMessageContext(config.getConfiguration()) {
@Override
protected Iterable<ReaderInterceptor> getReaderInterceptors() {
return null;
}
};
inboundMessageContext.header(HttpHeaders.CONTENT_TYPE, "");
MediaType mediaType = inboundMessageContext.getMediaType();
Assertions.assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, mediaType);
}
@Test
public void testGetMediaTypeInOutboundMessageContext() {
ClientConfig config = new ClientConfig().property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
OutboundMessageContext outboundMessageContext = new OutboundMessageContext(config.getConfiguration());
outboundMessageContext.getHeaders().add(HttpHeaders.CONTENT_TYPE, "");
try {
outboundMessageContext.getMediaType();
fail("Expected HeaderValueException has not been thrown");
} catch (IllegalArgumentException ex) {
// expected
}
config.property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, false);
outboundMessageContext = new OutboundMessageContext(config.getConfiguration());
outboundMessageContext.getHeaders().add(HttpHeaders.CONTENT_TYPE, "");
MediaType mediaType = outboundMessageContext.getMediaType();
Assertions.assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, mediaType);
}
private void testMap(MultivaluedMap<String, String> map, String expectedValue) {
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
Assertions.assertEquals(HEADER_NAME, entry.getKey());
Assertions.assertEquals(expectedValue, entry.getValue().iterator().next());
}
}
}