/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * 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 the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>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.apereo.portal.portlet.container.cache; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Collections; import javax.portlet.CacheControl; import javax.portlet.MimeResponse; import javax.portlet.PortletMode; import javax.portlet.WindowState; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import org.apache.pluto.container.om.portlet.PortletDefinition; import org.apereo.portal.mock.portlet.om.MockPortletDefinitionId; import org.apereo.portal.mock.portlet.om.MockPortletWindowId; import org.apereo.portal.portlet.om.IPortletEntity; import org.apereo.portal.portlet.om.IPortletWindow; import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; import org.apereo.portal.portlet.registry.IPortletWindowRegistry; import org.apereo.portal.portlet.rendering.PortletRenderResult; import org.apereo.portal.url.IPortalRequestInfo; import org.apereo.portal.url.IUrlSyntaxProvider; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; /** */ @RunWith(MockitoJUnitRunner.class) public class PortletCacheControlServiceImplTest { @InjectMocks private PortletCacheControlServiceImpl cacheControlService = new PortletCacheControlServiceImpl(); @Mock private IPortletWindowRegistry portletWindowRegistry; @Mock private IPortletDefinitionRegistry portletDefinitionRegistry; @Mock private IUrlSyntaxProvider urlSyntaxProvider; @Mock private IPortletWindow portletWindow; @Mock private IPortletEntity portletEntity; @Mock private PortletDefinition portletDescriptor; @Mock private IPortalRequestInfo portalRequestInfo; private CacheManager cacheManager; private Cache privateScopeRenderHeaderCache; private Cache publicScopeRenderHeaderCache; private Cache privateScopeRenderCache; private Cache publicScopeRenderCache; private Cache privateScopeResourceCache; private Cache publicScopeResourceCache; @Before public void getCaches() { cacheManager = new CacheManager( this.getClass().getResource("/portletCacheControlServiceTestEhcache.xml")); privateScopeRenderHeaderCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.privateScopePortletRenderHeaderOutputCache"); publicScopeRenderHeaderCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.publicScopePortletRenderHeaderOutputCache"); privateScopeRenderCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.privateScopePortletRenderOutputCache"); publicScopeRenderCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.publicScopePortletRenderOutputCache"); privateScopeResourceCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.privateScopePortletResourceOutputCache"); publicScopeResourceCache = cacheManager.getCache( "org.apereo.portal.portlet.container.cache.PortletCacheControlServiceImpl.publicScopePortletResourceOutputCache"); cacheControlService.setPrivateScopePortletRenderHeaderOutputCache( privateScopeRenderHeaderCache); cacheControlService.setPublicScopePortletRenderHeaderOutputCache( publicScopeRenderHeaderCache); cacheControlService.setPrivateScopePortletRenderOutputCache(privateScopeRenderCache); cacheControlService.setPublicScopePortletRenderOutputCache(publicScopeRenderCache); cacheControlService.setPrivateScopePortletResourceOutputCache(privateScopeResourceCache); cacheControlService.setPublicScopePortletResourceOutputCache(publicScopeResourceCache); } @After public void clearCaches() { privateScopeRenderHeaderCache.removeAll(true); publicScopeRenderHeaderCache.removeAll(true); privateScopeRenderCache.removeAll(true); publicScopeRenderCache.removeAll(true); privateScopeResourceCache.removeAll(true); publicScopeResourceCache.removeAll(true); cacheManager.shutdown(); } @Test public void testGetCacheControlDefault() { MockHttpServletRequest httpRequest = new MockHttpServletRequest(); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); when(portletDescriptor.getCacheScope()).thenReturn(null); final IPortletWindowRegistry portletWindowRegistry = mock(IPortletWindowRegistry.class); final IPortletWindow portletWindow = mock(IPortletWindow.class); final IPortletEntity portletEntity = mock(IPortletEntity.class); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDescriptor); final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> cacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); final CacheControl cacheControl = cacheState.getCacheControl(); assertFalse(cacheControl.isPublicScope()); assertNull(cacheControl.getETag()); } @Test public void testGetCacheControlDataExistsInPrivateCache() { // mock 2 requests, have to share sessionId for private cache MockHttpSession mockSession = new MockHttpSession(); MockHttpServletRequest httpRequest = new MockHttpServletRequest(); httpRequest.setSession(mockSession); MockHttpServletRequest nextHttpRequest = new MockHttpServletRequest(); nextHttpRequest.setSession(mockSession); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); // use private cache when(portletDescriptor.getCacheScope()).thenReturn("private"); when(portletDescriptor.getExpirationCache()).thenReturn(300); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindowRegistry.getPortletWindow(nextHttpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletWindowId()).thenReturn(portletWindowId); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDescriptor); when(urlSyntaxProvider.getPortalRequestInfo(httpRequest)).thenReturn(portalRequestInfo); final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> cacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); final CacheControl cacheControl = cacheState.getCacheControl(); assertFalse(cacheControl.isPublicScope()); cacheControl.setETag("123456"); final PortletRenderResult portletResult = new PortletRenderResult("title", null, 0, 1); final String content = "<p>Cached content</p>"; final CachedPortletData<PortletRenderResult> cachedPortletData = new CachedPortletData<PortletRenderResult>( portletResult, content, null, null, cacheControl.isPublicScope(), cacheControl.getETag(), -2); cacheControlService.cachePortletRenderOutput( portletWindowId, nextHttpRequest, cacheState, cachedPortletData); when(urlSyntaxProvider.getPortalRequestInfo(nextHttpRequest)).thenReturn(portalRequestInfo); final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> afterCacheState = cacheControlService.getPortletRenderState(nextHttpRequest, portletWindowId); // retrieve cachecontrol again, and return should have etag set // note using 'nextHttpRequest' Assert.assertEquals("123456", afterCacheState.getCacheControl().getETag()); } @Test public void testDetermineCacheScopePortletDefinitionPrivate() { MockHttpServletRequest httpRequest = new MockHttpServletRequest(); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); PortletDefinition portletDefinition = mock(PortletDefinition.class); when(portletDefinition.getCacheScope()).thenReturn("private"); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletWindowId()).thenReturn(portletWindowId); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDefinition); when(urlSyntaxProvider.getPortalRequestInfo(httpRequest)).thenReturn(portalRequestInfo); cacheControlService.setPortletWindowRegistry(portletWindowRegistry); cacheControlService.setPortletDefinitionRegistry(portletDefinitionRegistry); final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> cacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); final CacheControl cacheControl = cacheState.getCacheControl(); assertFalse(cacheControl.isPublicScope()); } @Test public void testDetermineCacheScopePortletDefinitionPublic() { MockHttpServletRequest httpRequest = new MockHttpServletRequest(); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); when(portletDescriptor.getCacheScope()).thenReturn(MimeResponse.PUBLIC_SCOPE); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletWindowId()).thenReturn(portletWindowId); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDescriptor); when(urlSyntaxProvider.getPortalRequestInfo(httpRequest)).thenReturn(portalRequestInfo); cacheControlService.setPortletWindowRegistry(portletWindowRegistry); cacheControlService.setPortletDefinitionRegistry(portletDefinitionRegistry); final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> cacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); final CacheControl cacheControl = cacheState.getCacheControl(); assertTrue(cacheControl.isPublicScope()); } @Test public void testCachePrivateRenderRoundTrip() { MockHttpServletRequest httpRequest = new MockHttpServletRequest(); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); when(portletDescriptor.getCacheScope()).thenReturn(MimeResponse.PUBLIC_SCOPE); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletWindowId()).thenReturn(portletWindowId); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDescriptor); when(urlSyntaxProvider.getPortalRequestInfo(httpRequest)).thenReturn(portalRequestInfo); when(this.urlSyntaxProvider.getPortalRequestInfo(httpRequest)) .thenReturn(portalRequestInfo); when(portalRequestInfo.getPortletRequestInfoMap()).thenReturn(Collections.EMPTY_MAP); //Get the initial cache state final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> firstCacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); //Fake Render execution final CacheControl cacheControl = firstCacheState.getCacheControl(); cacheControl.setExpirationTime(300); final PortletRenderResult renderResult = new PortletRenderResult("title", null, 0, 1000l); final String output = "{ \"hello\": \"world\" }"; final CachedPortletData<PortletRenderResult> cachedPortletData = new CachedPortletData<PortletRenderResult>( renderResult, output, null, null, false, cacheControl.getETag(), cacheControl.getExpirationTime()); firstCacheState.setCachedPortletData(cachedPortletData); assertTrue(cacheControlService.shouldOutputBeCached(cacheControl)); //Cache the results cacheControlService.cachePortletRenderOutput( portletWindowId, httpRequest, firstCacheState, cachedPortletData); //Check the cached results final CacheState<CachedPortletData<PortletRenderResult>, PortletRenderResult> secondCacheState = cacheControlService.getPortletRenderState(httpRequest, portletWindowId); assertNotNull(secondCacheState); final CachedPortletData<PortletRenderResult> actualCachedPortletData = secondCacheState.getCachedPortletData(); assertNotNull(actualCachedPortletData); } @Test public void testCachePrivateResourceRoundTrip() { MockHttpServletRequest httpRequest = new MockHttpServletRequest(); MockPortletWindowId portletWindowId = new MockPortletWindowId("123"); MockPortletDefinitionId portletDefinitionId = new MockPortletDefinitionId(789); when(portletDescriptor.getCacheScope()).thenReturn(MimeResponse.PUBLIC_SCOPE); when(portletWindowRegistry.getPortletWindow(httpRequest, portletWindowId)) .thenReturn(portletWindow); when(portletWindow.getPortletWindowId()).thenReturn(portletWindowId); when(portletWindow.getPortletEntity()).thenReturn(portletEntity); when(portletWindow.getWindowState()).thenReturn(WindowState.NORMAL); when(portletWindow.getPortletMode()).thenReturn(PortletMode.VIEW); when(portletEntity.getPortletDefinitionId()).thenReturn(portletDefinitionId); when(portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId)) .thenReturn(portletDescriptor); when(this.urlSyntaxProvider.getPortalRequestInfo(httpRequest)) .thenReturn(portalRequestInfo); when(portalRequestInfo.getPortletRequestInfoMap()).thenReturn(Collections.EMPTY_MAP); //Get the initial cache state final CacheState<CachedPortletResourceData<Long>, Long> firstCacheState = cacheControlService.getPortletResourceState(httpRequest, portletWindowId); //Fake resource execution final CacheControl cacheControl = firstCacheState.getCacheControl(); cacheControl.setExpirationTime(300); final String output = "{ \"hello\": \"world\" }"; final CachedPortletData<Long> cachedPortletData = new CachedPortletData<Long>( 1000l, output, null, "application/json", false, cacheControl.getETag(), cacheControl.getExpirationTime()); final CachedPortletResourceData<Long> cachedPortletResourceData = new CachedPortletResourceData<Long>( cachedPortletData, Collections.EMPTY_MAP, null, null, null, null); firstCacheState.setCachedPortletData(cachedPortletResourceData); assertTrue(cacheControlService.shouldOutputBeCached(cacheControl)); //Cache the results cacheControlService.cachePortletResourceOutput( portletWindowId, httpRequest, firstCacheState, cachedPortletResourceData); //Check the cached results final CacheState<CachedPortletResourceData<Long>, Long> secondCacheState = cacheControlService.getPortletResourceState(httpRequest, portletWindowId); assertNotNull(secondCacheState); final CachedPortletResourceData<Long> actualCachedPortletData = secondCacheState.getCachedPortletData(); assertNotNull(actualCachedPortletData); } }