Java tutorial
/** * Copyright (C) 2015 Bonitasoft S.A. * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.console.common.server.page; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Properties; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.IOUtils; import org.bonitasoft.console.common.server.preferences.constants.WebBonitaConstantsUtils; import org.bonitasoft.console.common.server.preferences.properties.CompoundPermissionsMapping; import org.bonitasoft.console.common.server.preferences.properties.ConsoleProperties; import org.bonitasoft.console.common.server.preferences.properties.ResourcesPermissionsMapping; import org.bonitasoft.engine.api.PageAPI; import org.bonitasoft.engine.exception.AlreadyExistsException; import org.bonitasoft.engine.page.Page; import org.bonitasoft.engine.page.PageNotFoundException; import org.bonitasoft.engine.session.APISession; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import groovy.lang.GroovyClassLoader; @RunWith(MockitoJUnitRunner.class) public class CustomPageServiceTest { public static final String PAGE_NO_API_EXTENSION_PROPERTIES = "pageNoApiExtension.properties"; public static final String PAGE_PROPERTIES = "page.properties"; private CustomPageService customPageService; @Mock CompoundPermissionsMapping compoundPermissionsMapping; @Mock ResourcesPermissionsMapping resourcesPermissionsMapping; @Rule public ExpectedException expectedEx = ExpectedException.none(); @Mock APISession apiSession; @Mock PageResourceProvider pageResourceProvider; @Mock PageAPI pageAPI; @Mock private HttpServletRequest request; @Mock private PageContext pageContext; @Mock private Page mockedPage; @Mock private ConsoleProperties consoleProperties; @Mock private WebBonitaConstantsUtils webBonitaConstantUtils; @Before public void before() throws IOException { customPageService = spy(new CustomPageService()); CustomPageService.clearCachedClassloaders(); when(apiSession.getTenantId()).thenReturn(1L); doReturn(consoleProperties).when(customPageService).getConsoleProperties(apiSession); doReturn(webBonitaConstantUtils).when(customPageService).getWebBonitaConstantsUtils(apiSession); } @Test public void should_load_page_return_page_impl() throws Exception { // Given final File pageFile = new File(getClass().getResource("/Index.groovy").toURI()); final File pageDir = pageFile.getParentFile(); assertThat(pageFile).as("no file " + pageFile.getAbsolutePath()).exists().canRead(); when(pageResourceProvider.getPageDirectory()).thenReturn(pageDir); doReturn(pageFile).when(customPageService).getGroovyPageFile(any(File.class)); final File pageLibDir = new File(pageFile.getParentFile(), File.separator + "lib"); doReturn(pageLibDir).when(customPageService).getCustomPageLibDirectory(any(File.class)); doReturn(Thread.currentThread().getContextClassLoader()).when(customPageService).getParentClassloader( anyString(), any(CustomPageDependenciesResolver.class), any(BDMClientDependenciesResolver.class)); when(mockedPage.getLastModificationDate()).thenReturn(new Date(0L)); doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); when(pageAPI.getPageByName("")).thenReturn(mockedPage); // When final GroovyClassLoader classloader = customPageService.getPageClassloader(apiSession, pageResourceProvider); final Class<PageController> pageClass = customPageService.registerPage(classloader, pageResourceProvider); final PageController pageController = customPageService.loadPage(pageClass); // Then assertNotNull(pageController); } @Test public void should_load_rest_api_page_return_api_impl() throws Exception { // Given when(apiSession.getTenantId()).thenReturn(0L); final File pageFile = new File(getClass().getResource("/IndexRestApi.groovy").toURI()); final File pageDir = pageFile.getParentFile(); assertThat(pageFile).as("no file " + pageFile.getAbsolutePath()).exists().canRead(); when(pageResourceProvider.getPageDirectory()).thenReturn(pageDir); doReturn(pageFile).when(customPageService).getPageFile(any(File.class), anyString()); final File pageLibDir = new File(pageFile.getParentFile(), File.separator + "lib"); doReturn(pageLibDir).when(customPageService).getCustomPageLibDirectory(any(File.class)); doReturn(Thread.currentThread().getContextClassLoader()).when(customPageService).getParentClassloader( anyString(), any(CustomPageDependenciesResolver.class), any(BDMClientDependenciesResolver.class)); final Page mockedPage = mock(Page.class); when(mockedPage.getLastModificationDate()).thenReturn(new Date(0L)); doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); when(pageAPI.getPageByName("")).thenReturn(mockedPage); // When final GroovyClassLoader classloader = customPageService.getPageClassloader(apiSession, pageResourceProvider); final Class<RestApiController> restApiControllerClass = customPageService.registerRestApiPage(classloader, pageResourceProvider, CustomPageService.PAGE_CONTROLLER_FILENAME); final RestApiController restApiController = customPageService.loadRestApiPage(restApiControllerClass); // Then assertNotNull(restApiController); } @Test public void should_retrievePageZipContent_save_it_in_bonita_home() throws Exception { // Given final Page mockedPage = mock(Page.class); when(mockedPage.getId()).thenReturn(1l); when(mockedPage.getName()).thenReturn("page1"); when(apiSession.getTenantId()).thenReturn(0L); doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final byte[] zipFile = IOUtils.toByteArray(getClass().getResourceAsStream("page.zip")); when(pageAPI.getPageContent(1l)).thenReturn(zipFile); when(pageResourceProvider.getPage(pageAPI)).thenReturn(mockedPage); when(pageResourceProvider.getTempPageFile()) .thenReturn(new File("target/bonita/home/client/tenant/1/temp")); when(pageResourceProvider.getPageDirectory()) .thenReturn(new File("target/bonita/home/client/tenants/1/pages/page1")); // When customPageService.retrievePageZipContent(apiSession, pageResourceProvider); // Validate assertNotNull(pageResourceProvider.getPageDirectory().listFiles()); } @Test public void should_get_Custom_Page_permissions_from_PageProperties() throws Exception { // Given final String fileContent = "name=customPage1\n" + "resources=[GET|identity/user, PUT|identity/user]"; final File pagePropertiesFile = File.createTempFile(PAGE_PROPERTIES, ".tmp"); IOUtils.write(fileContent.getBytes(), new FileOutputStream(pagePropertiesFile)); doReturn(new HashSet<>(Arrays.asList("Organization Visualization"))).when(resourcesPermissionsMapping) .getPropertyAsSet("GET|identity/user"); doReturn(new HashSet<>(Arrays.asList("Organization Visualization", "Organization Managment"))) .when(resourcesPermissionsMapping).getPropertyAsSet("PUT|identity/user"); // When final Set<String> customPagePermissions = customPageService.getCustomPagePermissions(pagePropertiesFile, resourcesPermissionsMapping, true); // Then assertThat(customPagePermissions).contains("Organization Visualization", "Organization Managment"); } @Test public void should_not_return_it_when_unkown_resource_is_declared_in_PageProperties_and_flag_false() throws Exception { // Given final String fileContent = "name=customPage1\n" + "resources=[GET|unkown/resource, PUT|identity/user]"; final File pagePropertiesFile = File.createTempFile(PAGE_PROPERTIES, ".tmp"); IOUtils.write(fileContent.getBytes(), new FileOutputStream(pagePropertiesFile)); doReturn(Collections.emptySet()).when(resourcesPermissionsMapping).getPropertyAsSet("GET|unkown/resource"); doReturn(new HashSet<>(Arrays.asList("Organization Visualization", "Organization Managment"))) .when(resourcesPermissionsMapping).getPropertyAsSet("PUT|identity/user"); // When final Set<String> customPagePermissions = customPageService.getCustomPagePermissions(pagePropertiesFile, resourcesPermissionsMapping, false); // Then assertThat(customPagePermissions).containsOnly("Organization Visualization", "Organization Managment"); } @Test public void should_return_it_when_unkown_resource_is_declared_in_PageProperties_and_flag_true() throws Exception { // Given final String fileContent = "name=customPage1\n" + "resources=[GET|unkown/resource, GET|identity/user, PUT|identity/user]"; final File pagePropertiesFile = File.createTempFile(PAGE_PROPERTIES, ".tmp"); IOUtils.write(fileContent.getBytes(), new FileOutputStream(pagePropertiesFile)); doReturn(new HashSet<>(Arrays.asList("Organization Visualization"))).when(resourcesPermissionsMapping) .getPropertyAsSet("GET|identity/user"); doReturn(new HashSet<>(Arrays.asList("Organization Visualization", "Organization Managment"))) .when(resourcesPermissionsMapping).getPropertyAsSet("PUT|identity/user"); // When final Set<String> customPagePermissions = customPageService.getCustomPagePermissions(pagePropertiesFile, resourcesPermissionsMapping, true); // Then assertThat(customPagePermissions).contains("<GET|unkown/resource>", "Organization Visualization", "Organization Managment"); } @Test public void should_get_Custom_Page_permissions_to_CompoundPermissions_with_empty_list() throws Exception { // Given final String fileContent = "name=customPage1\n" + "resources=[]"; final File pagePropertiesFile = File.createTempFile(PAGE_PROPERTIES, ".tmp"); IOUtils.write(fileContent.getBytes(), new FileOutputStream(pagePropertiesFile)); doReturn(Collections.emptySet()).when(resourcesPermissionsMapping).getPropertyAsSet("GET|unkown/resource"); // When final Set<String> customPagePermissions = customPageService.getCustomPagePermissions(pagePropertiesFile, resourcesPermissionsMapping, false); // Then assertTrue(customPagePermissions.equals(new HashSet<String>())); } @Test public void should_add_Custom_Page_permissions_to_CompoundPermissions() throws Exception { // Given final HashSet<String> customPagePermissions = new HashSet<>( Arrays.asList("Organization Visualization", "Organization Managment")); // When customPageService.addPermissionsToCompoundPermissions("customPage1", customPagePermissions, compoundPermissionsMapping, resourcesPermissionsMapping); // Then verify(compoundPermissionsMapping).setPropertyAsSet("customPage1", customPagePermissions); } @Test public void should_GetPageProperties_does_not_throws_already_exist_exception_if_checkIfItAlreadyExists_is_false() throws Exception { //given final boolean checkIfItAlreadyExists = false; doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); doReturn(new Properties()).when(pageAPI).getPageProperties(any(byte[].class), eq(checkIfItAlreadyExists)); //when final byte[] zipContent = new byte[0]; customPageService.getPageProperties(apiSession, zipContent, checkIfItAlreadyExists, 123123L); //then verify(pageAPI, times(0)).getPageByNameAndProcessDefinitionId(anyString(), anyLong()); } @Test public void should_GetPageProperties_throws_already_exist_exception_Page_when_same_page_at_tenant_level() throws Exception { //given final boolean checkIfItAlreadyExists = true; doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final Properties pageProperties = new Properties(); final String pageName = "test"; pageProperties.put(CustomPageService.NAME_PROPERTY, pageName); doReturn(pageProperties).when(pageAPI).getPageProperties(any(byte[].class), eq(false)); final long processDefinitionId = 123123L; doThrow(new PageNotFoundException("page not found")).when(pageAPI) .getPageByNameAndProcessDefinitionId(pageName, processDefinitionId); //when final byte[] zipContent = new byte[0]; try { customPageService.getPageProperties(apiSession, zipContent, checkIfItAlreadyExists, processDefinitionId); fail("AlreadyExistsException has not been thrown"); } catch (final AlreadyExistsException e) { } //then verify(pageAPI, times(1)).getPageByName(pageName); } @Test public void should_GetPageProperties_throws_already_exist_exception_Page_when_same_page_at_process_level() throws Exception { //given final boolean checkIfItAlreadyExists = true; doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final Properties pageProperties = new Properties(); final String pageName = "test"; pageProperties.put(CustomPageService.NAME_PROPERTY, pageName); doReturn(pageProperties).when(pageAPI).getPageProperties(any(byte[].class), eq(false)); final long processDefinitionId = 123123L; //when final byte[] zipContent = new byte[0]; try { customPageService.getPageProperties(apiSession, zipContent, checkIfItAlreadyExists, processDefinitionId); fail("AlreadyExistsException has not been thrown"); } catch (final AlreadyExistsException e) { } //then verify(pageAPI, times(1)).getPageByNameAndProcessDefinitionId(pageName, processDefinitionId); } @Test public void getPageProperties_should_Retrieve_Properties_Without_Errors() throws Exception { //given final boolean checkIfItAlreadyExists = true; doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final Properties pageProperties = new Properties(); final String pageName = "test"; pageProperties.put(CustomPageService.NAME_PROPERTY, pageName); doReturn(pageProperties).when(pageAPI).getPageProperties(any(byte[].class), eq(false)); final long processDefinitionId = 123123L; doThrow(new PageNotFoundException("page not found")).when(pageAPI).getPageByName(pageName); doThrow(new PageNotFoundException("page not found")).when(pageAPI) .getPageByNameAndProcessDefinitionId(pageName, processDefinitionId); //when final byte[] zipContent = new byte[0]; final Properties props = customPageService.getPageProperties(apiSession, zipContent, checkIfItAlreadyExists, processDefinitionId); //then verify(pageAPI, times(1)).getPageByNameAndProcessDefinitionId(pageName, processDefinitionId); verify(pageAPI, times(1)).getPageByName(pageName); assertThat(props).isSameAs(pageProperties); } @Test public void should_retrieve_class_file() throws Exception { // Given final Page mockedPage = mock(Page.class); when(mockedPage.getId()).thenReturn(1l); when(mockedPage.getName()).thenReturn("page1"); when(apiSession.getTenantId()).thenReturn(0L); doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final byte[] zipFile = IOUtils.toByteArray(getClass().getResourceAsStream("page.zip")); when(pageAPI.getPageContent(1l)).thenReturn(zipFile); when(pageResourceProvider.getPage(pageAPI)).thenReturn(mockedPage); when(pageResourceProvider.getTempPageFile()) .thenReturn(new File("target/bonita/home/client/tenant/1/temp")); when(pageResourceProvider.getPageDirectory()) .thenReturn(new File("target/bonita/home/client/tenants/1/pages/page1")); // When customPageService.retrievePageZipContent(apiSession, pageResourceProvider); final File file = customPageService.getPageFile(pageResourceProvider.getPageDirectory(), "readme.txt"); // Validate assertThat(file).as("should return file").exists(); } @Test public void should_register_restApiPage() throws Exception { // Given final Page mockedPage = mock(Page.class); when(mockedPage.getId()).thenReturn(1l); when(mockedPage.getName()).thenReturn("page2"); when(apiSession.getTenantId()).thenReturn(0L); doReturn(pageAPI).when(customPageService).getPageAPI(apiSession); final byte[] zipFile = IOUtils.toByteArray(getClass().getResourceAsStream("pageApiExtension.zip")); when(pageAPI.getPageContent(1l)).thenReturn(zipFile); when(pageResourceProvider.getPage(pageAPI)).thenReturn(mockedPage); when(pageResourceProvider.getTempPageFile()) .thenReturn(new File("target/bonita/home/client/tenant/1/temp")); when(pageResourceProvider.getPageDirectory()) .thenReturn(new File("target/bonita/home/client/tenants/1/pages/page2")); when(consoleProperties.isPageInDebugMode()).thenReturn(true); final GroovyClassLoader pageClassloader = customPageService.getPageClassloader(apiSession, pageResourceProvider); // When customPageService.retrievePageZipContent(apiSession, pageResourceProvider); final Class<RestApiController> restApiControllerClass = customPageService .registerRestApiPage(pageClassloader, pageResourceProvider, "RestResource.groovy"); // then final RestApiController restApiController = restApiControllerClass.newInstance(); final RestApiResponse restApiResponse = restApiController.doHandle(request, pageResourceProvider, pageContext, new RestApiResponseBuilder(), new RestApiUtilImpl()); RestApiResponseAssert.assertThat(restApiResponse).as("should return result") .hasResponse("RestResource.groovy!").hasNoAdditionalCookies().hasHttpStatus(200); } @Test public void should_add_api_extension_permission() throws Exception { //given doReturn("custompage_test").when(mockedPage).getName(); doReturn(null).when(mockedPage).getProcessDefinitionId(); final File propertyFile = new File(getClass().getResource(PAGE_PROPERTIES).toURI()); doReturn(pageResourceProvider).when(customPageService).getPageResourceProvider(eq(mockedPage), anyLong()); doReturn(propertyFile).when(pageResourceProvider).getResourceAsFile(anyString()); doNothing().when(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); //when customPageService.addRestApiExtensionPermissions(resourcesPermissionsMapping, pageResourceProvider, apiSession); //then verify(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); verify(resourcesPermissionsMapping).setProperty("GET|extension/restApiGet", "[permission1]"); verify(resourcesPermissionsMapping).setProperty("POST|extension/restApiPost", "[permission2,permission3]"); } @Test public void should_add_no_api_extension_permission() throws Exception { //given doReturn("custompage_test").when(mockedPage).getName(); doReturn(null).when(mockedPage).getProcessDefinitionId(); final File propertyFile = new File(getClass().getResource(PAGE_NO_API_EXTENSION_PROPERTIES).toURI()); doReturn(pageResourceProvider).when(customPageService).getPageResourceProvider(eq(mockedPage), anyLong()); doReturn(propertyFile).when(pageResourceProvider).getResourceAsFile(anyString()); doNothing().when(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); //when customPageService.addRestApiExtensionPermissions(resourcesPermissionsMapping, pageResourceProvider, apiSession); //then verify(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); verifyZeroInteractions(resourcesPermissionsMapping); } @Test public void should_remove_api_extension_permissions() throws Exception { //given final File propertyFile = new File(getClass().getResource(PAGE_PROPERTIES).toURI()); doReturn(pageResourceProvider).when(customPageService).getPageResourceProvider(eq(mockedPage), anyLong()); doReturn(propertyFile).when(pageResourceProvider).getResourceAsFile(anyString()); doNothing().when(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); //when customPageService.removeRestApiExtensionPermissions(resourcesPermissionsMapping, pageResourceProvider, apiSession); //then verify(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); verify(resourcesPermissionsMapping).removeProperty("GET|extension/restApiGet"); verify(resourcesPermissionsMapping).removeProperty("POST|extension/restApiPost"); } @Test public void should_remove_no_permissions() throws Exception { //given final File propertyFile = new File(getClass().getResource(PAGE_NO_API_EXTENSION_PROPERTIES).toURI()); doReturn(pageResourceProvider).when(customPageService).getPageResourceProvider(eq(mockedPage), anyLong()); doReturn(propertyFile).when(pageResourceProvider).getResourceAsFile(anyString()); doNothing().when(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); //when customPageService.removeRestApiExtensionPermissions(resourcesPermissionsMapping, pageResourceProvider, apiSession); //then verify(customPageService).ensurePageFolderIsUpToDate(apiSession, pageResourceProvider); verifyZeroInteractions(resourcesPermissionsMapping); } @Test public void should_add_page_root_folder_in_classpath() throws Exception { final File pageDir = new File(getClass().getResource("/ARootPageFolder").getFile()); final GroovyClassLoader classloader = customPageService.buildPageClassloader(apiSession, "pageName", pageDir); assertThat(classloader.loadClass("AbstractIndex")).isNotNull(); assertThat(classloader.loadClass("Index")).isNotNull(); assertThat(classloader.loadClass("org.company.test.Util")).isNotNull(); assertThat(classloader.getResource("org/company/test/config.properties")).isNotNull(); } }