diff --git a/.github/workflows/ga-publication.yml b/.github/workflows/ga-publication.yml index fb7e7f5a4d..4f266b64bb 100755 --- a/.github/workflows/ga-publication.yml +++ b/.github/workflows/ga-publication.yml @@ -46,7 +46,7 @@ jobs: - name: "Configure GA Repository" uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 server-id: maven-central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e782e3fc85..7642c0021a 100755 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -72,10 +72,10 @@ jobs: --token "$ENTANDO_BOT_TOKEN" \ ; #~ JDK - - name: "Set up JDK 11" + - name: "Set up JDK 17" uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 #~ MAVEN CACHE - name: "Cache Maven packages" uses: actions/cache@v2 @@ -119,10 +119,10 @@ jobs: # ${{ secrets.ENTANDO_OPT_PPL_INSTALL_CMD }} # ~/ppl-run checkout-branch pr --lcd "$LOCAL_CLONE_DIR" # #~ JDK -# - name: "Set up JDK 11" +# - name: "Set up JDK 17" # uses: actions/setup-java@v1 # with: -# java-version: 11 +# java-version: 17 # #~ MAVEN CACHE # - name: "Cache Maven packages" # id: maven-cache diff --git a/.github/workflows/publication.yml b/.github/workflows/publication.yml index bcbc107a53..80b9409e98 100755 --- a/.github/workflows/publication.yml +++ b/.github/workflows/publication.yml @@ -10,15 +10,15 @@ env: ENTANDO_BOT_TOKEN: ${{ secrets.ENTANDO_BOT_TOKEN }} PR_CHECKER_PATH: ".github/pr-title-checker-config.json" - JDK_VERSION: 11 + JDK_VERSION: 17 BUILD_COMMANDS: mvn clean install; - DOCKER_EAP_IMAGE_BASE_NAME: entando/entando-de-app-eap +# DOCKER_EAP_IMAGE_BASE_NAME: entando/entando-de-app-eap DOCKER_TOMCAT_IMAGE_BASE_NAME: entando/entando-de-app-tomcat - DOCKER_WILDFLY_IMAGE_BASE_NAME: entando/entando-de-app-wildfly +# DOCKER_WILDFLY_IMAGE_BASE_NAME: entando/entando-de-app-wildfly DOCKER_EAP-WILDFLY_IMAGE_ARCHITECTURE: linux/amd64 DOCKER_TOMCAT_IMAGE_ARCHITECTURE: linux/amd64,linux/arm64 DOCKER_IMAGE_CONTEXT: . - DOCKER_EAP_IMAGE_FILE: Dockerfile.eap +# DOCKER_EAP_IMAGE_FILE: Dockerfile.eap DOCKER_TOMCAT_IMAGE_FILE: Dockerfile.tomcat DOCKER_WILDFLY_IMAGE_FILE: Dockerfile.wildfly DOCKER_IMAGE_PUSH: true @@ -58,22 +58,22 @@ jobs: - name: Build with Maven run: ${{ env.BUILD_COMMANDS }} - - name: Docker meta-eap - id: meta-eap - uses: docker/metadata-action@v4 - with: - images: | - ${{ env.DOCKER_EAP_IMAGE_BASE_NAME }} - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr,value={{base_ref}} - type=ref,event=tag - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - type=raw,event=pr,value={{base_ref}} +# - name: Docker meta-eap +# id: meta-eap +# uses: docker/metadata-action@v4 +# with: +# images: | +# ${{ env.DOCKER_EAP_IMAGE_BASE_NAME }} +# tags: | +# type=schedule +# type=ref,event=branch +# type=ref,event=pr,value={{base_ref}} +# type=ref,event=tag +# type=semver,pattern={{version}} +# type=semver,pattern={{major}}.{{minor}} +# type=semver,pattern={{major}} +# type=sha +# type=raw,event=pr,value={{base_ref}} - name: Docker meta-tomcat id: meta-tomcat @@ -92,22 +92,22 @@ jobs: type=sha type=raw,event=pr,value={{base_ref}} - - name: Docker meta-wildfly - id: meta-wildfly - uses: docker/metadata-action@v4 - with: - images: | - ${{ env.DOCKER_WILDFLY_IMAGE_BASE_NAME }} - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr,value={{base_ref}} - type=ref,event=tag - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - type=raw,event=pr,value={{base_ref}} +# - name: Docker meta-wildfly +# id: meta-wildfly +# uses: docker/metadata-action@v4 +# with: +# images: | +# ${{ env.DOCKER_WILDFLY_IMAGE_BASE_NAME }} +# tags: | +# type=schedule +# type=ref,event=branch +# type=ref,event=pr,value={{base_ref}} +# type=ref,event=tag +# type=semver,pattern={{version}} +# type=semver,pattern={{major}}.{{minor}} +# type=semver,pattern={{major}} +# type=sha +# type=raw,event=pr,value={{base_ref}} - name: Set up QEMU uses: docker/setup-qemu-action@v2 @@ -130,15 +130,15 @@ jobs: username: ${{ secrets.ENTANDO_RHT_DOCKER_USERNAME }} password: ${{ secrets.ENTANDO_RHT_DOCKER_PASSWORD }} - - name: Build and push eap Docker image - uses: docker/build-push-action@v4 - with: - context: ${{ env.DOCKER_IMAGE_CONTEXT }} - file: ${{ env.DOCKER_EAP_IMAGE_FILE }} - push: ${{ env.DOCKER_IMAGE_PUSH }} - tags: ${{ steps.meta-eap.outputs.tags }} - labels: ${{ steps.meta-eap.outputs.labels }} - platforms: ${{ env.DOCKER_EAP-WILDFLY_IMAGE_ARCHITECTURE }} +# - name: Build and push eap Docker image +# uses: docker/build-push-action@v4 +# with: +# context: ${{ env.DOCKER_IMAGE_CONTEXT }} +# file: ${{ env.DOCKER_EAP_IMAGE_FILE }} +# push: ${{ env.DOCKER_IMAGE_PUSH }} +# tags: ${{ steps.meta-eap.outputs.tags }} +# labels: ${{ steps.meta-eap.outputs.labels }} +# platforms: ${{ env.DOCKER_EAP-WILDFLY_IMAGE_ARCHITECTURE }} - name: Build tomcat Docker image for amd64 uses: docker/build-push-action@v4 @@ -170,12 +170,12 @@ jobs: labels: ${{ steps.meta-tomcat.outputs.labels }} platforms: ${{ env.DOCKER_TOMCAT_IMAGE_ARCHITECTURE }} - - name: Build and push wildfly Docker image - uses: docker/build-push-action@v4 - with: - context: ${{ env.DOCKER_IMAGE_CONTEXT }} - file: ${{ env.DOCKER_WILDFLY_IMAGE_FILE }} - push: ${{ env.DOCKER_IMAGE_PUSH }} - tags: ${{ steps.meta-wildfly.outputs.tags }} - labels: ${{ steps.meta-wildfly.outputs.labels }} - platforms: ${{ env.DOCKER_EAP-WILDFLY_IMAGE_ARCHITECTURE }} \ No newline at end of file +# - name: Build and push wildfly Docker image +# uses: docker/build-push-action@v4 +# with: +# context: ${{ env.DOCKER_IMAGE_CONTEXT }} +# file: ${{ env.DOCKER_WILDFLY_IMAGE_FILE }} +# push: ${{ env.DOCKER_IMAGE_PUSH }} +# tags: ${{ steps.meta-wildfly.outputs.tags }} +# labels: ${{ steps.meta-wildfly.outputs.labels }} +# platforms: ${{ env.DOCKER_EAP-WILDFLY_IMAGE_ARCHITECTURE }} \ No newline at end of file diff --git a/Dockerfile.eap b/Dockerfile.eap index 7faa00a595..ff8b368929 100644 --- a/Dockerfile.eap +++ b/Dockerfile.eap @@ -1,4 +1,4 @@ -FROM registry.hub.docker.com/entando/entando-eap73-clustered-base:7.2.0 +FROM registry.hub.docker.com/entando/entando-eap73-clustered-base:7.4.0-ENG-5316-PR-28 ARG VERSION ### Required OpenShift Labels @@ -6,7 +6,7 @@ LABEL name="Entando App" \ maintainer="dev@entando.com" \ vendor="Entando Inc." \ version="${VERSION}" \ - release="7.0.0" \ + release="7.4.0" \ summary="Entando Application" \ description="This Entando app engine application provides APIs and composition for Entando applications" diff --git a/Dockerfile.tomcat b/Dockerfile.tomcat index 32ef7b0ede..322a956e78 100644 --- a/Dockerfile.tomcat +++ b/Dockerfile.tomcat @@ -1,4 +1,4 @@ -FROM registry.hub.docker.com/entando/entando-tomcat-base:7.2.0-IT-410-PR-26 +FROM registry.hub.docker.com/entando/entando-tomcat-base:7.4.0-ENG-5316-PR-28 ARG VERSION ### Required OpenShift Labels @@ -6,7 +6,7 @@ LABEL name="Entando App" \ maintainer="dev@entando.com" \ vendor="Entando Inc." \ version="${VERSION}" \ - release="7.0.0" \ + release="7.4.0" \ summary="Entando Application" \ description="This Entando app engine application provides APIs and composition for Entando applications" diff --git a/Dockerfile.wildfly b/Dockerfile.wildfly index ea66661a3b..fe69d61ec2 100644 --- a/Dockerfile.wildfly +++ b/Dockerfile.wildfly @@ -1,4 +1,4 @@ -FROM registry.hub.docker.com/entando/entando-wildfly17-base:7.2.0 +FROM registry.hub.docker.com/entando/entando-wildfly17-base:7.4.0-ENG-5316-PR-28 ARG VERSION @@ -7,7 +7,7 @@ LABEL name="Entando App" \ maintainer="dev@entando.com" \ vendor="Entando Inc." \ version="${VERSION}" \ - release="7.0.0" \ + release="7.4.0" \ summary="Entando Application" \ description="This Entando app engine application provides APIs and composition for Entando applications" diff --git a/admin-console/pom.xml b/admin-console/pom.xml index 8f81c155b5..16bc12f476 100644 --- a/admin-console/pom.xml +++ b/admin-console/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando entando-admin-console diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/system/BaseAction.java b/admin-console/src/main/java/com/agiletec/apsadmin/system/BaseAction.java index 8bbabcd0f7..786ed9c135 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/system/BaseAction.java +++ b/admin-console/src/main/java/com/agiletec/apsadmin/system/BaseAction.java @@ -219,7 +219,7 @@ protected ITreeNodeManager getTreeNodeManager(ITreeNode treeNode) { } public TenantConfig getCurrentTenantConfig() { - return ApsTenantApplicationUtils.getTenant().flatMap(getTenantManager()::getConfig).orElse(null); + return ApsTenantApplicationUtils.getTenant().flatMap(getTenantManager()::getConfigOfReadyTenant).orElse(null); } @Override diff --git a/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/inc/pagerInfo.jsp b/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/inc/pagerInfo.jsp index 6318ea6df2..53653dccb8 100644 --- a/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/inc/pagerInfo.jsp +++ b/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/inc/pagerInfo.jsp @@ -1,4 +1,4 @@ <%@ taglib prefix="s" uri="/struts-tags" %> <%@ taglib prefix="wp" uri="/aps-core" %> | - - \ No newline at end of file + - \ No newline at end of file diff --git a/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/tiles-inserts/header.jsp b/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/tiles-inserts/header.jsp index d20c0c351a..c16d5e03b6 100644 --- a/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/tiles-inserts/header.jsp +++ b/admin-console/src/main/webapp/WEB-INF/apsadmin/jsp/common/tiles-inserts/header.jsp @@ -17,6 +17,17 @@ diff --git a/admin-console/src/test/java/com/agiletec/apsadmin/system/BaseActionTest.java b/admin-console/src/test/java/com/agiletec/apsadmin/system/BaseActionTest.java index c46451df27..6d8d4447a5 100644 --- a/admin-console/src/test/java/com/agiletec/apsadmin/system/BaseActionTest.java +++ b/admin-console/src/test/java/com/agiletec/apsadmin/system/BaseActionTest.java @@ -47,19 +47,19 @@ void shouldCurrentTenantWorkFine() { apsTenantApplicationUtils.reset(); Mockito.reset(tenantManager); apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.of("tenantx")); - Mockito.when(tenantManager.getConfig("tenantx")).thenReturn(Optional.empty()); + Mockito.when(tenantManager.getConfigOfReadyTenant("tenantx")).thenReturn(Optional.empty()); config = this.baseAction.getCurrentTenantConfig(); Assertions.assertNull(config); - Mockito.verify(tenantManager, Mockito.times(1)).getConfig("tenantx"); + Mockito.verify(tenantManager, Mockito.times(1)).getConfigOfReadyTenant("tenantx"); apsTenantApplicationUtils.reset(); Mockito.reset(tenantManager); apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.of("tenanty")); TenantConfig tc = new TenantConfig(Map.of("tenantCode","tenanty")); - Mockito.when(tenantManager.getConfig("tenanty")).thenReturn(Optional.of(tc)); + Mockito.when(tenantManager.getConfigOfReadyTenant("tenanty")).thenReturn(Optional.of(tc)); config = this.baseAction.getCurrentTenantConfig(); Assertions.assertNotNull(config); - Mockito.verify(tenantManager, Mockito.times(1)).getConfig("tenanty"); + Mockito.verify(tenantManager, Mockito.times(1)).getConfigOfReadyTenant("tenanty"); } } diff --git a/cds-plugin/pom.xml b/cds-plugin/pom.xml index df0a26dd15..1ea086d684 100644 --- a/cds-plugin/pom.xml +++ b/cds-plugin/pom.xml @@ -5,7 +5,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpcds org.entando.entando.plugins diff --git a/cds-plugin/src/main/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManager.java b/cds-plugin/src/main/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManager.java index dd255c3ade..9cb0c81c2b 100644 --- a/cds-plugin/src/main/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManager.java +++ b/cds-plugin/src/main/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManager.java @@ -33,6 +33,7 @@ import org.entando.entando.aps.system.services.tenants.TenantConfig; import org.entando.entando.aps.util.UrlUtils.EntUrlBuilder; import org.entando.entando.ent.exception.EntException; +import org.entando.entando.ent.exception.EntResourceNotFoundException; import org.entando.entando.ent.exception.EntRuntimeException; import org.entando.entando.plugins.jpcds.aps.system.storage.CdsUrlUtils.EntSubPath; import org.springframework.beans.factory.annotation.Autowired; @@ -159,9 +160,9 @@ public InputStream getStream(String subPath, boolean isProtectedResource) throws log.info("File Not found - uri {}", url); return null; } - throw new EntException(ERROR_EXTRACTING_FILE, e); + throw new EntResourceNotFoundException(ERROR_EXTRACTING_FILE, e); } catch (Exception e) { - throw new EntException(ERROR_EXTRACTING_FILE, e); + throw new EntResourceNotFoundException(ERROR_EXTRACTING_FILE, e); } } diff --git a/cms-plugin/pom.xml b/cms-plugin/pom.xml index 51d5e924bd..ed0f1b1684 100644 --- a/cms-plugin/pom.xml +++ b/cms-plugin/pom.xml @@ -5,7 +5,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando.plugins entando-plugin-jacms diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentManager.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentManager.java index b85fd127c4..1ec8ee3738 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentManager.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentManager.java @@ -14,7 +14,6 @@ package com.agiletec.plugins.jacms.aps.system.services.content; import com.agiletec.aps.system.ApsSystemUtils; -import com.agiletec.aps.system.SystemConstants; import com.agiletec.aps.system.common.entity.ApsEntityManager; import com.agiletec.aps.system.common.entity.IEntityDAO; import com.agiletec.aps.system.common.entity.IEntitySearcherDAO; @@ -53,8 +52,9 @@ * Contents manager. This implements all the methods needed to create and manage * the contents. */ -public class ContentManager extends ApsEntityManager - implements IContentManager, GroupUtilizer, PageUtilizer, ContentUtilizer, ResourceUtilizer, CategoryUtilizer { +public class ContentManager extends ApsEntityManager + implements IContentManager, GroupUtilizer, PageUtilizer, + ContentUtilizer, ResourceUtilizer, CategoryUtilizer { private static final EntLogger logger = EntLogFactory.getSanitizedLogger(ContentManager.class); @@ -615,7 +615,7 @@ public List getPageUtilizers(String pageCode) throws EntException { } @Override - public List getContentUtilizers(String contentId) throws EntException { + public List getContentUtilizers(String contentId) throws EntException { try { return this.getContentDAO().getContentUtilizers(contentId); } catch (Throwable t) { @@ -633,7 +633,7 @@ public List getGroupUtilizers(String groupName) throws EntException { } @Override - public List getResourceUtilizers(String resourceId) throws EntException { + public List getResourceUtilizers(String resourceId) throws EntException { try { return this.getContentDAO().getResourceUtilizers(resourceId); } catch (Throwable t) { @@ -642,7 +642,7 @@ public List getResourceUtilizers(String resourceId) throws EntException { } @Override - public List getCategoryUtilizers(String resourceId) throws EntException { + public List getCategoryUtilizers(String resourceId) throws EntException { try { return this.getContentDAO().getCategoryUtilizers(resourceId); } catch (Throwable t) { @@ -661,7 +661,7 @@ public void reloadCategoryReferences(String categoryCode) { @SuppressWarnings("rawtypes") @Override - public List getCategoryUtilizersForReloadReferences(String categoryCode) { + public List getCategoryUtilizersForReloadReferences(String categoryCode) { List contentIdToReload = new ArrayList<>(); try { Set contents = this.getContentUpdaterService().getContentsId(categoryCode); diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentUtilizer.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentUtilizer.java index 79528b0801..6b6faf7810 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentUtilizer.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/ContentUtilizer.java @@ -20,8 +20,9 @@ /** * Basic interface for the services whose handled elements may have references to contents. * @author E.Santoboni + * @param */ -public interface ContentUtilizer { +public interface ContentUtilizer { /** * Return the ID of the utilizer service. @@ -35,6 +36,6 @@ public interface ContentUtilizer { * @return the list of the objects which reference the content. * @throws EntException in case of error. */ - public List getContentUtilizers(String contentId) throws EntException; + public List getContentUtilizers(String contentId) throws EntException; } diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/model/ContentDto.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/model/ContentDto.java index 67413eca75..9947eb0e2e 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/model/ContentDto.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/model/ContentDto.java @@ -294,6 +294,7 @@ private void fillAbstractResourceAttribute(AttributeInterface attribute, EntityA if (AbstractResourceAttribute.class.isAssignableFrom(attribute.getClass())) { AbstractResourceAttribute resourceAttribute = (AbstractResourceAttribute) attribute; for (Entry resourceEntry : attributeDto.getValues().entrySet()) { + @SuppressWarnings("unchecked") Map resourceMap = (Map) resourceEntry.getValue(); this.setResourceAttribute(resourceAttribute, resourceMap, resourceEntry.getKey()); } @@ -312,6 +313,7 @@ private void setResourceAttribute(AbstractResourceAttribute resourceAttribute, M resourceInterface.setId(resourceId); resourceInterface.setCorrelationCode(correlationCode); resourceAttribute.setResource(resourceInterface, langCode); + @SuppressWarnings("unchecked") Map values = (Map) resource.get("metadata"); if (values != null) { Map metadata = values.entrySet().stream() diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBean.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBean.java index fbc772a0fb..065be8a49b 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBean.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBean.java @@ -243,7 +243,7 @@ public EntitySearchFilter getEntityFilter() throws EntException { AttributeInterface attribute = this.getAttribute(); if (attribute instanceof ITextAttribute) { String text = this.getFormFieldValues().get(this.getFormFieldNames()[0]); - filter = new EntitySearchFilter(attribute.getName(), true, text, true); + filter = new EntitySearchFilter(attribute.getName(), true, text, true); if (attribute.isMultilingual()) { filter.setLangCode(this.getCurrentLang().getCode()); } @@ -252,7 +252,7 @@ public EntitySearchFilter getEntityFilter() throws EntException { String end = this.getFormFieldValues().get(this.getFormFieldNames()[1]); Date startDate = DateConverter.parseDate(start, this.getDateFormat()); Date endDate = DateConverter.parseDate(end, this.getDateFormat()); - filter = new EntitySearchFilter(attribute.getName(), true, startDate, endDate); + filter = new EntitySearchFilter(attribute.getName(), true, startDate, endDate); } else if (attribute instanceof BooleanAttribute) { String value = this.getFormFieldValues().get(this.getFormFieldNames()[0]); String ignore = this.getFormFieldValues().get(this.getFormFieldNames()[1]); @@ -263,7 +263,7 @@ public EntitySearchFilter getEntityFilter() throws EntException { filter = new EntitySearchFilter(attribute.getName(), true); filter.setNullOption(true); } else { - filter = new EntitySearchFilter(attribute.getName(), true, value, false); + filter = new EntitySearchFilter(attribute.getName(), true, value, false); } } else if (attribute instanceof NumberAttribute) { String start = this.getFormFieldValues().get(this.getFormFieldNames()[0]); @@ -278,7 +278,7 @@ public EntitySearchFilter getEntityFilter() throws EntException { Integer endNumberInt = Integer.parseInt(end); endNumber = new BigDecimal(endNumberInt); } catch (Throwable t) {} - filter = new EntitySearchFilter(attribute.getName(), true, startNumber, endNumber); + filter = new EntitySearchFilter(attribute.getName(), true, startNumber, endNumber); } } catch (Throwable t) { _logger.error("Error extracting entity search filters", t); @@ -308,45 +308,31 @@ public SearchEngineFilter extractFilter() { if (!this.isAttributeFilter()) { if (this.getKey().equals(KEY_FULLTEXT) && !StringUtils.isEmpty(value0)) { //String[] fieldsSuffix = {"", "_option"}; - filter = new SearchEngineFilter(this.getCurrentLang().getCode(), value0, this.getOption(value1)); + filter = new SearchEngineFilter<>(this.getCurrentLang().getCode(), value0, this.getOption(value1)); } else if (this.getKey().equals(KEY_CATEGORY) && !StringUtils.isEmpty(value0)) { - filter = new SearchEngineFilter(IIndexerDAO.CONTENT_CATEGORY_FIELD_NAME, value0, SearchEngineFilter.TextSearchOption.EXACT); + filter = new SearchEngineFilter<>(IIndexerDAO.CONTENT_CATEGORY_FIELD_NAME, value0, SearchEngineFilter.TextSearchOption.EXACT); } } else { AttributeInterface attribute = this.getAttribute(); if (attribute instanceof ITextAttribute && !StringUtils.isEmpty(value0)) { - filter = new SearchEngineFilter(this.getIndexFieldName(), value0, SearchEngineFilter.TextSearchOption.EXACT); + filter = new SearchEngineFilter<>(this.getIndexFieldName(), value0, SearchEngineFilter.TextSearchOption.EXACT); //String[] fieldsSuffix = {"_textFieldName"}; } else if (attribute instanceof DateAttribute && (!StringUtils.isEmpty(value0) || !StringUtils.isEmpty(value1))) { - Date big0 = null; - try { - big0 = DateConverter.parseDate(value0, this.getDateFormat()); - } catch (Exception e) {} - Date big1 = null; - try { - big1 = DateConverter.parseDate(value1, this.getDateFormat()); - } catch (Exception e) {} + Date big0 = DateConverter.parseDate(value0, this.getDateFormat()); + Date big1 = DateConverter.parseDate(value1, this.getDateFormat()); //String[] fieldsSuffix = {"_dateStartFieldName", "_dateEndFieldName"}; - filter = new SearchEngineFilter(this.getIndexFieldName(), big0, big1); + filter = new SearchEngineFilter<>(this.getIndexFieldName(), big0, big1); } else if (attribute instanceof BooleanAttribute && (!StringUtils.isEmpty(value0) && !StringUtils.isEmpty(value1))) { - filter = new SearchEngineFilter(this.getIndexFieldName(), value0, SearchEngineFilter.TextSearchOption.EXACT); + filter = new SearchEngineFilter<>(this.getIndexFieldName(), value0, SearchEngineFilter.TextSearchOption.EXACT); //String[] fieldsSuffix = {"_booleanFieldName", "_booleanFieldName_ignore", "_booleanFieldName_control"}; } else if (attribute instanceof NumberAttribute && (!StringUtils.isEmpty(value0) || !StringUtils.isEmpty(value1))) { //String[] fieldsSuffix = {"_numberStartFieldName", "_numberEndFieldName"}; - BigDecimal big0 = null; - try { - big0 = new BigDecimal(value0); - } catch (Exception e) { - } - BigDecimal big1 = null; - try { - big1 = new BigDecimal(value1); - } catch (Exception e) { - } - filter = new SearchEngineFilter(this.getIndexFieldName(), big0, big1); + BigDecimal big0 = new BigDecimal(value0); + BigDecimal big1 = new BigDecimal(value1); + filter = new SearchEngineFilter<>(this.getIndexFieldName(), big0, big1); } } return filter; diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceManager.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceManager.java index da3d4da41f..4e80457f7d 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceManager.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceManager.java @@ -59,8 +59,8 @@ * * @author W.Ambu - E.Santoboni */ -public class ResourceManager extends AbstractService implements IResourceManager, GroupUtilizer, CategoryUtilizer, - RefreshableBeanTenantAware { +public class ResourceManager extends AbstractService + implements IResourceManager, GroupUtilizer, CategoryUtilizer, RefreshableBeanTenantAware { private final EntLogger logger = EntLogFactory.getSanitizedLogger(getClass()); @@ -603,7 +603,7 @@ public List getGroupUtilizers(String groupName) throws EntException { } @Override - public List getCategoryUtilizers(String categoryCode) throws EntException { + public List getCategoryUtilizers(String categoryCode) throws EntException { List resourcesId = null; try { resourcesId = this.getResourceDAO().searchResourcesId(null, null, null, categoryCode, null); @@ -643,7 +643,7 @@ public void reloadCategoryReferences(String categoryCode) throws EntException { } @Override - public List getCategoryUtilizersForReloadReferences(String categoryCode) throws EntException { + public List getCategoryUtilizersForReloadReferences(String categoryCode) throws EntException { List resourcesId = null; try { resourcesId = this.getCategoryUtilizers(categoryCode); diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceUtilizer.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceUtilizer.java index 1c9d97a74d..d606c83a50 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceUtilizer.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/ResourceUtilizer.java @@ -21,8 +21,9 @@ * Interfaccia base per i servizi, i cui elementi gestiti, * possono presentare delle referenziazione con delle risorse. * @author E.Santoboni + * @param */ -public interface ResourceUtilizer { +public interface ResourceUtilizer { /** * Restituisce l'identificativo del servizio utilizzatore. @@ -37,6 +38,6 @@ public interface ResourceUtilizer { * @return La lista degli oggetti referenzianti la risorsa. * @throws EntException in caso di errore. */ - public List getResourceUtilizers(String resourceId) throws EntException; + public List getResourceUtilizers(String resourceId) throws EntException; } diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AbstractMonoInstanceResource.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AbstractMonoInstanceResource.java index 6aa9d8b809..b5b1ffca2d 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AbstractMonoInstanceResource.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AbstractMonoInstanceResource.java @@ -19,6 +19,9 @@ import org.apache.commons.lang.StringUtils; import java.io.InputStream; +import org.entando.entando.ent.exception.EntResourceNotFoundException; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; +import org.entando.entando.ent.exception.EntRuntimeException; import org.entando.entando.ent.util.EntLogging.EntLogFactory; import org.entando.entando.ent.util.EntLogging.EntLogger; @@ -28,6 +31,7 @@ public abstract class AbstractMonoInstanceResource extends AbstractResource { private static final EntLogger logger = EntLogFactory.getSanitizedLogger(AbstractMonoInstanceResource.class); + public static final String ERROR_ON_EXTRACTING_RESOURCE_STREAM = "Error on extracting resource Stream"; private ResourceInstance instance; @@ -46,16 +50,18 @@ public boolean isMultiInstance() { public InputStream getResourceStream(int size, String langCode) { return this.getResourceStream(); } - + @Override public InputStream getResourceStream() { ResourceInstance resourceInstance = instance; String subPath = super.getDiskSubFolder() + resourceInstance.getFileName(); try { return this.getStorageManager().getStream(subPath, this.isProtectedResource()); + } catch (EntResourceNotFoundException e) { + throw new EntResourceNotFoundRuntimeException(ERROR_ON_EXTRACTING_RESOURCE_STREAM, e); } catch (Throwable t) { - logger.error("Error on extracting resource Stream", t); - throw new RuntimeException("Error on extracting resource Stream", t); + logger.error(ERROR_ON_EXTRACTING_RESOURCE_STREAM, t); + throw new EntRuntimeException(ERROR_ON_EXTRACTING_RESOURCE_STREAM, t); } } diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResource.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResource.java index 9d33f00b3c..db308e390a 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResource.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResource.java @@ -34,6 +34,9 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.entando.entando.ent.exception.EntException; +import org.entando.entando.ent.exception.EntResourceNotFoundException; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; +import org.entando.entando.ent.exception.EntRuntimeException; import org.entando.entando.ent.util.EntLogging.EntLogFactory; import org.entando.entando.ent.util.EntLogging.EntLogger; import org.im4java.core.ConvertCmd; @@ -42,6 +45,7 @@ public class ImageResource extends AbstractMultiInstanceResource { private static final String FAILED_TO_DELETE_TEMP_FILE = "Failed to delete temp file {}"; + public static final String ERROR_ON_EXTRACTING_FILE = "Error on extracting file"; private IImageDimensionReader imageDimensionReader; private Map imageResizerClasses; private boolean imageMagickEnabled; @@ -74,9 +78,11 @@ public InputStream getResourceStream(int size, String langCode) { String subPath = super.getDiskSubFolder() + instance.getFileName(); try { return this.getStorageManager().getStream(subPath, this.isProtectedResource()); + } catch (EntResourceNotFoundException e) { + throw new EntResourceNotFoundRuntimeException(ERROR_ON_EXTRACTING_FILE, e); } catch (Throwable t) { - logger.error("Error on extracting file", t); - throw new RuntimeException("Error on extracting file", t); + logger.error(ERROR_ON_EXTRACTING_FILE, t); + throw new EntRuntimeException(ERROR_ON_EXTRACTING_FILE, t); } } diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ResourceDataBean.java b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ResourceDataBean.java index 010e6d9225..23d571b89c 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ResourceDataBean.java +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ResourceDataBean.java @@ -108,7 +108,7 @@ public interface ResourceDataBean { * * @return La lista dei metadati della risorsa. */ - public Map getMetadata(); + public Map getMetadata(); public void setMetadata(Map metadata); diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentService.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentService.java index 2eae9592f4..a582f2f6fc 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentService.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentService.java @@ -109,13 +109,13 @@ public class ContentService extends AbstractEntityService implements IContentService, GroupServiceUtilizer, CategoryServiceUtilizer, - PageServiceUtilizer, ContentServiceUtilizer, - ResourceServiceUtilizer, - IComponentExistsService, IComponentUsageService, + PageServiceUtilizer, ContentServiceUtilizer, + ResourceServiceUtilizer, + IComponentExistsService, IComponentUsageService, ApplicationContextAware { private final EntLogger logger = EntLogFactory.getSanitizedLogger(getClass()); - + private ICategoryManager categoryManager; private IContentManager contentManager; private IContentModelManager contentModelManager; @@ -326,7 +326,8 @@ protected void fillEntity(EntityDto request, Content entity, BindingResult bindi @Override public List getGroupUtilizer(String groupCode) { try { - List contentIds = ((GroupUtilizer) this.getContentManager()).getGroupUtilizers(groupCode); + @SuppressWarnings("unchecked") + List contentIds = ((GroupUtilizer) this.getContentManager()).getGroupUtilizers(groupCode); return this.buildDtoList(contentIds); } catch (EntException ex) { logger.error("Error loading content references for group {}", groupCode, ex); @@ -337,6 +338,7 @@ public List getGroupUtilizer(String groupCode) { @Override public List getCategoryUtilizer(String categoryCode) { try { + @SuppressWarnings("unchecked") List contentIds = ((CategoryUtilizer) this.getContentManager()).getCategoryUtilizers(categoryCode); return this.buildDtoList(contentIds); } catch (EntException ex) { @@ -348,6 +350,7 @@ public List getCategoryUtilizer(String categoryCode) { @Override public List getPageUtilizer(String pageCode) { try { + @SuppressWarnings("unchecked") List contentIds = ((PageUtilizer) this.getContentManager()).getPageUtilizers(pageCode); return this.buildDtoList(contentIds); } catch (EntException ex) { @@ -359,6 +362,7 @@ public List getPageUtilizer(String pageCode) { @Override public List getContentUtilizer(String contentId) { try { + @SuppressWarnings("unchecked") List contentIds = ((ContentUtilizer) this.getContentManager()).getContentUtilizers(contentId); return this.buildDtoList(contentIds); } catch (EntException ex) { @@ -370,6 +374,7 @@ public List getContentUtilizer(String contentId) { @Override public List getResourceUtilizer(String resourceId) { try { + @SuppressWarnings("unchecked") List contentIds = ((ResourceUtilizer) this.getContentManager()).getResourceUtilizers(resourceId); return this.buildDtoList(contentIds); } catch (EntException ex) { @@ -561,11 +566,9 @@ private PagedMetadata toPagedMetadata(RestContentListRequest request public Integer countContentsByType(String contentType) { try { EntitySearchFilter[] filters = new EntitySearchFilter[]{ - new EntitySearchFilter("typeCode", false, contentType, false) + new EntitySearchFilter<>("typeCode", false, contentType, false) }; - List userGroupCodes = Collections.singletonList("administrators"); - return getContentManager().countWorkContents(null, false, filters, userGroupCodes); } catch (Exception t) { logger.error("error in contents count by type", t); @@ -714,13 +717,13 @@ public ContentDto updateContent(ContentDto request, UserDetails user, BindingRes request.setRestriction(ContentRestriction.getRestrictionValue(request.getMainGroup())); return super.updateEntity(JacmsSystemConstants.CONTENT_MANAGER, request, bindingResult); } - + @Override public void deleteContent(String code, UserDetails user) { this.checkContentAuthorization(user, code, false, true, null); this.deleteContent(code); } - + private void deleteContent(String code) { try { Content content = this.getContentManager().loadContent(code, false); @@ -749,7 +752,7 @@ public ContentDto updateContentStatus(String code, String status, UserDetails us return updateContentStatus(code, status, user, bindingResult, false); } - private ContentDto updateContentStatus(String code, String status, + private ContentDto updateContentStatus(String code, String status, UserDetails user, BeanPropertyBindingResult bindingResult, boolean forceUnpublish) { try { this.checkContentExists(code); @@ -841,16 +844,16 @@ public PagedMetadata getContentReferences(String code, String managerName, Us logger.warn("no content found with code {}", code); throw new ResourceNotFoundException(ERRCODE_CONTENT_NOT_FOUND, ComponentUsageEntity.TYPE_CONTENT, code); } - ContentServiceUtilizer utilizer = this.getContentServiceUtilizer(managerName); + ContentServiceUtilizer utilizer = this.getContentServiceUtilizer(managerName); if (null == utilizer) { logger.warn("no references found for {}", managerName); throw new ResourceNotFoundException(ERRCODE_CONTENT_REFERENCES, "reference", managerName); } - List dtoList = utilizer.getContentUtilizer(code); - List subList = requestList.getSublist(dtoList); - SearcherDaoPaginatedResult pagedResult = new SearcherDaoPaginatedResult(dtoList.size(), subList); - PagedMetadata pagedMetadata = new PagedMetadata<>(requestList, pagedResult); - pagedMetadata.setBody((List) subList); + List dtoList = utilizer.getContentUtilizer(code); + List subList = requestList.getSublist(dtoList); + SearcherDaoPaginatedResult pagedResult = new SearcherDaoPaginatedResult<>(dtoList.size(), subList); + PagedMetadata pagedMetadata = new PagedMetadata<>(requestList, pagedResult); + pagedMetadata.setBody(subList); return pagedMetadata; } catch (EntException ex) { logger.error("Error extracting content references - content {} - manager {}", code, managerName, ex); @@ -858,7 +861,8 @@ public PagedMetadata getContentReferences(String code, String managerName, Us } } - private ContentServiceUtilizer getContentServiceUtilizer(String managerName) { + @SuppressWarnings("unchecked") + private ContentServiceUtilizer getContentServiceUtilizer(String managerName) { Map beans = this.applicationContext .getBeansOfType(ContentServiceUtilizer.class); ContentServiceUtilizer defName = beans.values().stream() @@ -885,6 +889,7 @@ public PagedMetadata getComponentUsageDetails(String compo List components = new ArrayList<>(); Map beans = this.applicationContext.getBeansOfType(ContentServiceUtilizer.class); for (var utilizer : beans.values()) { + @SuppressWarnings("unchecked") List objects = utilizer.getContentUtilizer(componentCode); List utilizerForService = objects.stream() .map(o -> o.buildUsageEntity()).collect(Collectors.toList()); diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentTypeService.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentTypeService.java index 1108a8841f..f54c0bc05d 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentTypeService.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentTypeService.java @@ -199,6 +199,7 @@ public PagedMetadata getComponentUsageDetails(String compo .map(ContentDto::buildUsageEntity) .collect(Collectors.toList()); for (var utilizer : this.contentTypeServiceUtilizers) { + @SuppressWarnings("unchecked") List objects = utilizer.getContentTypeUtilizer(componentCode); List utilizerForService = objects.stream() .map(o -> o.buildUsageEntity()).collect(Collectors.toList()); diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/page/CmsPageServiceWrapper.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/page/CmsPageServiceWrapper.java index fb8f540323..9504f2b9c2 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/page/CmsPageServiceWrapper.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/page/CmsPageServiceWrapper.java @@ -58,6 +58,7 @@ public String getManagerName() { @Override public List getContentUtilizer(String contentId) { try { + @SuppressWarnings("unchecked") List pages = this.getPageManagerWrapper().getContentUtilizers(contentId); return this.getDtoBuilder().convert(pages); } catch (EntException ex) { diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/resource/ResourcesService.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/resource/ResourcesService.java index 8c45d4db9d..912066001a 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/resource/ResourcesService.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/resource/ResourcesService.java @@ -51,6 +51,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -61,7 +62,6 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.lang3.StringUtils; import org.entando.entando.aps.system.exception.ResourceNotFoundException; import org.entando.entando.aps.system.exception.RestServerError; @@ -523,8 +523,7 @@ public void validateMimeType(String resourceType, final String mimeType) { private List getImageDimensions() { Map master = imageDimensionManager.getImageDimensions(); List dimensions = new ArrayList<>(master.values()); - BeanComparator comparator = new BeanComparator("dimx"); - Collections.sort(dimensions, comparator); + Collections.sort(dimensions, Comparator.comparing(ImageResourceDimension::getDimx)); return dimensions; } @@ -532,7 +531,7 @@ private FieldSearchFilter[] createSearchFilters(ListResourceRequest requestList) List filters = new ArrayList<>(); if (requestList.getType() != null) { filters.add( - new FieldSearchFilter(IResourceManager.RESOURCE_TYPE_FILTER_KEY, + new FieldSearchFilter<>(IResourceManager.RESOURCE_TYPE_FILTER_KEY, convertResourceType(requestList.getType()), false) ); } @@ -582,7 +581,7 @@ private FieldSearchFilter[] createSearchFilters(ListResourceRequest requestList) private FieldSearchFilter[] createFolderPathSearchFilter(String folderPath) { List filters = new ArrayList<>(); if (folderPath != null) { - filters.add(new FieldSearchFilter(IResourceManager.RESOURCE_FOLDER_PATH_FILTER_KEY, folderPath, true)); + filters.add(new FieldSearchFilter<>(IResourceManager.RESOURCE_FOLDER_PATH_FILTER_KEY, folderPath, true)); } return filters.stream().toArray(FieldSearchFilter[]::new); } @@ -593,10 +592,10 @@ private FieldSearchFilter checkDateFilter(FieldSearchFilter original) { Object start = original.getStart(); Object end = original.getEnd(); if (null != value) { - dateFilter = new FieldSearchFilter(original.getKey(), this.checkDate(value, original), false); + dateFilter = new FieldSearchFilter<>(original.getKey(), this.checkDate(value, original), false); dateFilter.setValueDateDelay(original.getValueDateDelay()); } else if (null != start || null != end) { - dateFilter = new FieldSearchFilter(original.getKey(), this.checkDate(start, original), this.checkDate(end, original)); + dateFilter = new FieldSearchFilter<>(original.getKey(), this.checkDate(start, original), this.checkDate(end, original)); dateFilter.setStartDateDelay(original.getStartDateDelay()); dateFilter.setEndDateDelay(original.getEndDateDelay()); } else { diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/widgettype/validators/WidgetValidatorCmsHelper.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/widgettype/validators/WidgetValidatorCmsHelper.java index 80b7f71e35..e6cb0adc8e 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/widgettype/validators/WidgetValidatorCmsHelper.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/aps/system/services/widgettype/validators/WidgetValidatorCmsHelper.java @@ -119,6 +119,7 @@ public static String extractConfigParam(WidgetConfigurationRequest widget, Strin return null; } + @SuppressWarnings("unchecked") public static List extractConfig(WidgetConfigurationRequest widget, String key) { Map config = (Map) widget.getConfig(); if (null != config) { diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/ResourcesController.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/ResourcesController.java index 5e8b263b18..4bdc76db4c 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/ResourcesController.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/ResourcesController.java @@ -241,6 +241,6 @@ public ResponseEntity>> deleteAsset( } service.deleteAsset(resourceId, correlationCode); - return ResponseEntity.ok(new SimpleRestResponse<>(new HashMap())); + return ResponseEntity.ok(new SimpleRestResponse<>(new HashMap<>())); } } diff --git a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/validator/ResourcesValidator.java b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/validator/ResourcesValidator.java index e0e0512397..a023607a09 100644 --- a/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/validator/ResourcesValidator.java +++ b/cms-plugin/src/main/java/org/entando/entando/plugins/jacms/web/resource/validator/ResourcesValidator.java @@ -66,6 +66,7 @@ public boolean resourceExists(String resourceId, String correlationCode) throws } public void resourceReferencesValidation(String resourceId, Errors errors) throws EntException { + @SuppressWarnings("unchecked") List references = ((ResourceUtilizer) contentManager).getResourceUtilizers(resourceId); if (references != null && references.size() > 0) { references.forEach(reference->{ diff --git a/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBeanTest.java b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBeanTest.java new file mode 100644 index 0000000000..da2aecbf96 --- /dev/null +++ b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/content/widget/UserFilterOptionBeanTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 2023-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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 Lesser General Public License for more + * details. + */ +package com.agiletec.plugins.jacms.aps.system.services.content.widget; + +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.aps.system.common.entity.model.IApsEntity; +import com.agiletec.aps.system.common.entity.model.attribute.BooleanAttribute; +import com.agiletec.aps.system.common.entity.model.attribute.DateAttribute; +import com.agiletec.aps.system.common.entity.model.attribute.NumberAttribute; +import com.agiletec.aps.system.common.entity.model.attribute.TextAttribute; +import com.agiletec.aps.system.services.lang.Lang; +import com.agiletec.aps.util.DateConverter; +import com.agiletec.plugins.jacms.aps.system.services.content.widget.UserFilterOptionBean.AttributeFormFieldError; +import java.math.BigDecimal; +import java.util.Properties; +import javax.servlet.http.HttpServletRequest; +import org.entando.entando.aps.system.services.searchengine.SearchEngineFilter; +import org.entando.entando.ent.exception.EntException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class UserFilterOptionBeanTest { + + @Mock + private IApsEntity prototype; + + @Test + void shouldReturnErrorOnInvalidAttribute() { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "textAttribute"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "text"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + Mockito.when(prototype.getAttribute("textAttribute")).thenReturn(null); + Assertions.assertThrows(EntException.class, () -> { + new UserFilterOptionBean(prop, prototype); + }); + } + + @Test + void shouldExtractTextFilter() throws Throwable { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "textAttribute"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "text"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + TextAttribute textAttribute = Mockito.mock(TextAttribute.class); + Mockito.when(textAttribute.getType()).thenReturn("Text"); + Mockito.when(textAttribute.getName()).thenReturn("textAttribute"); + Mockito.when(prototype.getAttribute("textAttribute")).thenReturn(textAttribute); + Lang lang = new Lang(); + lang.setCode("en"); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // String[] fieldsSuffix = {"_textFieldName"}; + // String fieldName = paramName + fieldSuffix + frameIdSuffix; + Mockito.when(request.getParameter("textAttribute_textFieldName_frame8")).thenReturn("text"); + UserFilterOptionBean ubof = new UserFilterOptionBean(prop, prototype, 8, lang, "yyyy-MM-dd", request); + EntitySearchFilter ef = ubof.getEntityFilter(); + Assertions.assertEquals("textAttribute", ef.getKey()); + Assertions.assertEquals("text", ef.getValue()); + Assertions.assertEquals(true, ef.isAttributeFilter()); + SearchEngineFilter filter = ubof.extractFilter(); + Assertions.assertEquals("Text:textAttribute", filter.getKey()); + Assertions.assertEquals("text", filter.getValue()); + Assertions.assertEquals(SearchEngineFilter.TextSearchOption.EXACT, filter.getTextSearchOption()); + } + + @Test + void shouldExtractDateFilter() throws Throwable { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "dateAttribute"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "date"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + DateAttribute dateAttribute = Mockito.mock(DateAttribute.class); + Mockito.when(dateAttribute.getType()).thenReturn("Date"); + Mockito.when(dateAttribute.getName()).thenReturn("dateAttribute"); + Mockito.when(prototype.getAttribute("dateAttribute")).thenReturn(dateAttribute); + Lang lang = new Lang(); + lang.setCode("it"); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // String[] fieldsSuffix = {"_dateStartFieldName", "_dateEndFieldName"}; + Mockito.when(request.getParameter("dateAttribute_dateStartFieldName_frame7")).thenReturn("2023-10-23"); + Mockito.when(request.getParameter("dateAttribute_dateEndFieldName_frame7")).thenReturn("2023-11-17"); + UserFilterOptionBean ubof = new UserFilterOptionBean(prop, prototype, 7, lang, "yyyy-MM-dd", request); + Assertions.assertNull(ubof.getFormFieldErrors()); + EntitySearchFilter ef = ubof.getEntityFilter(); + Assertions.assertEquals("dateAttribute", ef.getKey()); + Assertions.assertNull(ef.getValue()); + Assertions.assertEquals(true, ef.isAttributeFilter()); + Assertions.assertEquals(DateConverter.parseDate("2023-10-23", "yyyy-MM-dd"), ef.getStart()); + Assertions.assertEquals(DateConverter.parseDate("2023-11-17", "yyyy-MM-dd"), ef.getEnd()); + SearchEngineFilter filter = ubof.extractFilter(); + Assertions.assertEquals("Date:dateAttribute", filter.getKey()); + Assertions.assertNull(filter.getValue()); + Assertions.assertEquals(DateConverter.parseDate("2023-10-23", "yyyy-MM-dd"), filter.getStart()); + Assertions.assertEquals(DateConverter.parseDate("2023-11-17", "yyyy-MM-dd"), filter.getEnd()); + Assertions.assertNull(filter.getTextSearchOption()); + } + + @Test + void shouldReturnErrorWithWrongDateRange() throws Throwable { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "dateAttr"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "date"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + DateAttribute dateAttribute = Mockito.mock(DateAttribute.class); + Mockito.when(dateAttribute.getType()).thenReturn("Date"); + Mockito.when(dateAttribute.getName()).thenReturn("dateAttr"); + Mockito.when(prototype.getAttribute("dateAttr")).thenReturn(dateAttribute); + Lang lang = new Lang(); + lang.setCode("it"); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // String[] fieldsSuffix = {"_dateStartFieldName", "_dateEndFieldName"}; + Mockito.when(request.getParameter("dateAttr_dateStartFieldName_frame7")).thenReturn("2023-10-23"); + Mockito.when(request.getParameter("dateAttr_dateEndFieldName_frame7")).thenReturn("2023-07-17"); + UserFilterOptionBean ubof = new UserFilterOptionBean(prop, prototype, 7, lang, "yyyy-MM-dd", request); + Assertions.assertEquals(1, ubof.getFormFieldErrors().size()); + AttributeFormFieldError error = ubof.getFormFieldErrors().get("dateAttr_dateEndFieldName_frame7"); + Assertions.assertEquals("dateAttr", error.getAttributeName()); + Assertions.assertEquals("dateAttr_dateEndFieldName_frame7", error.getFieldName()); + Assertions.assertEquals(AttributeFormFieldError.INVALID_RANGE_KEY, error.getErrorKey()); + } + + @Test + void shouldExtractNumberFilter() throws Throwable { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "numberAttribute"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "number"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + NumberAttribute numberAttribute = Mockito.mock(NumberAttribute.class); + Mockito.when(numberAttribute.getType()).thenReturn("Number"); + Mockito.when(numberAttribute.getName()).thenReturn("numberAttribute"); + Mockito.when(prototype.getAttribute("numberAttribute")).thenReturn(numberAttribute); + Lang lang = new Lang(); + lang.setCode("it"); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // String[] fieldsSuffix = {"_numberStartFieldName", "_numberEndFieldName"}; + Mockito.when(request.getParameter("numberAttribute_numberStartFieldName_frame3")).thenReturn("19"); + Mockito.when(request.getParameter("numberAttribute_numberEndFieldName_frame3")).thenReturn("128"); + UserFilterOptionBean ubof = new UserFilterOptionBean(prop, prototype, 3, lang, "yyyy-MM-dd", request); + Assertions.assertNull(ubof.getFormFieldErrors()); + EntitySearchFilter ef = ubof.getEntityFilter(); + Assertions.assertEquals("numberAttribute", ef.getKey()); + Assertions.assertNull(ef.getValue()); + Assertions.assertEquals(true, ef.isAttributeFilter()); + Assertions.assertEquals(19, ((BigDecimal) ef.getStart()).intValue()); + Assertions.assertEquals(128, ((BigDecimal) ef.getEnd()).intValue()); + SearchEngineFilter filter = ubof.extractFilter(); + Assertions.assertEquals("Number:numberAttribute", filter.getKey()); + Assertions.assertNull(filter.getValue()); + Assertions.assertEquals(19, ((BigDecimal) filter.getStart()).intValue()); + Assertions.assertEquals(128, ((BigDecimal) filter.getEnd()).intValue()); + Assertions.assertNull(filter.getTextSearchOption()); + } + + @Test + void shouldExtractBooleanFilter() throws Throwable { + Properties prop = new Properties(); + prop.setProperty(UserFilterOptionBean.PARAM_KEY, "booleanAttribute"); + prop.setProperty(UserFilterOptionBean.TYPE_ATTRIBUTE, "boolean"); + prop.setProperty(UserFilterOptionBean.PARAM_IS_ATTRIBUTE_FILTER, "true"); + BooleanAttribute booleanAttribute = Mockito.mock(BooleanAttribute.class); + Mockito.when(booleanAttribute.getType()).thenReturn("Boolean"); + Mockito.when(booleanAttribute.getName()).thenReturn("booleanAttribute"); + Mockito.when(prototype.getAttribute("booleanAttribute")).thenReturn(booleanAttribute); + Lang lang = new Lang(); + lang.setCode("en"); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // String[] fieldsSuffix = {"_booleanFieldName", "_booleanFieldName_ignore", "_booleanFieldName_control"}; + Mockito.when(request.getParameter("booleanAttribute_booleanFieldName_frame9")).thenReturn("true"); + Mockito.when(request.getParameter("booleanAttribute_booleanFieldName_ignore_frame9")).thenReturn(null); + Mockito.when(request.getParameter("booleanAttribute_booleanFieldName_control_frame9")).thenReturn("true"); + UserFilterOptionBean ubof = new UserFilterOptionBean(prop, prototype, 9, lang, "yyyy-MM-dd", request); + Assertions.assertNull(ubof.getFormFieldErrors()); + EntitySearchFilter ef = ubof.getEntityFilter(); + Assertions.assertEquals("booleanAttribute", ef.getKey()); + Assertions.assertEquals("true", ef.getValue()); + Assertions.assertEquals(true, ef.isAttributeFilter()); + Assertions.assertNull(ef.getStart()); + Assertions.assertNull(ef.getEnd()); + } + +} diff --git a/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AttachResourceTest.java b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AttachResourceTest.java new file mode 100644 index 0000000000..6a4ad888e9 --- /dev/null +++ b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/AttachResourceTest.java @@ -0,0 +1,43 @@ +package com.agiletec.plugins.jacms.aps.system.services.resource.model; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.entando.entando.aps.system.services.storage.IStorageManager; +import org.entando.entando.ent.exception.EntResourceNotFoundException; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; +import org.entando.entando.ent.exception.EntException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class AttachResourceTest { + + @Test + void getResourceStreamShouldFireEntCDSResourceNotFoundExceptionIfAnErrorOccurInCDSManager() throws EntException { + AttachResource attachResource = new AttachResource(); + ResourceInstance resourceInstance = mock(ResourceInstance.class); + when(resourceInstance.getFileName()).thenReturn(""); + attachResource.addInstance(resourceInstance); + IStorageManager storageManager = mock(IStorageManager.class); + attachResource.setStorageManager(storageManager); + when(storageManager.getStream(any(), anyBoolean())).thenThrow(EntResourceNotFoundException.class); + Assertions.assertThrows(EntResourceNotFoundRuntimeException.class, + () -> attachResource.getResourceStream(1, "")); + } + + @Test + void getResourceStreamShouldFireRuntimeExceptionIfAnErrorOccurInAnyManagerButCDSManager() throws EntException { + AttachResource attachResource = new AttachResource(); + ResourceInstance resourceInstance = mock(ResourceInstance.class); + when(resourceInstance.getFileName()).thenReturn(""); + attachResource.addInstance(resourceInstance); + IStorageManager storageManager = mock(IStorageManager.class); + attachResource.setStorageManager(storageManager); + when(storageManager.getStream(any(), anyBoolean())).thenThrow(EntException.class); + Assertions.assertThrows(RuntimeException.class, + () -> attachResource.getResourceStream(1, "")); + } + +} diff --git a/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResourceTest.java b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResourceTest.java new file mode 100644 index 0000000000..841cc8b3b4 --- /dev/null +++ b/cms-plugin/src/test/java/com/agiletec/plugins/jacms/aps/system/services/resource/model/ImageResourceTest.java @@ -0,0 +1,38 @@ +package com.agiletec.plugins.jacms.aps.system.services.resource.model; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.entando.entando.aps.system.services.storage.IStorageManager; +import org.entando.entando.ent.exception.EntResourceNotFoundException; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; +import org.entando.entando.ent.exception.EntException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ImageResourceTest { + + @Test + void getResourceStreamShouldFireEntCDSResourceNotFoundExceptionIfAnErrorOccurInCDSManager() throws EntException { + ImageResource imageResource = new ImageResource(); + IStorageManager storageManager = mock(IStorageManager.class); + imageResource.setStorageManager(storageManager); + imageResource.getInstances().put("1", mock(ResourceInstance.class)); + when(storageManager.getStream(any(), anyBoolean())).thenThrow(EntResourceNotFoundException.class); + Assertions.assertThrows(EntResourceNotFoundRuntimeException.class, + () -> imageResource.getResourceStream(1, "")); + } + @Test + void getResourceStreamShouldFireRuntimeExceptionIfAnErrorOccurInAnyManagerButCDSManager() throws EntException { + ImageResource imageResource = new ImageResource(); + IStorageManager storageManager = mock(IStorageManager.class); + imageResource.setStorageManager(storageManager); + imageResource.getInstances().put("1", mock(ResourceInstance.class)); + when(storageManager.getStream(any(), anyBoolean())).thenThrow(EntException.class); + Assertions.assertThrows(RuntimeException.class, + () -> imageResource.getResourceStream(1, "")); + } + +} diff --git a/cms-plugin/src/test/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentServiceTest.java b/cms-plugin/src/test/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentServiceTest.java index 9021434891..732ea50a48 100644 --- a/cms-plugin/src/test/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentServiceTest.java +++ b/cms-plugin/src/test/java/org/entando/entando/plugins/jacms/aps/system/services/content/ContentServiceTest.java @@ -525,6 +525,23 @@ private RestContentListRequest prepareGetContentTest(UserDetails user) throws En return requestList; } + @Test + void shouldFindReferences() throws Exception { + ContentServiceUtilizer utilizer = Mockito.mock(ContentServiceUtilizer.class); + List components = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + IComponentDto dto = Mockito.mock(IComponentDto.class); + components.add(dto); + } + when(utilizer.getManagerName()).thenReturn("service"); + when(utilizer.getContentUtilizer(Mockito.anyString())).thenReturn(components); + when(this.applicationContext.getBeansOfType(ContentServiceUtilizer.class)).thenReturn(Map.of("service", utilizer)); + when(this.contentManager.loadContent("ART123", false)).thenReturn(Mockito.mock(Content.class)); + PagedMetadata result = contentService.getContentReferences("ART123", + "service", Mockito.mock(UserDetails.class), new RestListRequest()); + Assertions.assertEquals(5, result.getBody().size()); + } + @Test void shouldFindComponentDto() throws Exception { this.addMockedContent("ART123", "ART", null, null); diff --git a/contentscheduler-plugin/pom.xml b/contentscheduler-plugin/pom.xml index 7bf7de9b8b..68f178e522 100644 --- a/contentscheduler-plugin/pom.xml +++ b/contentscheduler-plugin/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpcontentscheduler org.entando.entando.plugins diff --git a/engine/pom.xml b/engine/pom.xml index 1950b28499..dc5dc16b50 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando entando-engine @@ -500,6 +500,10 @@ org.junit.jupiter junit-jupiter-api + + uk.org.webcompere + system-stubs-jupiter + org.mockito mockito-core diff --git a/engine/src/main/java/com/agiletec/aps/system/services/category/CategoryUtilizer.java b/engine/src/main/java/com/agiletec/aps/system/services/category/CategoryUtilizer.java index 77bb00ec17..318f1edc19 100644 --- a/engine/src/main/java/com/agiletec/aps/system/services/category/CategoryUtilizer.java +++ b/engine/src/main/java/com/agiletec/aps/system/services/category/CategoryUtilizer.java @@ -23,7 +23,7 @@ * * @author E.Santoboni */ -public interface CategoryUtilizer { +public interface CategoryUtilizer { /** * Restituisce l'identificativo del servizio utilizzatore. @@ -41,7 +41,7 @@ public interface CategoryUtilizer { * dal codice specificato. * @throws EntException In caso di errore. */ - public List getCategoryUtilizers(String categoryCode) throws EntException; + public List getCategoryUtilizers(String categoryCode) throws EntException; /** * Reload the category references. @@ -64,6 +64,6 @@ public interface CategoryUtilizer { * @return * @throws EntException In case of error */ - public List getCategoryUtilizersForReloadReferences(String categoryCode) throws EntException; + public List getCategoryUtilizersForReloadReferences(String categoryCode) throws EntException; } diff --git a/engine/src/main/java/org/entando/entando/aps/system/init/DatabaseManager.java b/engine/src/main/java/org/entando/entando/aps/system/init/DatabaseManager.java index 4af58e5190..ed6e1af35e 100644 --- a/engine/src/main/java/org/entando/entando/aps/system/init/DatabaseManager.java +++ b/engine/src/main/java/org/entando/entando/aps/system/init/DatabaseManager.java @@ -106,9 +106,6 @@ public SystemInstallationReport installDatabase(SystemInstallationReport report, DatabaseMigrationStrategy strategy, Optional> datasources) throws Exception { String lastLocalBackupFolder = null; - - - if (DatabaseMigrationStrategy.SKIP.equals(strategy)) { Optional tenantCodeOp = ApsTenantApplicationUtils.getTenant(); logger.warn(String.format("Database Migration Strategy, Tenant '%s', SKIPPED", tenantCodeOp.orElse("*primary*"))); @@ -118,10 +115,8 @@ public SystemInstallationReport installDatabase(SystemInstallationReport report, report = SystemInstallationReport.getInstance(); lastLocalBackupFolder = checkRestore(report, strategy); } - // Check if we are dealing with an old database version (not Liquibase compliant - Entando <= 6.3.2) legacyDatabaseCheck(datasources); - try { initComponents(report, strategy, datasources); if (DatabaseMigrationStrategy.AUTO.equals(strategy) && Status.RESTORE.equals(report.getStatus())) { @@ -264,7 +259,6 @@ public List initLiquiBaseResources(Component componentConfigura componentConfiguration.getCode(), changeLogFile, dataSourceName, report.getStatus(), migrationStrategy, datasources); - pendingChangeSet.addAll(changeSetToExecute); ApsSystemUtils.directStdoutTrace("| ( ok ) " + dataSourceName); if (!DatabaseMigrationStrategy.DISABLED.equals(migrationStrategy)) { @@ -272,6 +266,8 @@ public List initLiquiBaseResources(Component componentConfigura } else { liquibaseReport.getDatabaseStatus().put(dataSourceName, Status.SKIPPED); } + } else { + liquibaseReport.getDatabaseStatus().put(dataSourceName, Status.NOT_AVAILABLE); } } if (report.getStatus().equals(SystemInstallationReport.Status.RESTORE) || report.getStatus().equals(SystemInstallationReport.Status.PORTING)) { diff --git a/engine/src/main/java/org/entando/entando/aps/system/init/InitializerManager.java b/engine/src/main/java/org/entando/entando/aps/system/init/InitializerManager.java index 96278c8057..1da8589c87 100644 --- a/engine/src/main/java/org/entando/entando/aps/system/init/InitializerManager.java +++ b/engine/src/main/java/org/entando/entando/aps/system/init/InitializerManager.java @@ -93,7 +93,7 @@ private DatabaseMigrationStrategy getMigrationStrategyEnum() throws EntException throw new EntException(message, e); } } - + public void init() throws Exception { initPrimary(); } @@ -101,8 +101,7 @@ public void init() throws Exception { public void initPrimary() throws Exception { DatabaseMigrationStrategy migrationStrategyEnum = this.getMigrationStrategyEnum(); DatabaseMigrationStrategy defaultComputedStrategy = Optional.ofNullable(migrationStrategyEnum).orElse(DatabaseMigrationStrategy.DISABLED); - - initTenant(defaultComputedStrategy, Optional.empty()); + this.initTenant(defaultComputedStrategy, Optional.empty()); } public void initTenant(DatabaseMigrationStrategy migrationStrategy, Optional> datasources) throws Exception { @@ -122,7 +121,7 @@ public void initTenant(DatabaseMigrationStrategy migrationStrategy, Optional getConfigOfReadyTenant(String tenantCode); + Optional getConfig(String tenantCode); Optional getTenantConfigByDomain(String domain); diff --git a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantInitializerService.java b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantInitializerService.java index 8846add029..2bbb35afe0 100644 --- a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantInitializerService.java +++ b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantInitializerService.java @@ -2,8 +2,6 @@ import com.agiletec.aps.system.services.baseconfig.BaseConfigManager; import com.agiletec.aps.util.ApsTenantApplicationUtils; -import com.agiletec.aps.util.ApsWebApplicationUtils; -import com.fasterxml.jackson.databind.ser.Serializers.Base; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -71,6 +69,8 @@ private void manageTenantsInit(Map statuses, Initializatio statuses.put(tenantCode,TenantStatus.READY); refreshBeanForTenantCode(svCtx, tenantCode); + + this.executePostInitProcesses(); } catch (Throwable th) { statuses.put(tenantCode,TenantStatus.FAILED); @@ -106,8 +106,11 @@ private void initDb(String tenantCode) throws Exception { Map datasources = new HashMap<>(); datasources.put("portDataSource",tenantDataAccessor.getTenantDatasource(tenantCode)); datasources.put("servDataSource",tenantDataAccessor.getTenantDatasource(tenantCode)); - initializerManager.initTenant(strategy, Optional.of(datasources)); - + this.initializerManager.initTenant(strategy, Optional.of(datasources)); + } + + private void executePostInitProcesses() { + initializerManager.executePostInitProcesses(); } private void refreshBeanForTenantCode(ServletContext svCtx, String tenantCode) throws Throwable { diff --git a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantManager.java b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantManager.java index cdca9207eb..41bd6bf8ca 100644 --- a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantManager.java +++ b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantManager.java @@ -34,12 +34,11 @@ public class TenantManager implements ITenantManager, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(TenantManager.class); - - + private final String tenantsConfigAsString; private final ObjectMapper objectMapper; private final TenantDataAccessor tenantDataAccessor; - + @Autowired public TenantManager(@Value("${ENTANDO_TENANTS:}") String s, ObjectMapper o, TenantDataAccessor tenantDataAccessor){ this.tenantsConfigAsString = s; @@ -47,7 +46,6 @@ public TenantManager(@Value("${ENTANDO_TENANTS:}") String s, ObjectMapper o, Ten this.tenantDataAccessor = tenantDataAccessor; } - protected void release() { try { tenantDataAccessor.getTenantDataSources().values().forEach(this::destroyDataSource); @@ -85,13 +83,13 @@ public Map getStatuses() { @Override public String getTenantCodeByDomain(String domain) { - String tenantCode = tenantDataAccessor.getTenantConfigs().values().stream() + String tenantCode = tenantDataAccessor.getTenantConfigs().values().stream() .filter(v -> v.getFqdns().contains(domain)) .map(tc -> tc.getTenantCode()) .filter(StringUtils::isNotBlank) .findFirst() .orElse(getCodes().stream().filter(code -> StringUtils.equals(code, domain)).findFirst().orElse(null)); - if(logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { logger.debug("From domain:'{}' retrieved tenantCode:'{}' from codes:'{}'", domain, tenantCode, getCodes().stream().collect(Collectors.joining(","))); } @@ -100,7 +98,7 @@ public String getTenantCodeByDomain(String domain) { @Override public Optional getTenantConfigByDomain(String domain) { - return this.getConfig(this.getTenantCodeByDomain(domain)); + return this.getConfigOfReadyTenant(this.getTenantCodeByDomain(domain)); } @Override @@ -109,17 +107,21 @@ public DataSource getDatasource(String tenantCode) { } @Override - public Optional getConfig(String tenantCode) { + public Optional getConfigOfReadyTenant(String tenantCode) { return Optional.ofNullable(tenantCode).map(this::identityIfStatusReadyOrThrow).map(tenantDataAccessor.getTenantConfigs()::get); } + @Override + public Optional getConfig(String tenantCode) { + return Optional.ofNullable(tenantCode).map(tenantDataAccessor.getTenantConfigs()::get); + } + private void initTenantsCodes() throws Exception { if (!StringUtils.isBlank(this.tenantsConfigAsString)) { List list = this.objectMapper.readValue(tenantsConfigAsString, new TypeReference>>(){}) .stream() .map(TenantConfig::new) .collect(Collectors.toList()); - list.stream().filter(tc -> PRIMARY_CODE.equalsIgnoreCase(tc.getTenantCode())).findFirst().ifPresent(tc -> { logger.error("You cannot use 'primary' as tenant code"); throw new RuntimeException("You cannot use 'primary' as tenant code"); diff --git a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantService.java b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantService.java index 667ae10ac1..b73583d9c8 100644 --- a/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantService.java +++ b/engine/src/main/java/org/entando/entando/aps/system/services/tenants/TenantService.java @@ -51,19 +51,19 @@ public TenantService(ITenantManager tenantManager, TenantDataAccessor accessor, } public TenantDto getCurrentTenant() { - return tenantManager.getConfig(ApsTenantApplicationUtils.getTenant().orElse(PRIMARY_CODE)) + return tenantManager.getConfigOfReadyTenant(ApsTenantApplicationUtils.getTenant().orElse(PRIMARY_CODE)) .map(this::mapTenantToTenantDto).orElseGet(this::mapPrimaryToTenantDto); } public Optional getTenant(String tenantCode) { - return tenantManager.getConfig(tenantCode) + return tenantManager.getConfigOfReadyTenant(tenantCode) .map(this::mapTenantToTenantDto).or(() -> Optional.ofNullable(tenantCode) .filter(PRIMARY_CODE::equals).map(t -> mapPrimaryToTenantDto())); } public List getTenants() { List tenants = tenantManager.getCodes().stream() - .map(tenantManager::getConfig) + .map(tenantManager::getConfigOfReadyTenant) .flatMap(Optional::stream) .map(this::mapTenantToTenantDto).collect(Collectors.toList()); diff --git a/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundException.java b/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundException.java new file mode 100644 index 0000000000..bf7d081e5c --- /dev/null +++ b/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundException.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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 Lesser General Public License for more + * details. + */ +package org.entando.entando.ent.exception; + +/** + * Generic Entando Runtime Exception + */ +public class EntResourceNotFoundException extends EntException { + + public EntResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundRuntimeException.java b/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundRuntimeException.java new file mode 100644 index 0000000000..b57abf4c40 --- /dev/null +++ b/engine/src/main/java/org/entando/entando/ent/exception/EntResourceNotFoundRuntimeException.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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 Lesser General Public License for more + * details. + */ +package org.entando.entando.ent.exception; + +/** + * Generic Entando Runtime Exception + */ +public class EntResourceNotFoundRuntimeException extends EntRuntimeException { + + public EntResourceNotFoundRuntimeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/engine/src/test/java/org/entando/entando/aps/system/init/DatabaseManagerTest.java b/engine/src/test/java/org/entando/entando/aps/system/init/DatabaseManagerTest.java index 46f1338e9c..a53467a616 100644 --- a/engine/src/test/java/org/entando/entando/aps/system/init/DatabaseManagerTest.java +++ b/engine/src/test/java/org/entando/entando/aps/system/init/DatabaseManagerTest.java @@ -310,7 +310,7 @@ void testMigrationStrategyForTenant() throws Exception { try { TenantConfig tenantConfig = Mockito.mock(TenantConfig.class); Mockito.lenient().when(tenantConfig.getDbMigrationStrategy()).thenReturn(Optional.of("disabled")); - Mockito.lenient().when(tenantManager.getConfig("tenant1")).thenReturn(Optional.of(tenantConfig)); + Mockito.lenient().when(tenantManager.getConfigOfReadyTenant("tenant1")).thenReturn(Optional.of(tenantConfig)); Map liquibaseChangeSets = new HashMap<>(); liquibaseChangeSets.put("portDataSource", "changeSetPort.xml"); Component componentConfiguration = Mockito.mock(Component.class); @@ -350,7 +350,7 @@ private void testSkippedMigrationStrategyForTenant(String tenantStrategy) throws try { TenantConfig tenantConfig = Mockito.mock(TenantConfig.class); Mockito.lenient().when(tenantConfig.getDbMigrationStrategy()).thenReturn(Optional.ofNullable(tenantStrategy)); - Mockito.lenient().when(tenantManager.getConfig("tenant1")).thenReturn(Optional.of(tenantConfig)); + Mockito.lenient().when(tenantManager.getConfigOfReadyTenant("tenant1")).thenReturn(Optional.of(tenantConfig)); SystemInstallationReport report = Mockito.mock(SystemInstallationReport.class); databaseManager.installDatabase(Mockito.mock(SystemInstallationReport.class), DatabaseMigrationStrategy.SKIP, Optional.empty()); Mockito.verifyNoInteractions(storageManager); diff --git a/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantManagerTest.java b/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantManagerTest.java index c63c87ff99..038ef17b3c 100644 --- a/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantManagerTest.java +++ b/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantManagerTest.java @@ -108,7 +108,7 @@ void shouldAllOperationWorkFineWithConfigMapsWithCustomFields() throws Throwable Map statuses = data.getTenantStatuses(); data.getTenantStatuses().keySet().stream().forEach(k -> statuses.put(k, TenantStatus.READY)); - Optional otc = tm.getConfig("TE_nant1"); + Optional otc = tm.getConfigOfReadyTenant("TE_nant1"); Assertions.assertThat(otc).isNotEmpty(); TenantConfig tc = otc.get(); Optional customValue1 = tc.getProperty("customField1"); @@ -127,7 +127,7 @@ void shouldAllOperationWorkFineWithCorrectInput() throws Throwable { Map statuses = data.getTenantStatuses(); data.getTenantStatuses().keySet().stream().forEach(k -> statuses.put(k, TenantStatus.READY)); - Optional otc = tm.getConfig("TE_nant1"); + Optional otc = tm.getConfigOfReadyTenant("TE_nant1"); Assertions.assertThat(otc).isNotEmpty(); TenantConfig tc = otc.get(); Assertions.assertThat(tc.isKcEnabled()).isTrue(); @@ -150,7 +150,7 @@ void shouldAllOperationWorkFineWithBadInput() throws Throwable { TenantManager tm = new TenantManager("[\"pippo\"pippo]", new ObjectMapper(), new TenantDataAccessor()); Assertions.catchThrowableOfType(() -> tm.afterPropertiesSet(), JsonMappingException.class); - Optional otc = tm.getConfig("TE_nant1"); + Optional otc = tm.getConfigOfReadyTenant("TE_nant1"); Assertions.assertThat(otc).isEmpty(); otc = tm.getTenantConfigByDomain("tenant2.com"); @@ -158,7 +158,6 @@ void shouldAllOperationWorkFineWithBadInput() throws Throwable { BasicDataSource ds = (BasicDataSource)tm.getDatasource("TE_nant_not_found"); Assertions.assertThat(ds).isNull(); - } @Test @@ -167,7 +166,7 @@ void shouldInitThrowExceptionWithTenantCodeWithValuePrimary() throws Throwable { RuntimeException ex = Assertions.catchThrowableOfType(() -> tm.afterPropertiesSet(), RuntimeException.class); Assertions.assertThat(ex.getMessage()).isEqualTo("You cannot use 'primary' as tenant code"); - Optional otc = tm.getConfig("TE_nant1"); + Optional otc = tm.getConfigOfReadyTenant("TE_nant1"); Assertions.assertThat(otc).isEmpty(); otc = tm.getTenantConfigByDomain("tenant2.com"); @@ -175,24 +174,31 @@ void shouldInitThrowExceptionWithTenantCodeWithValuePrimary() throws Throwable { BasicDataSource ds = (BasicDataSource)tm.getDatasource("TE_nant_not_found"); Assertions.assertThat(ds).isNull(); - } @Test void shouldOperationThrowExceptionWithTenantNotInitiated() throws Throwable { + TenantDataAccessor data = new TenantDataAccessor(); + data.getTenantStatuses().put("tenant2", TenantStatus.READY); TenantManager tm = new TenantManager(TENANT_CONFIGS, new ObjectMapper(), new TenantDataAccessor()); tm.afterPropertiesSet(); - RuntimeException ex = Assertions.catchThrowableOfType(() -> tm.getConfig("TE_nant1"), RuntimeException.class); + RuntimeException ex = Assertions.catchThrowableOfType(() -> tm.getConfigOfReadyTenant("TE_nant1"), RuntimeException.class); Assertions.assertThat(ex.getMessage()).isEqualTo(String.format(errorToCheck,"TE_nant1")); ex = Assertions.catchThrowableOfType(() -> tm.getTenantConfigByDomain("tenant2.com"), RuntimeException.class); Assertions.assertThat(ex.getMessage()).isEqualTo(String.format(errorToCheck,"TE_nant1")); + + Optional otc1 = tm.getConfig("TE_nant1"); + Assertions.assertThat(otc1).isNotEmpty(); + TenantConfig tc = otc1.get(); + Assertions.assertThat(tc.isKcEnabled()).isTrue(); + Assertions.assertThat(tc.getTenantCode()).isEqualTo("TE_nant1"); BasicDataSource ds = (BasicDataSource)tm.getDatasource("TE_nant1"); Assertions.assertThat(ds.getDriverClassName()).isEqualTo("org.postgresql.Driver"); - Optional otc = tm.getConfig("TE_pippo123"); + Optional otc = tm.getConfigOfReadyTenant("TE_pippo123"); Assertions.assertThat(otc).isEmpty(); otc = tm.getTenantConfigByDomain("pippo123.com"); @@ -200,7 +206,6 @@ void shouldOperationThrowExceptionWithTenantNotInitiated() throws Throwable { ds = (BasicDataSource)tm.getDatasource("TE_nant_not_found"); Assertions.assertThat(ds).isNull(); - } } diff --git a/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantServiceTest.java b/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantServiceTest.java index 5c249a7939..da43d84b21 100644 --- a/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantServiceTest.java +++ b/engine/src/test/java/org/entando/entando/aps/system/services/tenants/TenantServiceTest.java @@ -57,7 +57,7 @@ void shouldCurrentTenantWorkFine() { // primary case of CDS disabled apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.empty()); when(storageManager.getResourceUrl("",false)).thenReturn("/cmsresource"); - when(tenantManager.getConfig("primary")).thenReturn(Optional.empty()); + when(tenantManager.getConfigOfReadyTenant("primary")).thenReturn(Optional.empty()); TenantDto primary = tenantService.getCurrentTenant(); Assertions.assertTrue(primary.isPrimary()); @@ -70,7 +70,7 @@ void shouldCurrentTenantWorkFine() { Mockito.reset(tenantManager, storageManager); apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.empty()); when(storageManager.getResourceUrl("",false)).thenReturn("http://cds-primary/public"); - when(tenantManager.getConfig("primary")).thenReturn(Optional.empty()); + when(tenantManager.getConfigOfReadyTenant("primary")).thenReturn(Optional.empty()); TenantDto primaryCds = tenantService.getCurrentTenant(); Assertions.assertTrue(primaryCds.isPrimary()); @@ -84,7 +84,7 @@ void shouldCurrentTenantWorkFine() { apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.of("tenant1")); when(storageManager.getResourceUrl("",false)).thenReturn("http://cds-tenant1/public"); TenantConfig tc = new TenantConfig(Map.of("tenantCode","tenant1")); - when(tenantManager.getConfig("tenant1")).thenReturn(Optional.of(tc)); + when(tenantManager.getConfigOfReadyTenant("tenant1")).thenReturn(Optional.of(tc)); TenantDto tenant = tenantService.getCurrentTenant(); Assertions.assertFalse(tenant.isPrimary()); @@ -102,7 +102,7 @@ void shouldGetTenantWorkFineWithRightInput() { // primary case of CDS disabled apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.empty()); when(storageManager.getResourceUrl("",false)).thenReturn("/cmsresource"); - when(tenantManager.getConfig("primary")).thenReturn(Optional.empty()); + when(tenantManager.getConfigOfReadyTenant("primary")).thenReturn(Optional.empty()); Optional primaryRes = tenantService.getTenant("primary"); Assertions.assertTrue(primaryRes.isPresent()); @@ -116,7 +116,7 @@ void shouldGetTenantWorkFineWithRightInput() { Mockito.reset(tenantManager, storageManager); apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.empty()); when(storageManager.getResourceUrl("",false)).thenReturn("http://cds-primary/public"); - when(tenantManager.getConfig("primary")).thenReturn(Optional.empty()); + when(tenantManager.getConfigOfReadyTenant("primary")).thenReturn(Optional.empty()); Optional primaryCdsRes = tenantService.getTenant("primary"); Assertions.assertTrue(primaryCdsRes.isPresent()); @@ -132,7 +132,7 @@ void shouldGetTenantWorkFineWithRightInput() { apsTenantApplicationUtils.when(() -> ApsTenantApplicationUtils.getTenant()).thenReturn(Optional.of("tenant1")); when(storageManager.getResourceUrl("",false)).thenReturn("http://cds-tenant1/public"); TenantConfig tc = new TenantConfig(Map.of("tenantCode","tenant1")); - when(tenantManager.getConfig("tenant1")).thenReturn(Optional.of(tc)); + when(tenantManager.getConfigOfReadyTenant("tenant1")).thenReturn(Optional.of(tc)); Optional tenantRes = tenantService.getTenant("tenant1"); Assertions.assertTrue(tenantRes.isPresent()); @@ -167,7 +167,7 @@ void shouldGetTenantsWorkFine() { // Cds enabled with 1 tenant TenantConfig tc = new TenantConfig(Map.of("tenantCode","tenant1")); - when(tenantManager.getConfig("tenant1")).thenReturn(Optional.of(tc)); + when(tenantManager.getConfigOfReadyTenant("tenant1")).thenReturn(Optional.of(tc)); when(tenantManager.getCodes()).thenReturn(Arrays.asList("tenant1")); diff --git a/engine/src/test/java/org/entando/entando/aps/util/UrlUtilsTest.java b/engine/src/test/java/org/entando/entando/aps/util/UrlUtilsTest.java index ea2427a506..959500b4ed 100644 --- a/engine/src/test/java/org/entando/entando/aps/util/UrlUtilsTest.java +++ b/engine/src/test/java/org/entando/entando/aps/util/UrlUtilsTest.java @@ -21,13 +21,9 @@ import com.google.common.net.HttpHeaders; import java.net.URI; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import org.entando.entando.aps.util.UrlUtils.EntUrlBuilder; -import org.entando.entando.test_utils.UnitTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -36,11 +32,17 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; -@ExtendWith(MockitoExtension.class) +@ExtendWith({MockitoExtension.class, SystemStubsExtension.class}) class UrlUtilsTest { @Mock private HttpServletRequest requestMock; + + @SystemStub + private EnvironmentVariables environmentVariables; @BeforeEach private void init() throws Exception { @@ -51,33 +53,26 @@ private void init() throws Exception { public void afterAll() throws Exception { Mockito.reset(requestMock); } - + @Test void shouldFetchSchemeWorksFineWithDifferentInputs() throws Exception { - // case1 - Map envsOrig = System.getenv().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - Map envs = (HashMap) envsOrig.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - envs.put("ENTANDO_APP_USE_TLS", "true"); - UnitTestUtils.setEnv(envs); - when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PROTO)).thenReturn(HTTP_SCHEME); - when(requestMock.getScheme()).thenReturn(HTTP_SCHEME); - Assertions.assertEquals(HTTPS_SCHEME, UrlUtils.fetchScheme(requestMock)); - UnitTestUtils.setEnv(envsOrig); - - // case2 + // case0 Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PROTO)).thenReturn(HTTPS_SCHEME); when(requestMock.getScheme()).thenReturn(HTTP_SCHEME); Assertions.assertEquals(HTTPS_SCHEME, UrlUtils.fetchScheme(requestMock)); - // case3 + // case1 Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PROTO)).thenReturn(HTTP_SCHEME); when(requestMock.getScheme()).thenReturn(HTTP_SCHEME); Assertions.assertEquals(HTTP_SCHEME, UrlUtils.fetchScheme(requestMock)); + + // case3 + environmentVariables.set("ENTANDO_APP_USE_TLS", "true"); + when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PROTO)).thenReturn(HTTP_SCHEME); + when(requestMock.getScheme()).thenReturn(HTTP_SCHEME); + Assertions.assertEquals(HTTPS_SCHEME, UrlUtils.fetchScheme(requestMock)); } @@ -114,31 +109,15 @@ void shouldFetchHostWorksFineWithDifferentInputs() throws Exception { @Test void shouldFetchPortWorksFineWithDifferentInputs() throws Exception { - // case 0 - Map envsOrig = System.getenv().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - Map envs = (HashMap) envsOrig.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - envs.put("ENTANDO_APP_ENGINE_EXTERNAL_PORT", "8888"); - UnitTestUtils.setEnv(envs); + // case0 when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn("443"); when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn("test.com:4443"); when(requestMock.getServerPort()).thenReturn(8443); - Optional port = UrlUtils.fetchPort(requestMock); - Assertions.assertTrue(port.isPresent()); - Assertions.assertEquals(8888, port.get()); - UnitTestUtils.setEnv(envsOrig); - - // case1 - when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn("443"); - when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn("test.com:4443"); - when(requestMock.getServerPort()).thenReturn(8443); - port = UrlUtils.fetchPort(requestMock); + Optional port = port = UrlUtils.fetchPort(requestMock); Assertions.assertTrue(port.isPresent()); Assertions.assertEquals(443, port.get()); - // case2-a + // case1-a Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn(null); when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn("test.com:4443"); @@ -148,7 +127,7 @@ void shouldFetchPortWorksFineWithDifferentInputs() throws Exception { Assertions.assertTrue(port.isPresent()); Assertions.assertEquals(4443, port.get()); - // case2-b + // case1-b Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn(null); when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn("test.com:4443"); @@ -158,7 +137,7 @@ void shouldFetchPortWorksFineWithDifferentInputs() throws Exception { Assertions.assertTrue(port.isPresent()); Assertions.assertEquals(8443, port.get()); - // case3 + // case2 Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn(null); when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn(null); @@ -167,7 +146,7 @@ void shouldFetchPortWorksFineWithDifferentInputs() throws Exception { Assertions.assertTrue(port.isPresent()); Assertions.assertEquals(8443, port.get()); - // case4 + // case3 Mockito.reset(requestMock); when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn(null); when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn(null); @@ -175,6 +154,14 @@ void shouldFetchPortWorksFineWithDifferentInputs() throws Exception { port = UrlUtils.fetchPort(requestMock); Assertions.assertTrue(port.isEmpty()); + // case 4 + environmentVariables.set("ENTANDO_APP_ENGINE_EXTERNAL_PORT", "8888"); + when(requestMock.getHeader(HttpHeaders.X_FORWARDED_PORT)).thenReturn("443"); + when(requestMock.getHeader(HttpHeaders.HOST)).thenReturn("test.com:4443"); + when(requestMock.getServerPort()).thenReturn(8443); + port = UrlUtils.fetchPort(requestMock); + Assertions.assertTrue(port.isPresent()); + Assertions.assertEquals(8888, port.get()); } @Test diff --git a/engine/src/test/java/org/entando/entando/test_utils/UnitTestUtils.java b/engine/src/test/java/org/entando/entando/test_utils/UnitTestUtils.java deleted file mode 100644 index 00dd1224af..0000000000 --- a/engine/src/test/java/org/entando/entando/test_utils/UnitTestUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.entando.entando.test_utils; - -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.Map; - -public final class UnitTestUtils { - - private UnitTestUtils() { - } - - /** - * use the received map as source to inject some variables in the environment. - * - * @param envMap the map from which get data to populate the environment variables - * @throws Exception if an error occurr during the injection - */ - public static void setEnv(Map envMap) throws Exception { - - try { - Class processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); - Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment"); - theEnvironmentField.setAccessible(true); - Map env = (Map) theEnvironmentField.get(null); - env.putAll(envMap); - Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField( - "theCaseInsensitiveEnvironment"); - theCaseInsensitiveEnvironmentField.setAccessible(true); - Map cienv = (Map) theCaseInsensitiveEnvironmentField.get(null); - cienv.putAll(envMap); - } catch (NoSuchFieldException e) { - Class[] classes = Collections.class.getDeclaredClasses(); - Map env = System.getenv(); - for (Class cl : classes) { - if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { - Field field = cl.getDeclaredField("m"); - field.setAccessible(true); - Object obj = field.get(env); - Map map = (Map) obj; - map.clear(); - map.putAll(envMap); - } - } - } - } -} - diff --git a/keycloak-plugin/core/pom.xml b/keycloak-plugin/core/pom.xml index 198ef12e9e..2c02fd49b4 100644 --- a/keycloak-plugin/core/pom.xml +++ b/keycloak-plugin/core/pom.xml @@ -83,73 +83,4 @@ - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - 3.0.0-M3 - - ${skipIntegrationTests} - 1 - - - - - integration-test - verify - - - - - - org.jacoco - jacoco-maven-plugin - 0.8.3 - - - **/KeycloakService.* - - - - - prepare-agent - - prepare-agent - - - - report - report - - - - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - ${maven.compiler.source} - ${maven.compiler.target} - - - - \ No newline at end of file diff --git a/keycloak-plugin/pom.xml b/keycloak-plugin/pom.xml index b14e287f94..981b01cfd4 100644 --- a/keycloak-plugin/pom.xml +++ b/keycloak-plugin/pom.xml @@ -5,7 +5,7 @@ app-engine org.entando - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando entando-keycloak-auth diff --git a/keycloak-plugin/src/main/java/org/entando/entando/keycloak/services/KeycloakConfiguration.java b/keycloak-plugin/src/main/java/org/entando/entando/keycloak/services/KeycloakConfiguration.java index aa1f94828f..0c0e098387 100644 --- a/keycloak-plugin/src/main/java/org/entando/entando/keycloak/services/KeycloakConfiguration.java +++ b/keycloak-plugin/src/main/java/org/entando/entando/keycloak/services/KeycloakConfiguration.java @@ -119,6 +119,6 @@ public void setDefaultAuthorizations(String defaultAuthorizations) { private Optional getCurrentConfig() { return ApsTenantApplicationUtils.getTenant() .filter(StringUtils::isNotBlank) - .flatMap(tenantManager::getConfig); + .flatMap(tenantManager::getConfigOfReadyTenant); } } diff --git a/keycloak-plugin/src/test/java/org/entando/entando/keycloak/services/KeycloakConfigurationTest.java b/keycloak-plugin/src/test/java/org/entando/entando/keycloak/services/KeycloakConfigurationTest.java index 6f1ad0f5f2..4603f9e7ab 100644 --- a/keycloak-plugin/src/test/java/org/entando/entando/keycloak/services/KeycloakConfigurationTest.java +++ b/keycloak-plugin/src/test/java/org/entando/entando/keycloak/services/KeycloakConfigurationTest.java @@ -52,7 +52,7 @@ void shouldConfigManageDefaultWhenTenantNotPresent() { // we need this because there is no filter or http request ApsTenantApplicationUtils.setTenant("my-test-tenant"); - Mockito.when(tenantManager.getConfig("my-test-tenant")).thenReturn(Optional.empty()); + Mockito.when(tenantManager.getConfigOfReadyTenant("my-test-tenant")).thenReturn(Optional.empty()); kc.setTenantManager(tenantManager); @@ -90,7 +90,7 @@ void shouldConfigManageTenantsOrThrows(){ ApsTenantApplicationUtils.setTenant("my-test-tenant"); KeycloakConfiguration kc = new KeycloakConfiguration(); TenantConfig tc = new TenantConfig(map); - Mockito.when(tenantManager.getConfig("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); + Mockito.when(tenantManager.getConfigOfReadyTenant("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); kc.setTenantManager(tenantManager); Assertions.assertTrue(kc.isEnabled()); @@ -110,7 +110,7 @@ void shouldConfigManageThrows(){ ApsTenantApplicationUtils.setTenant("my-test-tenant"); KeycloakConfiguration kc = new KeycloakConfiguration(); TenantConfig tc = new TenantConfig(new HashMap<>()); - Mockito.when(tenantManager.getConfig("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); + Mockito.when(tenantManager.getConfigOfReadyTenant("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); kc.setTenantManager(tenantManager); Assertions.assertFalse(kc.isEnabled()); @@ -138,7 +138,7 @@ void shouldConfigManageThrowsErrorWithConfigsEmpty(){ ApsTenantApplicationUtils.setTenant("my-test-tenant"); KeycloakConfiguration kc = new KeycloakConfiguration(); TenantConfig tc = new TenantConfig(map); - Mockito.when(tenantManager.getConfig("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); + Mockito.when(tenantManager.getConfigOfReadyTenant("my-test-tenant")).thenReturn(Optional.ofNullable(tc)); kc.setTenantManager(tenantManager); Assertions.assertFalse(kc.isEnabled()); diff --git a/mail-plugin/pom.xml b/mail-plugin/pom.xml index 9809a34fed..20d2438831 100644 --- a/mail-plugin/pom.xml +++ b/mail-plugin/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpmail org.entando.entando.plugins diff --git a/pom.xml b/pom.xml index 092aa8d469..49e77484fb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,12 @@ org.entando entando-maven-root - 7.2.0-ENG-4226-PR-18 + 7.4.0-ENG-5316-PR-21 org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT pom @@ -64,8 +64,8 @@ HEAD - 11 - 11 + 17 + 17 true @@ -79,14 +79,13 @@ agile jdbc:derby:memory:testPort;create=true jdbc:derby:memory:testServ;create=true - 11 - 11 5.3.27 5.5.7 2.5.2.RELEASE 2.5.31 - 2.11.4 + 2.12.7 + 2.12.7.1 6.0.20.Final 8.9.0 2.6.0 @@ -130,6 +129,7 @@ 3.11.2 5.7.2 1.17.6 + 2.1.3 4.0.1 1.3.2 1.1.3 @@ -153,7 +153,7 @@ 0.8 2.18.0 4.4 - 1.18.20 + 1.18.22 3.3.0 3.0.0-M4 2.5 @@ -1013,6 +1013,12 @@ ${hamcrest-all.version} test + + uk.org.webcompere + system-stubs-jupiter + ${system-stubs-jupiter.version} + test + org.apache.tomcat tomcat-servlet-api @@ -1183,7 +1189,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} com.fasterxml.jackson.module diff --git a/portal-ui/pom.xml b/portal-ui/pom.xml index a2a7729e6e..bb8ca67999 100644 --- a/portal-ui/pom.xml +++ b/portal-ui/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando entando-portal-ui diff --git a/portal-ui/src/main/resources/validation.properties b/portal-ui/src/main/resources/validation.properties new file mode 100644 index 0000000000..9a24c2513a --- /dev/null +++ b/portal-ui/src/main/resources/validation.properties @@ -0,0 +1,35 @@ +# The ESAPI validator does many security checks on input, such as canonicalization +# and whitelist validation. Note that all of these validation rules are applied *after* +# canonicalization. Double-encoded characters (even with different encodings involved, +# are never allowed. +# +# To use: +# +# First set up a pattern below. You can choose any name you want, prefixed by the word +# "Validation." For example: +# Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$ +# +# Then you can validate in your code against the pattern like this: +# ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull); +# Where maxLength and allowNull are set for you needs, respectively. +# +# But note, when you use boolean variants of validation functions, you lose critical +# canonicalization. It is preferable to use the "get" methods (which throw exceptions) and +# and use the returned user input which is in canonical form. Consider the following: +# +# try { +# someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull)); +# +Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$ +#Given the discussion: https://github.com/ESAPI/esapi-java-legacy/issues/374, a better upper-bound for domain name +#was selected as 62. This is slightly under the length in RFC-1035 +Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,62}$ +Validator.Gmail=^[A-Za-z0-9._%'-+]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,62}$ +Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ +#Validator.URL=^(?:ht|f)tp(s?+)\\:\\/\\/[0-9a-zA-Z](?:[-.\\w]*[0-9a-zA-Z])*(?::(?:0-9)*)*(?:\\/?+)(?:[-a-zA-Z0-9\\.\\?\\,\\:\\'\\/\\\\\\+=&%\\$#_]*)?+$ +Validator.URL=^(?:ht|f)tp(?:s?)(?:[:A-Za-z0-9%/#?&.=-]*)$ +Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$ +Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$ +#RegexString here is PURELY for regression testing purposes. NOT for production use. +Validator.RegexString=^[^<>]* +Validator.avaloqLooseSafeString=^[+>= org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpredis org.entando.entando.plugins @@ -103,10 +103,6 @@ - - org.jacoco - jacoco-maven-plugin - org.apache.maven.plugins maven-surefire-plugin diff --git a/seo-plugin/pom.xml b/seo-plugin/pom.xml index 0d9c298c66..cc8061a2fd 100644 --- a/seo-plugin/pom.xml +++ b/seo-plugin/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpseo org.entando.entando.plugins diff --git a/solr-plugin/docker-compose.yaml b/solr-plugin/docker-compose.yaml deleted file mode 100644 index fc51119812..0000000000 --- a/solr-plugin/docker-compose.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: '2.1' - -services: - solr: - container_name: solr_test - image: "solr:latest" - ports: - - "8984:8983" - command: - - solr-precreate - - entando diff --git a/solr-plugin/pom.xml b/solr-plugin/pom.xml index d81e183ea4..bf2759a991 100644 --- a/solr-plugin/pom.xml +++ b/solr-plugin/pom.xml @@ -5,7 +5,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpsolr org.entando.entando.plugins @@ -156,6 +156,11 @@ mockito-junit-jupiter test + + uk.org.webcompere + system-stubs-jupiter + test + org.springframework spring-test diff --git a/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrProxyTenantAware.java b/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrProxyTenantAware.java index 0c97cabb94..1891140111 100644 --- a/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrProxyTenantAware.java +++ b/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrProxyTenantAware.java @@ -127,7 +127,7 @@ public String getSolrAddress() { private String getTenantParameter(String paramName, String defaultValue) { return ApsTenantApplicationUtils.getTenant() - .flatMap(tenantManager::getConfig) + .flatMap(tenantManager::getConfigOfReadyTenant) .flatMap(tenantConfig -> tenantConfig.getProperty(paramName)) .orElse(defaultValue); } diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrBaseTestCase.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrBaseTestCase.java new file mode 100644 index 0000000000..5ba0ff8c2a --- /dev/null +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrBaseTestCase.java @@ -0,0 +1,60 @@ +/* + * Copyright 2023-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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 Lesser General Public License for more + * details. + */ +package org.entando.entando.plugins.jpsolr; + +import com.agiletec.aps.BaseTestCase; +import javax.servlet.ServletContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.FileSystemResourceLoader; +import org.springframework.mock.web.MockServletContext; +import org.testcontainers.containers.GenericContainer; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; + +@ExtendWith(SystemStubsExtension.class) +public abstract class SolrBaseTestCase { + + private static GenericContainer solrContainer; + + private static ApplicationContext applicationContext; + + @SystemStub + private static EnvironmentVariables environmentVariables; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static void setApplicationContext(ApplicationContext applicationContextToSet) { + applicationContext = applicationContextToSet; + } + + @BeforeAll + public static void startUp() throws Exception { + solrContainer = SolrTestUtils.startContainer(solrContainer, environmentVariables); + ServletContext srvCtx = new MockServletContext("", new FileSystemResourceLoader()); + applicationContext = new CustomConfigTestUtils().createApplicationContext(srvCtx); + setApplicationContext(applicationContext); + } + + @AfterAll + public static void tearDown() throws Exception { + BaseTestCase.tearDown(); + } + +} diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestExtension.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestExtension.java deleted file mode 100644 index 5aa0c6db9d..0000000000 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestExtension.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.entando.entando.plugins.jpsolr; - -import java.lang.reflect.Field; -import java.util.Map; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpSolrClient; -import org.apache.solr.client.solrj.request.schema.SchemaRequest; -import org.apache.solr.common.SolrException; -import org.entando.entando.aps.system.services.searchengine.SolrEnvironmentVariables; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.testcontainers.containers.GenericContainer; - -public class SolrTestExtension implements BeforeAllCallback { - - public static final String RECREATE_CORE = "RECREATE_CORE"; - - private static final int SOLR_PORT = 8983; - private static final String SOLR_IMAGE = "solr:9"; - private static final String SOLR_CORE = "entando"; - - private static GenericContainer solrContainer; - - @Override - public void beforeAll(ExtensionContext extensionContext) throws Exception { - if (solrContainer == null) { - solrContainer = new GenericContainer(SOLR_IMAGE).withExposedPorts(SOLR_PORT) - .withCommand("solr-precreate", SOLR_CORE); - solrContainer.start(); - - updateEnv("SOLR_ADDRESS", "http://localhost:" + solrContainer.getMappedPort(SOLR_PORT) + "/solr"); - } - - if (extensionContext.getTags().contains(RECREATE_CORE)) { - solrContainer.execInContainer("bin/solr", "delete", "-c", SOLR_CORE); - solrContainer.execInContainer("bin/solr", "create_core", "-c", SOLR_CORE); - } - - waitSolrReady(); - } - - /** - * Sometimes Solr is not ready even if the container is ready. This method attempts to read the schema fields. - */ - private void waitSolrReady() throws Exception { - int attempt = 0; - do { - SolrClient solrClient = new HttpSolrClient.Builder(SolrEnvironmentVariables.solrAddress()) - .withConnectionTimeout(10000) - .withSocketTimeout(60000) - .build(); - try { - solrClient.request(new SchemaRequest.Fields(), SolrEnvironmentVariables.solrCore()); - return; - } catch (SolrServerException | SolrException ex) { - attempt++; - } finally { - solrClient.close(); - } - } while (attempt < 10); - } - - /** - * Some tests that use this extension start instances of NotifyingThread where we need to override the SOLR_ADDRESS - * value. Unfortunately Mockito.mockStatic doesn't work in secondary threads, so we can't mock - * SolrEnvironmentVariables static methods as done in RedisTestExtension. The following method is a workaround that - * manipulates the env map directly. - */ - private static void updateEnv(String name, String val) throws Exception { - Map env = System.getenv(); - Field field = env.getClass().getDeclaredField("m"); - field.setAccessible(true); - ((Map) field.get(env)).put(name, val); - } -} diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestUtils.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestUtils.java index b8fef61e64..4b505e13b7 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestUtils.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/SolrTestUtils.java @@ -14,11 +14,23 @@ package org.entando.entando.plugins.jpsolr; import com.agiletec.aps.system.common.notify.NotifyManager; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.request.schema.SchemaRequest; +import org.apache.solr.common.SolrException; +import org.entando.entando.aps.system.services.searchengine.SolrEnvironmentVariables; +import org.testcontainers.containers.GenericContainer; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; /** * @author E.Santoboni */ public class SolrTestUtils { + + private static final int SOLR_PORT = 8983; + private static final String SOLR_IMAGE = "solr:9"; + private static final String SOLR_CORE = "entando"; public static void waitNotifyingThread() throws InterruptedException { waitThreads(NotifyManager.NOTIFYING_THREAD_NAME); @@ -35,5 +47,41 @@ public static void waitThreads(String threadNamePrefix) throws InterruptedExcept } } } + + public static GenericContainer startContainer(GenericContainer solrContainer, EnvironmentVariables environmentVariables) throws Exception { + if (solrContainer == null) { + solrContainer = new GenericContainer(SOLR_IMAGE).withExposedPorts(SOLR_PORT) + .withCommand("solr-precreate", SOLR_CORE); + solrContainer.start(); + environmentVariables.set("SOLR_ADDRESS", "http://localhost:" + solrContainer.getMappedPort(SOLR_PORT) + "/solr"); + } + waitSolrReady(); + return solrContainer; + } + + /** + * Sometimes Solr is not ready even if the container is ready. This method attempts to read the schema fields. + */ + private static void waitSolrReady() throws Exception { + int attempt = 0; + do { + SolrClient solrClient = new HttpSolrClient.Builder(SolrEnvironmentVariables.solrAddress()) + .withConnectionTimeout(10000) + .withSocketTimeout(60000) + .build(); + try { + solrClient.request(new SchemaRequest.Fields(), SolrEnvironmentVariables.solrCore()); + return; + } catch (SolrServerException | SolrException ex) { + attempt++; + } finally { + solrClient.close(); + } + } while (attempt < 10); + } + + + + } diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/AdvContentSearchTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/AdvContentSearchTest.java index 2a760c4a04..e899956ca9 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/AdvContentSearchTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/AdvContentSearchTest.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.agiletec.aps.BaseTestCase; import java.util.ArrayList; import java.util.List; import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; @@ -34,27 +33,18 @@ import java.util.Collection; import java.util.Date; import java.util.stream.Collectors; -import javax.servlet.ServletContext; import org.entando.entando.aps.system.services.searchengine.FacetedContentsResult; import org.entando.entando.aps.system.services.searchengine.SearchEngineFilter; -import org.entando.entando.plugins.jpsolr.CustomConfigTestUtils; -import org.entando.entando.plugins.jpsolr.SolrTestExtension; +import org.entando.entando.plugins.jpsolr.SolrBaseTestCase; import org.entando.entando.plugins.jpsolr.SolrTestUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.context.ApplicationContext; -import org.springframework.core.io.FileSystemResourceLoader; -import org.springframework.mock.web.MockServletContext; /** * Rewriting of some default tests for content manager * @author E.Santoboni */ -@ExtendWith(SolrTestExtension.class) -class AdvContentSearchTest { +class AdvContentSearchTest extends SolrBaseTestCase { private IContentManager contentManager = null; private ISolrSearchEngineManager searchEngineManager = null; @@ -62,28 +52,6 @@ class AdvContentSearchTest { private List allowedGroup = new ArrayList<>(); - private static ApplicationContext applicationContext; - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - public static void setApplicationContext(ApplicationContext applicationContext) { - AdvContentSearchTest.applicationContext = applicationContext; - } - - @BeforeAll - public static void startUp() throws Exception { - ServletContext srvCtx = new MockServletContext("", new FileSystemResourceLoader()); - applicationContext = new CustomConfigTestUtils().createApplicationContext(srvCtx); - setApplicationContext(applicationContext); - } - - @AfterAll - public static void tearDown() throws Exception { - BaseTestCase.tearDown(); - } - @BeforeEach protected void init() throws Exception { try { diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/FacetSearchEngineManagerIntegrationTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/FacetSearchEngineManagerIntegrationTest.java index eb0e6a306e..9a4e2f7ce0 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/FacetSearchEngineManagerIntegrationTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/FacetSearchEngineManagerIntegrationTest.java @@ -13,13 +13,14 @@ */ package org.entando.entando.plugins.jpsolr.aps.system.solr; +import org.entando.entando.plugins.jpsolr.SolrBaseTestCase; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.agiletec.aps.BaseTestCase; import com.agiletec.aps.system.common.FieldSearchFilter; import com.agiletec.aps.system.common.entity.model.attribute.ITextAttribute; import com.agiletec.aps.system.services.category.Category; @@ -34,52 +35,18 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import javax.servlet.ServletContext; import org.entando.entando.aps.system.services.searchengine.FacetedContentsResult; import org.entando.entando.aps.system.services.searchengine.SearchEngineFilter; -import org.entando.entando.plugins.jpsolr.CustomConfigTestUtils; -import org.entando.entando.plugins.jpsolr.SolrTestExtension; import org.entando.entando.plugins.jpsolr.SolrTestUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.context.ApplicationContext; -import org.springframework.core.io.FileSystemResourceLoader; -import org.springframework.mock.web.MockServletContext; -/** - * @author eu - */ -@ExtendWith(SolrTestExtension.class) -class FacetSearchEngineManagerIntegrationTest { +class FacetSearchEngineManagerIntegrationTest extends SolrBaseTestCase { private IContentManager contentManager = null; private ICmsSearchEngineManager searchEngineManager = null; private ICategoryManager categoryManager; - private static ApplicationContext applicationContext; - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - public static void setApplicationContext(ApplicationContext applicationContext) { - FacetSearchEngineManagerIntegrationTest.applicationContext = applicationContext; - } - - @BeforeAll - public static void startUp() throws Exception { - ServletContext srvCtx = new MockServletContext("", new FileSystemResourceLoader()); - applicationContext = new CustomConfigTestUtils().createApplicationContext(srvCtx); - setApplicationContext(applicationContext); - } - - @AfterAll - public static void tearDown() throws Exception { - BaseTestCase.tearDown(); - } @BeforeEach protected void init() throws Exception { @@ -88,7 +55,7 @@ protected void init() throws Exception { this.categoryManager = getApplicationContext().getBean(ICategoryManager.class); ((ISolrSearchEngineManager) this.searchEngineManager).refreshCmsFields(); } - + @Test void testSearchAllContents() throws Exception { Thread thread = this.searchEngineManager.startReloadContentsReferences(); diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrResourcesManagerTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrResourcesManagerTest.java index f59a475681..a35613b752 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrResourcesManagerTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrResourcesManagerTest.java @@ -79,6 +79,6 @@ private void mockTenantConfig() { TenantConfig tenantConfig = Mockito.mock(TenantConfig.class); Mockito.when(tenantConfig.getProperty("solrAddress")).thenReturn(Optional.of("http://localhost:9999/solr")); Mockito.when(tenantConfig.getProperty("solrCore")).thenReturn(Optional.of(TENANT_1)); - Mockito.when(tenantManager.getConfig(TENANT_1)).thenReturn(Optional.of(tenantConfig)); + Mockito.when(tenantManager.getConfigOfReadyTenant(TENANT_1)).thenReturn(Optional.of(tenantConfig)); } } diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrSearchEngineManagerIntegrationTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrSearchEngineManagerIntegrationTest.java index d07617300e..a309450459 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrSearchEngineManagerIntegrationTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/aps/system/solr/SolrSearchEngineManagerIntegrationTest.java @@ -52,13 +52,11 @@ import java.util.Set; import java.util.function.BiConsumer; import java.util.stream.IntStream; -import javax.servlet.ServletContext; import org.entando.entando.aps.system.services.searchengine.FacetedContentsResult; import org.entando.entando.aps.system.services.searchengine.SearchEngineFilter; import org.entando.entando.aps.system.services.searchengine.SearchEngineFilter.TextSearchOption; import org.entando.entando.ent.exception.EntRuntimeException; -import org.entando.entando.plugins.jpsolr.CustomConfigTestUtils; -import org.entando.entando.plugins.jpsolr.SolrTestExtension; +import org.entando.entando.plugins.jpsolr.SolrBaseTestCase; import org.entando.entando.plugins.jpsolr.SolrTestUtils; import org.entando.entando.plugins.jpsolr.aps.system.solr.model.SolrSearchEngineFilter; import org.junit.jupiter.api.AfterAll; @@ -67,18 +65,13 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.context.ApplicationContext; -import org.springframework.core.io.FileSystemResourceLoader; -import org.springframework.mock.web.MockServletContext; /** * Test del servizio detentore delle operazioni sul motore di ricerca. * * @author E.Santoboni */ -@ExtendWith(SolrTestExtension.class) -class SolrSearchEngineManagerIntegrationTest { +class SolrSearchEngineManagerIntegrationTest extends SolrBaseTestCase { private static final String ROLE_FOR_TEST = "jacmstest:date"; @@ -87,22 +80,19 @@ class SolrSearchEngineManagerIntegrationTest { private ISolrSearchEngineManager searchEngineManager = null; private ICategoryManager categoryManager; - private static ApplicationContext applicationContext; - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - public static void setApplicationContext(ApplicationContext applicationContext) { - SolrSearchEngineManagerIntegrationTest.applicationContext = applicationContext; - } + //private static ApplicationContext applicationContext; @BeforeAll public static void startUp() throws Exception { + /* ServletContext srvCtx = new MockServletContext("", new FileSystemResourceLoader()); ApplicationContext applicationContext = new CustomConfigTestUtils().createApplicationContext(srvCtx); setApplicationContext(applicationContext); - IContentManager contentManager = applicationContext.getBean(IContentManager.class); + */ + SolrBaseTestCase.startUp(); + + + IContentManager contentManager = getApplicationContext().getBean(IContentManager.class); AttributeRole role = contentManager.getAttributeRole(ROLE_FOR_TEST); Assertions.assertNotNull(role); Content artType = contentManager.createContentType("ART"); @@ -139,7 +129,7 @@ public static void startUp() throws Exception { dateAttrEnv.setRoles(new String[]{ROLE_FOR_TEST}); ((IEntityTypesConfigurer) contentManager).updateEntityPrototype(evnType); } - ISolrSearchEngineManager solrSearchEngineManager = applicationContext.getBean(ISolrSearchEngineManager.class); + ISolrSearchEngineManager solrSearchEngineManager = getApplicationContext().getBean(ISolrSearchEngineManager.class); solrSearchEngineManager.refreshCmsFields(); } @@ -169,7 +159,7 @@ public void accept(List attributes, String name) { dateAttrEnv.setRoles(new String[0]); ((IEntityTypesConfigurer) contentManager).updateEntityPrototype(evnType); } finally { - BaseTestCase.tearDown(); + SolrBaseTestCase.tearDown(); } } diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/AbstractControllerIntegrationTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/AbstractControllerIntegrationTest.java index 347c1ebf68..0c88b3b183 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/AbstractControllerIntegrationTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/AbstractControllerIntegrationTest.java @@ -21,6 +21,7 @@ import com.agiletec.aps.system.services.user.UserDetails; import org.entando.entando.TestEntandoJndiUtils; import org.entando.entando.aps.system.services.oauth2.IApiOAuth2TokenManager; +import org.entando.entando.plugins.jpsolr.SolrTestUtils; import org.entando.entando.web.AuthRequestBuilder; import org.entando.entando.web.common.interceptor.EntandoOauth2Interceptor; import org.entando.entando.web.utils.OAuth2TestUtils; @@ -39,8 +40,12 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.CorsFilter; +import org.testcontainers.containers.GenericContainer; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; -@ExtendWith(SpringExtension.class) +@ExtendWith({SystemStubsExtension.class, SpringExtension.class}) @ContextConfiguration(locations = { "classpath*:spring/testpropertyPlaceholder.xml", "classpath*:spring/baseSystemConfig.xml", @@ -53,7 +58,7 @@ "classpath*:spring/web/**.xml",}) @WebAppConfiguration(value = "") public abstract class AbstractControllerIntegrationTest { - + protected MockMvc mockMvc; private String accessToken; @@ -76,9 +81,15 @@ public abstract class AbstractControllerIntegrationTest { @Autowired @InjectMocks protected EntandoOauth2Interceptor entandoOauth2Interceptor; + + private static GenericContainer solrContainer; + @SystemStub + private static EnvironmentVariables environmentVariables; + @BeforeAll public static void setup() throws Exception { + solrContainer = SolrTestUtils.startContainer(solrContainer, environmentVariables); TestEntandoJndiUtils.setupJndi(); } diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/AdvContentSearchControllerTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/AdvContentSearchControllerTest.java index 1cc7a37ff1..982ee432c1 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/AdvContentSearchControllerTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/AdvContentSearchControllerTest.java @@ -37,7 +37,6 @@ import java.util.List; import java.util.Map; import org.entando.entando.plugins.jacms.aps.system.services.content.IContentService; -import org.entando.entando.plugins.jpsolr.SolrTestExtension; import org.entando.entando.plugins.jpsolr.aps.system.solr.ISolrSearchEngineManager; import org.entando.entando.plugins.jpsolr.web.AbstractControllerIntegrationTest; import org.entando.entando.web.utils.OAuth2TestUtils; @@ -47,7 +46,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; @@ -55,7 +53,6 @@ /** * @author E.Santoboni */ -@ExtendWith(SolrTestExtension.class) class AdvContentSearchControllerTest extends AbstractControllerIntegrationTest { @Autowired diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByDoubleFiltersControllerTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByDoubleFiltersControllerTest.java index 30c7329169..49616cbb5b 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByDoubleFiltersControllerTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByDoubleFiltersControllerTest.java @@ -36,7 +36,6 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.entando.entando.plugins.jpsolr.SolrTestExtension; import org.entando.entando.plugins.jpsolr.aps.system.solr.ISolrSearchEngineManager; import org.entando.entando.plugins.jpsolr.web.AbstractControllerIntegrationTest; import org.entando.entando.web.utils.OAuth2TestUtils; @@ -45,14 +44,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; /** * @author E.Santoboni */ -@ExtendWith(SolrTestExtension.class) public class SearchByDoubleFiltersControllerTest extends AbstractControllerIntegrationTest { private static final String TEXT_FOR_TEST = "Entando is the leading modular application platform for building enterprise applications on Kubernetes"; diff --git a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByResourceControllerTest.java b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByResourceControllerTest.java index e26825251b..8d4ed58be5 100644 --- a/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByResourceControllerTest.java +++ b/solr-plugin/src/test/java/org/entando/entando/plugins/jpsolr/web/content/SearchByResourceControllerTest.java @@ -58,11 +58,6 @@ public class SearchByResourceControllerTest extends AbstractControllerIntegratio @Autowired private IResourceManager resourceManager; - @BeforeAll - public static void setup() throws Exception { - AbstractControllerIntegrationTest.setup(); - } - @Override @BeforeEach public void setUp() throws Exception { diff --git a/versioning-plugin/pom.xml b/versioning-plugin/pom.xml index 4d5c35c90c..977ea36b77 100644 --- a/versioning-plugin/pom.xml +++ b/versioning-plugin/pom.xml @@ -4,7 +4,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT entando-plugin-jpversioning org.entando.entando.plugins diff --git a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TrashedResourceManager.java b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TrashedResourceManager.java index 750c90e0e3..1442e32b2c 100644 --- a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TrashedResourceManager.java +++ b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TrashedResourceManager.java @@ -21,7 +21,6 @@ */ package com.agiletec.plugins.jpversioning.aps.system.services.resource; -import com.agiletec.aps.util.ApsTenantApplicationUtils; import java.io.File; import java.io.InputStream; import java.io.StringReader; @@ -31,15 +30,13 @@ import java.util.List; import java.util.Map; -import java.util.Optional; import javax.xml.parsers.SAXParser; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.entando.entando.aps.system.services.storage.IStorageManager; -import org.entando.entando.aps.system.services.tenants.ITenantManager; -import org.entando.entando.aps.system.services.tenants.RefreshableBeanTenantAware; import org.entando.entando.ent.exception.EntException; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; import org.entando.entando.ent.util.EntLogging.EntLogger; import org.entando.entando.ent.util.EntLogging.EntLogFactory; import org.entando.entando.ent.util.EntSafeXmlUtils; @@ -202,7 +199,8 @@ public void addTrashedResource(ResourceInterface resource) throws EntException { Iterator iter = instancesMap.values().iterator(); while (iter.hasNext()) { ResourceInstance resourceInstance = iter.next(); - InputStream is = resource.getResourceStream(resourceInstance); + InputStream is = getResourceStream(resource, resourceInstance); + if (null != is) { String path = folder + resourceInstance.getFileName(); paths.add(path); @@ -212,7 +210,7 @@ public void addTrashedResource(ResourceInterface resource) throws EntException { } else { AbstractMonoInstanceResource monoResource = (AbstractMonoInstanceResource) resource; ResourceInstance resourceInstance = monoResource.getInstance(); - InputStream is = resource.getResourceStream(resourceInstance); + InputStream is = getResourceStream(resource, resourceInstance); if (null != is) { String path = folder + resourceInstance.getFileName(); paths.add(path); @@ -230,6 +228,16 @@ public void addTrashedResource(ResourceInterface resource) throws EntException { } } + private static InputStream getResourceStream(ResourceInterface resource, ResourceInstance resourceInstance) { + InputStream is = null; + try { + is = resource.getResourceStream(resourceInstance); + } catch (EntResourceNotFoundRuntimeException e) { + _logger.warn("removal of a resource not in the CDS"); + } + return is; + } + /** * Verifica l'esistenza della directory di destinazione dei file */ diff --git a/versioning-plugin/src/test/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TestTrashedResourceManager.java b/versioning-plugin/src/test/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TestTrashedResourceManager.java index 6706d507a5..406d725400 100644 --- a/versioning-plugin/src/test/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TestTrashedResourceManager.java +++ b/versioning-plugin/src/test/java/com/agiletec/plugins/jpversioning/aps/system/services/resource/TestTrashedResourceManager.java @@ -21,15 +21,24 @@ */ package com.agiletec.plugins.jpversioning.aps.system.services.resource; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; import com.agiletec.aps.BaseTestCase; +import com.agiletec.plugins.jacms.aps.system.services.resource.model.AbstractMonoInstanceResource; +import com.agiletec.plugins.jacms.aps.system.services.resource.model.AbstractMultiInstanceResource; +import com.agiletec.plugins.jacms.aps.system.services.resource.model.ResourceInstance; import java.io.File; import java.util.ArrayList; import java.util.List; import com.agiletec.aps.system.SystemConstants; +import java.util.Map; +import org.entando.entando.aps.system.services.storage.IStorageManager; +import org.entando.entando.ent.exception.EntResourceNotFoundRuntimeException; import org.entando.entando.ent.exception.EntException; import com.agiletec.aps.system.services.category.Category; import com.agiletec.aps.system.services.category.ICategoryManager; @@ -47,123 +56,129 @@ * @author G.Cocco */ public class TestTrashedResourceManager extends BaseTestCase { - - @Test - void testSearchTrashedResourceIds() throws EntException { - String resourceTypeCode = null; - String text = null; - List allowedGroups = new ArrayList(); - List resourceIds = this._trashedResourceManager.searchTrashedResourceIds(resourceTypeCode, text, allowedGroups); - assertNotNull(resourceIds); - assertEquals(6, resourceIds.size()); - assertEquals("67", resourceIds.get(0)); - assertEquals("68", resourceIds.get(1)); - - resourceTypeCode = "Image"; - text = "qq"; - allowedGroups = new ArrayList(); - allowedGroups.add("customers"); - resourceIds = this._trashedResourceManager.searchTrashedResourceIds(resourceTypeCode, text, allowedGroups); - assertNotNull(resourceIds); - assertEquals(1, resourceIds.size()); - assertEquals("69", resourceIds.get(0)); - } - - @Test - void testAdd_Trash_LoadFromTrash_RemoveFromTrash() throws Throwable { - String mainGroup = Group.FREE_GROUP_NAME; - String resDescrToAdd = "Versioning test 1"; - String resourceType = "Image"; - String categoryCodeToAdd = "resCat1"; - List groups = new ArrayList(); - groups.add(Group.FREE_GROUP_NAME); - try { - ResourceDataBean bean = this.getMockResource(resourceType, mainGroup, resDescrToAdd, categoryCodeToAdd); - - // add the resource - this._resourceManager.addResource(bean); - List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(1, resources.size()); - - ResourceInterface resource = _resourceManager.loadResource(resources.get(0)); - assertNotNull(resource); - - // move into the trash - _resourceManager.deleteResource(resource); - - // load from Trash - ResourceInterface resourceLoadedFromTrash = this._trashedResourceManager.loadTrashedResource(resource.getId()); - assertNotNull(resourceLoadedFromTrash); - assertEquals(resDescrToAdd, resourceLoadedFromTrash.getDescr()); - assertEquals(mainGroup, resourceLoadedFromTrash.getMainGroup()); - assertEquals(resourceType, resourceLoadedFromTrash.getType()); - - // del from trash - this._trashedResourceManager.removeFromTrash(resource.getId()); - } catch (Throwable t) { - List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - if (null != resources && resources.size() > 0) { - for (int i = 0; i < resources.size(); i++) { - String id = resources.get(i); - this._trashedResourceManager.removeFromTrash(id); - ResourceInterface resource = this._resourceManager.loadResource(id); - this._resourceManager.deleteResource(resource); - } - } - throw t; - } - } - - @Test - void testAdd_Trash_RestoreResource_DeleteFromArchive() throws Throwable { - String mainGroup = Group.FREE_GROUP_NAME; - String resDescrToAdd = "Versioning test 2"; - String resourceType = "Image"; - String categoryCodeToAdd = "resCat1"; - ResourceDataBean bean = this.getMockResource(resourceType, mainGroup, resDescrToAdd, categoryCodeToAdd); - List groups = new ArrayList(); - groups.add(Group.FREE_GROUP_NAME); - try { - // add the resource - this._resourceManager.addResource(bean); - List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(1, resources.size()); - - String resourceId = resources.get(0); - ResourceInterface resource = this._resourceManager.loadResource(resourceId); - assertNotNull(resource); - - // move into the trash - this._resourceManager.deleteResource(resource); - resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(0, resources.size()); - - // restore from Trash - this._trashedResourceManager.restoreResource(resourceId); - resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(1, resources.size()); - resource = this._resourceManager.loadResource(resources.get(0)); - // delete from archive and from trash - _resourceManager.deleteResource(resource); - resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(0, resources.size()); - this._trashedResourceManager.removeFromTrash(resource.getId()); - } catch (Throwable t) { - List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - if (null != resources && resources.size() > 0) { - for (int i = 0; i < resources.size(); i++) { - String id = resources.get(i); - this._trashedResourceManager.removeFromTrash(id); - ResourceInterface resource = this._resourceManager.loadResource(id); - this._resourceManager.deleteResource(resource); - } - } - throw t; - } - } @Test - void testRestoreImageFromTrashProtectedResource() throws Throwable { + void testSearchTrashedResourceIds() throws EntException { + String resourceTypeCode = null; + String text = null; + List allowedGroups = new ArrayList(); + List resourceIds = this._trashedResourceManager.searchTrashedResourceIds(resourceTypeCode, text, + allowedGroups); + assertNotNull(resourceIds); + assertEquals(6, resourceIds.size()); + assertEquals("67", resourceIds.get(0)); + assertEquals("68", resourceIds.get(1)); + + resourceTypeCode = "Image"; + text = "qq"; + allowedGroups = new ArrayList(); + allowedGroups.add("customers"); + resourceIds = this._trashedResourceManager.searchTrashedResourceIds(resourceTypeCode, text, allowedGroups); + assertNotNull(resourceIds); + assertEquals(1, resourceIds.size()); + assertEquals("69", resourceIds.get(0)); + } + + @Test + void testAdd_Trash_LoadFromTrash_RemoveFromTrash() throws Throwable { + String mainGroup = Group.FREE_GROUP_NAME; + String resDescrToAdd = "Versioning test 1"; + String resourceType = "Image"; + String categoryCodeToAdd = "resCat1"; + List groups = new ArrayList(); + groups.add(Group.FREE_GROUP_NAME); + try { + ResourceDataBean bean = this.getMockResource(resourceType, mainGroup, resDescrToAdd, categoryCodeToAdd); + + // add the resource + this._resourceManager.addResource(bean); + List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, + categoryCodeToAdd, groups); + assertEquals(1, resources.size()); + + ResourceInterface resource = _resourceManager.loadResource(resources.get(0)); + assertNotNull(resource); + + // move into the trash + _resourceManager.deleteResource(resource); + + // load from Trash + ResourceInterface resourceLoadedFromTrash = this._trashedResourceManager.loadTrashedResource( + resource.getId()); + assertNotNull(resourceLoadedFromTrash); + assertEquals(resDescrToAdd, resourceLoadedFromTrash.getDescr()); + assertEquals(mainGroup, resourceLoadedFromTrash.getMainGroup()); + assertEquals(resourceType, resourceLoadedFromTrash.getType()); + + // del from trash + this._trashedResourceManager.removeFromTrash(resource.getId()); + } catch (Throwable t) { + List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, + categoryCodeToAdd, groups); + if (null != resources && resources.size() > 0) { + for (int i = 0; i < resources.size(); i++) { + String id = resources.get(i); + this._trashedResourceManager.removeFromTrash(id); + ResourceInterface resource = this._resourceManager.loadResource(id); + this._resourceManager.deleteResource(resource); + } + } + throw t; + } + } + + @Test + void testAdd_Trash_RestoreResource_DeleteFromArchive() throws Throwable { + String mainGroup = Group.FREE_GROUP_NAME; + String resDescrToAdd = "Versioning test 2"; + String resourceType = "Image"; + String categoryCodeToAdd = "resCat1"; + ResourceDataBean bean = this.getMockResource(resourceType, mainGroup, resDescrToAdd, categoryCodeToAdd); + List groups = new ArrayList(); + groups.add(Group.FREE_GROUP_NAME); + try { + // add the resource + this._resourceManager.addResource(bean); + List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, + categoryCodeToAdd, groups); + assertEquals(1, resources.size()); + + String resourceId = resources.get(0); + ResourceInterface resource = this._resourceManager.loadResource(resourceId); + assertNotNull(resource); + + // move into the trash + this._resourceManager.deleteResource(resource); + resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(0, resources.size()); + + // restore from Trash + this._trashedResourceManager.restoreResource(resourceId); + resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(1, resources.size()); + resource = this._resourceManager.loadResource(resources.get(0)); + // delete from archive and from trash + _resourceManager.deleteResource(resource); + resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(0, resources.size()); + this._trashedResourceManager.removeFromTrash(resource.getId()); + } catch (Throwable t) { + List resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, + categoryCodeToAdd, groups); + if (null != resources && resources.size() > 0) { + for (int i = 0; i < resources.size(); i++) { + String id = resources.get(i); + this._trashedResourceManager.removeFromTrash(id); + ResourceInterface resource = this._resourceManager.loadResource(id); + this._resourceManager.deleteResource(resource); + } + } + throw t; + } + } + + @Test + void testRestoreImageFromTrashProtectedResource() throws Throwable { String mainGroup = Group.ADMINS_GROUP_NAME; String resDescrToAdd = "Test protected resource"; String resourceType = "Image"; @@ -215,103 +230,140 @@ void testRestoreImageFromTrashProtectedResource() throws Throwable { } } - @Test - void testRestoreAttachmentFromTrashProtectedResource() throws Throwable { - String mainGroup = Group.ADMINS_GROUP_NAME; - String resDescrToAdd = "Test protected resource Attachment"; - String resourceType = "Attach"; - String categoryCodeToAdd = "resCat1"; - ResourceDataBean bean = this.getMockResourceAttachment(mainGroup, resDescrToAdd, categoryCodeToAdd); - List groups = new ArrayList<>(); - groups.add(Group.ADMINS_GROUP_NAME); - try { - // add the resource - this._resourceManager.addResource(bean); - List resources = this._resourceManager - .searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(1, resources.size()); - - String resourceId = resources.get(0); - ResourceInterface resource = this._resourceManager.loadResource(resourceId); - assertNotNull(resource); - - // move into the trash - this._resourceManager.deleteResource(resource); - resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(0, resources.size()); - - // restore from Trash - this._trashedResourceManager.restoreResource(resourceId); - resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(1, resources.size()); - resource = this._resourceManager.loadResource(resources.get(0)); - - assertNotNull(resource.getResourceStream()); - assertEquals(Group.ADMINS_GROUP_NAME, resource.getMainGroup()); - // delete from archive and from trash - _resourceManager.deleteResource(resource); - resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - assertEquals(0, resources.size()); - this._trashedResourceManager.removeFromTrash(resource.getId()); - } catch (Throwable t) { - List resources = this._resourceManager - .searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); - if (null != resources && resources.size() > 0) { - for (int i = 0; i < resources.size(); i++) { - String id = resources.get(i); - this._trashedResourceManager.removeFromTrash(id); - ResourceInterface resource = this._resourceManager.loadResource(id); - this._resourceManager.deleteResource(resource); - } - } - throw t; - } - } - - private ResourceDataBean getMockResource(String resourceType, String mainGroup, String resDescrToAdd, String categoryCodeToAdd) { - File file = new File("target/test/entando_logo.jpg"); - BaseResourceDataBean bean = new BaseResourceDataBean(file); - bean.setDescr(resDescrToAdd); - bean.setMainGroup(mainGroup); - bean.setResourceType(resourceType); - bean.setMimeType("image/jpeg"); - List categories = new ArrayList(); - ICategoryManager catManager = - (ICategoryManager) this.getService(SystemConstants.CATEGORY_MANAGER); - Category cat = catManager.getCategory(categoryCodeToAdd); - categories.add(cat); - bean.setCategories(categories); - return bean; + @Test + void testRestoreAttachmentFromTrashProtectedResource() throws Throwable { + String mainGroup = Group.ADMINS_GROUP_NAME; + String resDescrToAdd = "Test protected resource Attachment"; + String resourceType = "Attach"; + String categoryCodeToAdd = "resCat1"; + ResourceDataBean bean = this.getMockResourceAttachment(mainGroup, resDescrToAdd, categoryCodeToAdd); + List groups = new ArrayList<>(); + groups.add(Group.ADMINS_GROUP_NAME); + try { + // add the resource + this._resourceManager.addResource(bean); + List resources = this._resourceManager + .searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(1, resources.size()); + + String resourceId = resources.get(0); + ResourceInterface resource = this._resourceManager.loadResource(resourceId); + assertNotNull(resource); + + // move into the trash + this._resourceManager.deleteResource(resource); + resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(0, resources.size()); + + // restore from Trash + this._trashedResourceManager.restoreResource(resourceId); + resources = this._resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(1, resources.size()); + resource = this._resourceManager.loadResource(resources.get(0)); + + assertNotNull(resource.getResourceStream()); + assertEquals(Group.ADMINS_GROUP_NAME, resource.getMainGroup()); + // delete from archive and from trash + _resourceManager.deleteResource(resource); + resources = _resourceManager.searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + assertEquals(0, resources.size()); + this._trashedResourceManager.removeFromTrash(resource.getId()); + } catch (Throwable t) { + List resources = this._resourceManager + .searchResourcesId(resourceType, resDescrToAdd, categoryCodeToAdd, groups); + if (null != resources && resources.size() > 0) { + for (int i = 0; i < resources.size(); i++) { + String id = resources.get(i); + this._trashedResourceManager.removeFromTrash(id); + ResourceInterface resource = this._resourceManager.loadResource(id); + this._resourceManager.deleteResource(resource); + } + } + throw t; + } + } + + + @Test + void testAddMultiInstanceTrashedResourceShouldNotCrashIfResourceIsNoMoreInTheCDS() throws Throwable { + + AbstractMultiInstanceResource resource = mock(AbstractMultiInstanceResource.class); + when(resource.isMultiInstance()).thenReturn(true); + when(resource.getInstances()).thenReturn(Map.of("", mock(ResourceInstance.class))); + when(resource.getResourceStream(any())).thenThrow(EntResourceNotFoundRuntimeException.class); + TrashedResourceManager trashedResourceManager = new TrashedResourceManager(); + IStorageManager storageManager = mock(IStorageManager.class); + when(storageManager.exists(anyString(), anyBoolean())).thenReturn(true); + trashedResourceManager.setStorageManager(storageManager); + trashedResourceManager.setTrashedResourceDAO(mock(TrashedResourceDAO.class)); + assertDoesNotThrow(() -> trashedResourceManager.addTrashedResource(resource)); + trashedResourceManager.removeFromTrash(resource.getId()); + } - private ResourceDataBean getMockResourceAttachment(String mainGroup, String resDescrToAdd, String categoryCodeToAdd) { - File file = new File("target/test/test_attachment.txt"); - - BaseResourceDataBean bean = new BaseResourceDataBean(file); - bean.setDescr(resDescrToAdd); - bean.setMainGroup(mainGroup); - bean.setResourceType("Attach"); - bean.setMimeType("text/plain"); - List categories = new ArrayList(); - ICategoryManager catManager = - (ICategoryManager) this.getService(SystemConstants.CATEGORY_MANAGER); - Category cat = catManager.getCategory(categoryCodeToAdd); - categories.add(cat); - bean.setCategories(categories); - return bean; - } + @Test + void testAddMonoInstanceTrashedResourceShouldNotCrashIfResourceIsNoMoreInTheCDS() throws Throwable { + + AbstractMonoInstanceResource resource = mock(AbstractMonoInstanceResource.class); + when(resource.getInstance()).thenReturn(mock(ResourceInstance.class)); + when(resource.getResourceStream(any())).thenThrow(EntResourceNotFoundRuntimeException.class); + TrashedResourceManager trashedResourceManager = new TrashedResourceManager(); + IStorageManager storageManager = mock(IStorageManager.class); + when(storageManager.exists(anyString(), anyBoolean())).thenReturn(true); + trashedResourceManager.setStorageManager(storageManager); + trashedResourceManager.setTrashedResourceDAO(mock(TrashedResourceDAO.class)); + assertDoesNotThrow(() -> trashedResourceManager.addTrashedResource(resource)); + trashedResourceManager.removeFromTrash(resource.getId()); + + } + + private ResourceDataBean getMockResource(String resourceType, String mainGroup, String resDescrToAdd, + String categoryCodeToAdd) { + File file = new File("target/test/entando_logo.jpg"); + BaseResourceDataBean bean = new BaseResourceDataBean(file); + bean.setDescr(resDescrToAdd); + bean.setMainGroup(mainGroup); + bean.setResourceType(resourceType); + bean.setMimeType("image/jpeg"); + List categories = new ArrayList(); + ICategoryManager catManager = + (ICategoryManager) this.getService(SystemConstants.CATEGORY_MANAGER); + Category cat = catManager.getCategory(categoryCodeToAdd); + categories.add(cat); + bean.setCategories(categories); + return bean; + } + + private ResourceDataBean getMockResourceAttachment(String mainGroup, String resDescrToAdd, + String categoryCodeToAdd) { + File file = new File("target/test/test_attachment.txt"); + + BaseResourceDataBean bean = new BaseResourceDataBean(file); + bean.setDescr(resDescrToAdd); + bean.setMainGroup(mainGroup); + bean.setResourceType("Attach"); + bean.setMimeType("text/plain"); + List categories = new ArrayList(); + ICategoryManager catManager = + (ICategoryManager) this.getService(SystemConstants.CATEGORY_MANAGER); + Category cat = catManager.getCategory(categoryCodeToAdd); + categories.add(cat); + bean.setCategories(categories); + return bean; + } @BeforeEach - private void init() throws Exception { - try { - this._resourceManager = (IResourceManager) this.getService(JacmsSystemConstants.RESOURCE_MANAGER); - this._trashedResourceManager = (TrashedResourceManager) this.getService(JpversioningSystemConstants.TRASHED_RESOURCE_MANAGER); - } catch (Throwable t) { + private void init() throws Exception { + try { + this._resourceManager = (IResourceManager) this.getService(JacmsSystemConstants.RESOURCE_MANAGER); + this._trashedResourceManager = (TrashedResourceManager) this.getService( + JpversioningSystemConstants.TRASHED_RESOURCE_MANAGER); + } catch (Throwable t) { throw new Exception(t); } } - - private IResourceManager _resourceManager; - private TrashedResourceManager _trashedResourceManager; - + + private IResourceManager _resourceManager; + private TrashedResourceManager _trashedResourceManager; + } \ No newline at end of file diff --git a/webapp/pom.xml b/webapp/pom.xml index 5fb04048c3..48429090d6 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -5,7 +5,7 @@ org.entando app-engine - 7.3.0-SNAPSHOT + 7.4.0-SNAPSHOT org.entando.entando webapp