/******************************************************************************* * Copyright (c) 2012-2016 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.everrest.core; import org.everrest.core.impl.EnvironmentContext; import org.everrest.core.impl.EverrestConfiguration; import org.everrest.core.impl.LifecycleComponent; import org.everrest.core.impl.ProviderBinder; import org.everrest.core.impl.async.AsynchronousJobPool; import org.everrest.core.impl.async.AsynchronousMethodInvoker; import org.everrest.core.impl.method.DefaultMethodInvoker; import org.everrest.core.impl.method.MethodInvokerDecorator; import org.everrest.core.impl.method.MethodInvokerDecoratorFactory; import org.everrest.core.impl.method.OptionsRequestMethodInvoker; import org.everrest.core.impl.uri.PathSegmentImpl; import org.everrest.core.method.MethodInvoker; import org.everrest.core.resource.GenericResourceMethod; import org.everrest.core.resource.ResourceMethodDescriptor; import org.everrest.core.servlet.ServletContainerRequest; import org.everrest.core.tools.SimpleSecurityContext; import org.everrest.core.tools.WebApplicationDeclaredRoles; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import javax.ws.rs.core.Application; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.PathSegment; import java.net.URI; import java.security.Principal; import java.util.List; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Sets.newHashSet; import static org.everrest.core.ApplicationContext.anApplicationContext; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ApplicationContextTest { @Rule public ExpectedException thrown = ExpectedException.none(); private GenericContainerRequest request; private GenericContainerResponse response; private ProviderBinder providers; private EnvironmentContext environmentContext; private ApplicationContext applicationContext; @Before public void setUp() throws Exception { request = mock(ServletContainerRequest.class); response = mock(GenericContainerResponse.class); providers = mock(ProviderBinder.class); environmentContext = mock(EnvironmentContext.class); EnvironmentContext.setCurrent(environmentContext); applicationContext = anApplicationContext() .withRequest(request) .withResponse(response) .withProviders(providers) .build(); } @Test public void addsMatchedResourceAtBeginningOfMatchedResourcesList() { Object resourceOne = new Object(); Object resourceTwo = new Object(); applicationContext.addMatchedResource(resourceOne); applicationContext.addMatchedResource(resourceTwo); assertEquals(newArrayList(resourceTwo, resourceOne), applicationContext.getMatchedResources()); } @Test public void addsMatchedUriAtBeginningOfMatchedUrisList() { String uriOne = "a/%20b%20"; String uriTwo = "c/d"; applicationContext.addMatchedURI(uriOne); applicationContext.addMatchedURI(uriTwo); assertEquals(newArrayList("c/d", "a/ b "), applicationContext.getMatchedURIs()); assertEquals(newArrayList(uriTwo, uriOne), applicationContext.getMatchedURIs(false)); } @Test public void getsAbsolutePathAndRemovesQueryParametersAndFragment() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b/c?q#f")); assertEquals(URI.create("http://localhost:8080/a/b/c"), applicationContext.getAbsolutePath()); } @Test public void getsAbsolutePathBuilderAndRemovesQueryParametersAndFragment() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b/c?q#f")); assertEquals(URI.create("http://localhost:8080/a/b/c"), applicationContext.getAbsolutePathBuilder().build()); } @Test public void getsNonNullAttributesMap() { assertNotNull(applicationContext.getAttributes()); } @Test public void getsBaseUri() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet")); assertEquals(URI.create("http://localhost:8080/servlet"), applicationContext.getBaseUri()); } @Test public void getsBaseUriBuilder() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet/")); assertEquals(URI.create("http://localhost:8080/servlet/"), applicationContext.getBaseUriBuilder().build()); } @Test public void getsContainerRequest() { assertSame(request, applicationContext.getContainerRequest()); } @Test public void getsRequest() { assertSame(request, applicationContext.getRequest()); } @Test public void getsContainerResponse() { assertSame(response, applicationContext.getContainerResponse()); } @Test public void getsHttpHeaders() { assertSame(request, applicationContext.getHttpHeaders()); } @Test public void resolvesUriAgainstBaseUri() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/a/b/")); assertEquals(URI.create("http://localhost:8080/a/b/c"), applicationContext.resolve(URI.create("c"))); } @Test public void relativizesUriAgainstRequestUri() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/a/b/")); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b/c/d")); assertEquals(URI.create("y"), applicationContext.relativize(URI.create("c/d/y"))); } @Test public void getsMethodInvoker() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getMethod()).thenReturn("GET"); MethodInvoker methodInvoker = applicationContext.getMethodInvoker(mock(GenericResourceMethod.class)); assertTrue(String.format("Expected instance of DefaultMethodInvoker but actual is %s", methodInvoker), methodInvoker instanceof DefaultMethodInvoker); } @Test public void getsDecoratedMethodInvoker() { MethodInvokerDecoratorFactory methodInvokerDecoratorFactory = mock(MethodInvokerDecoratorFactory.class); when(methodInvokerDecoratorFactory.makeDecorator(isA(MethodInvoker.class))) .thenAnswer(invocation -> new MethodInvokerDecorator((MethodInvoker)invocation.getArguments()[0])); applicationContext = anApplicationContext() .withRequest(request) .withResponse(response) .withProviders(providers) .withMethodInvokerDecoratorFactory(methodInvokerDecoratorFactory) .build(); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getMethod()).thenReturn("GET"); MethodInvoker methodInvoker = applicationContext.getMethodInvoker(mock(GenericResourceMethod.class)); assertTrue(String.format("Expected instance of MethodInvokerDecorator but actual is %s", methodInvoker), methodInvoker instanceof MethodInvokerDecorator); } @Test public void getsMethodInvokerFor_OPTIONS_Request() { when(request.getMethod()).thenReturn("OPTIONS"); MethodInvoker methodInvoker = applicationContext.getMethodInvoker(mock(GenericResourceMethod.class)); assertTrue(String.format("Expected instance of OptionsRequestMethodInvoker but actual is %s", methodInvoker), methodInvoker instanceof OptionsRequestMethodInvoker); } @Test public void getsAsynchronousMethodInvokerWhenCallerProvidesAsyncQueryParameter() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b?async=true")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getMethod()).thenReturn("GET"); when(providers.getContextResolver(AsynchronousJobPool.class, null)).thenReturn(mock(AsynchronousJobPool.class)); MethodInvoker methodInvoker = applicationContext.getMethodInvoker(mock(ResourceMethodDescriptor.class)); assertTrue(String.format("Expected instance of AsynchronousMethodInvoker but actual is %s", methodInvoker), methodInvoker instanceof AsynchronousMethodInvoker); } @Test public void getsAsynchronousMethodInvokerWhenCallerProvidesAsyncHeaderParameter() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b")); MultivaluedMap<String, String> headers = new MultivaluedHashMap<>(); headers.putSingle("x-everrest-async", "true"); when(request.getRequestHeaders()).thenReturn(headers); when(request.getMethod()).thenReturn("GET"); when(providers.getContextResolver(AsynchronousJobPool.class, null)).thenReturn(mock(AsynchronousJobPool.class)); MethodInvoker methodInvoker = applicationContext.getMethodInvoker(mock(ResourceMethodDescriptor.class)); assertTrue(String.format("Expected instance of AsynchronousMethodInvoker but actual is %s", methodInvoker), methodInvoker instanceof AsynchronousMethodInvoker); } @Test public void throwsExceptionWhenAsynchronousFeatureIsNotConfiguredButCallerRequestsAsynchronousInvocation() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b?async=true")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getMethod()).thenReturn("GET"); thrown.expect(IllegalStateException.class); applicationContext.getMethodInvoker(mock(ResourceMethodDescriptor.class)); } @Test public void getsEncodedPath() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet")); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a/%20b")); assertEquals("/a/%20b", applicationContext.getPath(false)); } @Test public void getsDecodedPath() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet")); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a/%20b")); assertEquals("/a/ b", applicationContext.getPath()); } @Test public void getsEncodedPathParameters() { applicationContext.getParameterValues().addAll(newArrayList("x", "%20y%20")); applicationContext.setParameterNames(newArrayList("a", "b")); MultivaluedMap<String, String> expectedParameters = new MultivaluedHashMap<>(); expectedParameters.putSingle("a", "x"); expectedParameters.putSingle("b", "%20y%20"); assertEquals(expectedParameters, applicationContext.getPathParameters(false)); } @Test public void getsDecodedPathParameters() { applicationContext.getParameterValues().addAll(newArrayList("x", "%20y%20")); applicationContext.setParameterNames(newArrayList("a", "b")); MultivaluedMap<String, String> expectedParameters = new MultivaluedHashMap<>(); expectedParameters.putSingle("a", "x"); expectedParameters.putSingle("b", " y "); assertEquals(expectedParameters, applicationContext.getPathParameters()); } @Test public void getsEncodedPathSegments() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet")); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a/%20b;x=y")); List<PathSegment> expectedPathSegments = newArrayList(PathSegmentImpl.fromString("a", false), PathSegmentImpl.fromString("%20b;x=y", false)); assertEquals(expectedPathSegments, applicationContext.getPathSegments(false)); } @Test public void getsDecodedPathSegments() { when(request.getBaseUri()).thenReturn(URI.create("http://localhost:8080/servlet")); when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a/%20b;x=y")); List<PathSegment> expectedPathSegments = newArrayList(PathSegmentImpl.fromString("a", true), PathSegmentImpl.fromString("%20b;x=y", true)); assertEquals(expectedPathSegments, applicationContext.getPathSegments()); } @Test public void getsEncodedQueryParameters() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a?a=x&b=%20y%20")); MultivaluedMap<String, String> expectedQueryParameters = new MultivaluedHashMap<>(); expectedQueryParameters.putSingle("a", "x"); expectedQueryParameters.putSingle("b", "%20y%20"); assertEquals(expectedQueryParameters, applicationContext.getQueryParameters(false)); } @Test public void getsDecodedQueryParameters() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/servlet/a?a=x&b=%20y%20")); MultivaluedMap<String, String> expectedQueryParameters = new MultivaluedHashMap<>(); expectedQueryParameters.putSingle("a", "x"); expectedQueryParameters.putSingle("b", " y "); assertEquals(expectedQueryParameters, applicationContext.getQueryParameters()); } @Test public void getsNonPropertyMap() { assertNotNull(applicationContext.getProperties()); } @Test public void consumesProviderBinderAndReturnsItOnNextCall() { ProviderBinder providers = mock(ProviderBinder.class); applicationContext.setProviders(providers); assertSame(providers, applicationContext.getProviders()); } @Test public void getsSecurityContext() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); assertSame(request, applicationContext.getSecurityContext()); } @Test public void getsSimpleSecurityContextWhenCallerRequestsAsynchronousInvocation() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b?async=true")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); SimpleSecurityContext securityContext = (SimpleSecurityContext)applicationContext.getSecurityContext(); assertNotNull(securityContext); } @Test public void getsSimpleSecurityContextWithPrincipalFromRequestWhenCallerRequestsAsynchronousInvocation() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b?async=true")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getAuthenticationScheme()).thenReturn("BASIC_AUTH"); Principal principal = mockPrincipal("andrew"); when(request.getUserPrincipal()).thenReturn(principal); SimpleSecurityContext securityContext = (SimpleSecurityContext)applicationContext.getSecurityContext(); assertNotNull(securityContext); assertNotNull(securityContext.getUserPrincipal()); assertEquals(principal.getName(), securityContext.getUserPrincipal().getName()); assertEquals("BASIC_AUTH", securityContext.getAuthenticationScheme()); } @Test public void getsSimpleSecurityContextWithPrincipalFromRequestAndRolesFromWebApplicationDeclaredRolesWhenCallerRequestsAsynchronousInvocation() { when(request.getRequestUri()).thenReturn(URI.create("http://localhost:8080/a/b?async=true")); when(request.getRequestHeaders()).thenReturn(new MultivaluedHashMap<>()); when(request.getAuthenticationScheme()).thenReturn("BASIC_AUTH"); when(request.isUserInRole("user")).thenReturn(true); Principal principal = mockPrincipal("andrew"); when(request.getUserPrincipal()).thenReturn(principal); WebApplicationDeclaredRoles webApplicationDeclaredRoles = mockWebApplicationDeclaredRoles("user"); when(environmentContext.get(WebApplicationDeclaredRoles.class)).thenReturn(webApplicationDeclaredRoles); SimpleSecurityContext securityContext = (SimpleSecurityContext)applicationContext.getSecurityContext(); assertNotNull(securityContext); assertNotNull(securityContext.getUserPrincipal()); assertEquals(principal.getName(), securityContext.getUserPrincipal().getName()); assertEquals("BASIC_AUTH", securityContext.getAuthenticationScheme()); assertTrue(securityContext.isUserInRole("user")); assertFalse(securityContext.isUserInRole("admin")); } private Principal mockPrincipal(String name) { Principal principal = mock(Principal.class); when(principal.getName()).thenReturn(name); return principal; } private WebApplicationDeclaredRoles mockWebApplicationDeclaredRoles(String... roles) { WebApplicationDeclaredRoles webApplicationDeclaredRoles = mock(WebApplicationDeclaredRoles.class); when(webApplicationDeclaredRoles.getDeclaredRoles()).thenReturn(newHashSet(roles)); return webApplicationDeclaredRoles; } @Test public void getsNonNullEverrestConfiguration() { assertNotNull(applicationContext.getEverrestConfiguration()); } @Test public void consumesEverrestConfigurationAndReturnsItOnNextCall() { EverrestConfiguration configuration = mock(EverrestConfiguration.class); applicationContext.setEverrestConfiguration(configuration); assertSame(configuration, applicationContext.getEverrestConfiguration()); } @Test public void notifiesLifecycleComponentWhenStopped() { LifecycleComponent lifecycleComponent = mock(LifecycleComponent.class); applicationContext.getAttributes().put("org.everrest.lifecycle.PerRequest", newArrayList(lifecycleComponent)); applicationContext.stop(); verify(lifecycleComponent).destroy(); } @Test public void getsUriInfo() { assertSame(applicationContext, applicationContext.getUriInfo()); } @Test public void consumesDependencySupplierAndReturnsItOnNextCall() { DependencySupplier dependencySupplier = mock(DependencySupplier.class); applicationContext.setDependencySupplier(dependencySupplier); assertSame(dependencySupplier, applicationContext.getDependencySupplier()); } @Test public void consumesApplicationAndReturnsItOnNextCall() { Application application = mock(Application.class); applicationContext.setApplication(application); assertSame(application, applicationContext.getApplication()); } }