Skip to content

Commit

Permalink
Update external management url
Browse files Browse the repository at this point in the history
   Add {objectId} property in external management url (base64 unique identifier for the record)
   Change external management type url property {type} so that it is fixed values so that same value can be used in {objectId}
CMIS
   Fixed property names used for validation fields to be consistent with other names.
Jcloud
   Updgade from jcloud 2.3.0 to jcloud 2.5.0
   Add support for external management named properties similar to cmis
   Fix bug with deleting all resources as it was failing to identify folders correctly for azure blob.
  • Loading branch information
ianwallen committed Sep 9, 2024
1 parent 05b2e43 commit 682c86c
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* =============================================================================
* === Copyright (C) 2019 Food and Agriculture Organization of the
* === Copyright (C) 2024 Food and Agriculture Organization of the
* === United Nations (FAO-UN), United Nations World Food Programme (WFP)
* === and United Nations Environment Programme (UNEP)
* ===
Expand Down Expand Up @@ -44,12 +44,16 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public abstract class AbstractStore implements Store {
protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR = ":";
protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR = "\\:";

@Override
public final List<MetadataResource> getResources(final ServiceContext context, final String metadataUuid, final Sort sort,
final String filter) throws Exception {
Expand Down Expand Up @@ -279,4 +283,28 @@ public String toString() {
}
};
}

private String escapeResourceManagementExternalProperties(String value) {
return value.replace(RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR, RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR);
}

/**
* Create an encoded base 64 object id contains the following fields to uniquely identify the resource
* The fields are separated by a colon ":"
* @param type to identify type of storage - document/folder
* @param visibility of the resource public/private
* @param metadataId internal metadata id
* @param version identifier which can be used to directly get this version.
* @param resourceId or filename of the resource
* @return based 64 object id
*/
protected String getResourceManagementExternalPropertiesObjectId(final String type, final MetadataResourceVisibility visibility, final Integer metadataId, final String version,
final String resourceId) {
return Base64.getEncoder().encodeToString(
((type + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR +
escapeResourceManagementExternalProperties(visibility == null ? "" : visibility.toString().toLowerCase()) + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR +
metadataId + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR +
escapeResourceManagementExternalProperties(version == null ? "" : version) + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR +
escapeResourceManagementExternalProperties(resourceId)).getBytes()));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* =============================================================================
* === Copyright (C) 2001-2016 Food and Agriculture Organization of the
* === Copyright (C) 2001-2024 Food and Agriculture Organization of the
* === United Nations (FAO-UN), United Nations World Food Programme (WFP)
* === and United Nations Environment Programme (UNEP)
* ===
Expand Down Expand Up @@ -627,8 +627,10 @@ private GeonetworkDataDirectory getDataDirectory(ServiceContext context) {
/**
* get external resource management for the supplied resource.
* Replace the following
* {objectId} type:visibility:metadataId:version:resourceId in base64 encoding
* {id} resource id
* {type:folder:document} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
* {type:folder:document} // Custom return type based on type. If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
* {type} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
* {uuid} metadatauuid
* {metadataid} metadataid
* {visibility} visibility
Expand Down Expand Up @@ -657,16 +659,28 @@ protected MetadataResourceExternalManagementProperties getMetadataResourceExtern
) {
String metadataResourceExternalManagementPropertiesUrl = cmisConfiguration.getExternalResourceManagementUrl();
if (!StringUtils.isEmpty(metadataResourceExternalManagementPropertiesUrl)) {
// {objectid} objectId // It will be the type:visibility:metadataId:version:resourceId in base64
// i.e. folder::100::100 # Folder in resource 100
// i.e. document:public:100:v1:sample.jpg # public document 100 version v1 name sample.jpg
if (metadataResourceExternalManagementPropertiesUrl.contains("{objectid}")) {
metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{objectid\\})",
getResourceManagementExternalPropertiesObjectId((type == null ? "document" : (type instanceof Folder ? "folder" : "document")), visibility, metadataId, version, resourceId));
}

// {id} id
if (metadataResourceExternalManagementPropertiesUrl.contains("{id}")) {
metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{id\\})", (resourceId==null?"":resourceId));
}
// {type:folder:document} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
// {type:folder:document} // Custom return type based on type. If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
if (metadataResourceExternalManagementPropertiesUrl.contains("{type:")) {
metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("\\{type:([a-zA-Z0-9]*?):([a-zA-Z0-9]*?)\\}",
(type==null?"":(type instanceof Folder?"$1":"$2")));
}

// {type} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed
if (metadataResourceExternalManagementPropertiesUrl.contains("{type}")) {
metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{type\\})",
(type == null ? "document" : (type instanceof Folder ? "folder" : "document")));
}
// {uuid} metadatauuid
if (metadataResourceExternalManagementPropertiesUrl.contains("{uuid}")) {
metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{uuid\\})", (metadataUuid==null?"":metadataUuid));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2016 Food and Agriculture Organization of the
* Copyright (C) 2001-2024 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -59,26 +59,28 @@
public class CMISConfiguration {
private Session client = null;

public final static Integer CMIS_MAX_ITEMS_PER_PAGE = 1000;
public final static String CMIS_FOLDER_DELIMITER = "/"; // Specs indicate that "/" is the folder delimiter/separator - not sure if other delimiter can be used?.
public final static String CMIS_SECONDARY_PROPERTY_SEPARATOR = "->";
private final String CMIS_DEFAULT_WEBSERVICES_ACL_SERVICE = "/services/ACLService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_DISCOVERY_SERVICE = "/services/DiscoveryService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_MULTIFILING_SERVICE = "/services/MultiFilingService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_NAVIGATION_SERVICE = "/services/NavigationService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_OBJECT_SERVICE = "/services/ObjectService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_POLICY_SERVICE = "/services/PolicyService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_RELATIONSHIP_SERVICE = "/services/RelationshipService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_REPOSITORY_SERVICE = "/services/RepositoryService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_VERSIONING_SERVICE = "/services/VersioningService?wsdl";
private final String CMIS_DEFAULT_WEBSERVICES_BASE_URL_SERVICE = "/cmis";
private final String CMIS_DEFAULT_BROWSER_URL_SERVICE = "/browser";
private final String CMIS_DEFAULT_ATOMPUB_URL_SERVICE = "/atom";

private final String CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_WINDOW_PARAMETERS = "toolbar=0,width=600,height=600";
private final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED = true;
private final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED = true;
private final Boolean CMIS_DEFAULT_VERSIONING_ENABLED = false;
// DFO change to 100. Due to bug with open text cmis where if max is set to 1000, it will return 100 but if it is set to 100 it will return all records.
// https://dev.azure.com/foc-poc/EDH-CDE/_workitems/edit/95878
public static final Integer CMIS_MAX_ITEMS_PER_PAGE = 100;
public static final String CMIS_FOLDER_DELIMITER = "/"; // Specs indicate that "/" is the folder delimiter/separator - not sure if other delimiter can be used?.
public static final String CMIS_SECONDARY_PROPERTY_SEPARATOR = "->";
private static final String CMIS_DEFAULT_WEBSERVICES_ACL_SERVICE = "/services/ACLService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_DISCOVERY_SERVICE = "/services/DiscoveryService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_MULTIFILING_SERVICE = "/services/MultiFilingService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_NAVIGATION_SERVICE = "/services/NavigationService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_OBJECT_SERVICE = "/services/ObjectService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_POLICY_SERVICE = "/services/PolicyService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_RELATIONSHIP_SERVICE = "/services/RelationshipService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_REPOSITORY_SERVICE = "/services/RepositoryService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_VERSIONING_SERVICE = "/services/VersioningService?wsdl";
private static final String CMIS_DEFAULT_WEBSERVICES_BASE_URL_SERVICE = "/cmis";
private static final String CMIS_DEFAULT_BROWSER_URL_SERVICE = "/browser";
private static final String CMIS_DEFAULT_ATOMPUB_URL_SERVICE = "/atom";

private static final String CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_WINDOW_PARAMETERS = "toolbar=0,width=600,height=600";
private static final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED = true;
private static final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED = true;
private static final Boolean CMIS_DEFAULT_VERSIONING_ENABLED = false;

private String servicesBaseUrl;
private String bindingType;
Expand Down Expand Up @@ -111,7 +113,6 @@ public class CMISConfiguration {
* Property name for validation status that is expected to be an integer with values of null, 0, 1, 2
* (See MetadataResourceExternalManagementProperties.ValidationStatus for code meaning)
* Property name follows the same format as cmisMetadataUUIDPropertyName
*
* If null then validation status will default to UNKNOWN.
*/
private String externalResourceManagementValidationStatusPropertyName;
Expand Down Expand Up @@ -505,7 +506,6 @@ public void setExternalResourceManagementValidationStatusPropertyName(String ext
String.format("Invalid format for property name %s property will not be used", externalResourceManagementValidationStatusPropertyName));
this.externalResourceManagementValidationStatusPropertyName = null;
this.externalResourceManagementValidationStatusSecondaryProperty = false;
return;
} else {
this.externalResourceManagementValidationStatusSecondaryProperty = true;
}
Expand All @@ -514,7 +514,7 @@ public void setExternalResourceManagementValidationStatusPropertyName(String ext

public MetadataResourceExternalManagementProperties.ValidationStatus getValidationStatusDefaultValue() {
// We only need to set the default if there is a status property supplied, and it is not already set
if (this.defaultStatus == null && !org.springframework.util.StringUtils.isEmpty(getExternalResourceManagementValidationStatusPropertyName())) {
if (this.defaultStatus == null && org.springframework.util.StringUtils.hasLength(getExternalResourceManagementValidationStatusPropertyName())) {
if (getExternalResourceManagementValidationStatusDefaultValue() != null) {
// If a default property name does exist then use it
this.defaultStatus = MetadataResourceExternalManagementProperties.ValidationStatus.valueOf(getExternalResourceManagementValidationStatusDefaultValue());
Expand All @@ -536,9 +536,8 @@ public void init() {
}

// default factory implementation
Map<String, String> parameters = new HashMap<String, String>();
Map<String, String> parameters = new HashMap<>();

this.baseRepositoryPath = baseRepositoryPath;
if (this.baseRepositoryPath == null) {
this.baseRepositoryPath = "";
}
Expand Down Expand Up @@ -609,7 +608,7 @@ public void init() {
}
}
} else {
// Try to find the repository name for the id that we have specified..
// Try to find the repository name for the id that we have specified.
try {
for (Repository repository : factory.getRepositories(parameters)) {
if (repository.getId().equalsIgnoreCase(this.repositoryId)) {
Expand All @@ -633,7 +632,7 @@ public void init() {
repositoryUrl + "' using product '" + client.getRepositoryInfo().getProductName() + "' version '" +
client.getRepositoryInfo().getProductVersion() + "'.");

// Check if we can parse the secondary parameters from human readable to secondary ids.
// Check if we can parse the secondary parameters from human-readable to secondary ids.
parsedCmisMetadataUUIDPropertyName = parseSecondaryProperty(client, cmisMetadataUUIDPropertyName);
parsedExternalResourceManagementValidationStatusPropertyName = parseSecondaryProperty(client, externalResourceManagementValidationStatusPropertyName);

Expand Down Expand Up @@ -743,7 +742,7 @@ public boolean existExternalResourceManagementValidationStatusSecondaryProperty(
}

/**
* Generte a full url based on the supplied entered serviceurl and the default.
* Generate a full url based on the supplied entered serviceUrl and the default.
*
* @param baseUrl Base url
* @param serviceUrl Supplied service url (This could start with / or http. If it starts with http then ignore baseUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ cmis.external.resource.management.window.parameters=${CMIS_EXTERNAL_RESOURCE_MAN
cmis.external.resource.management.modal.enabled=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED:#{null}}
cmis.external.resource.management.folder.enabled=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED:#{null}}
cmis.external.resource.management.folder.root=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ROOT:#{null}}
cmis.external.resource.status.property.name=${CMIS_EXTERNAL_RESOURCE_STATUS_PROPERTY_NAME:#{null}}
cmis.external.resource.management.status.default.value=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_STATUS_DEFAULT_VALUE:#{null}}
cmis.external.resource.management.validation.status.property.name=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_VALIDATION_STATUS_PROPERTY_NAME:#{null}}
cmis.external.resource.management.validation.status.default.value=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_VALIDATION_STATUS_DEFAULT_VALUE:#{null}}

cmis.versioning.enabled=${CMIS_VERSIONING_ENABLED:#{null}}
cmis.versioning.state=#{'${CMIS_VERSIONING_STATE:MAJOR}'.toUpperCase()}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (C) 2001-2016 Food and Agriculture Organization of the
~ Copyright (C) 2001-2024 Food and Agriculture Organization of the
~ United Nations (FAO-UN), United Nations World Food Programme (WFP)
~ and United Nations Environment Programme (UNEP)
~
Expand Down Expand Up @@ -99,8 +99,8 @@
<property name="externalResourceManagementModalEnabled" value="${cmis.external.resource.management.modal.enabled}"/>
<property name="externalResourceManagementFolderEnabled" value="${cmis.external.resource.management.folder.enabled}"/>
<property name="externalResourceManagementFolderRoot" value="${cmis.external.resource.management.folder.root}"/>
<property name="externalResourceManagementValidationStatusPropertyName" value="${cmis.external.resource.status.property.name}"/>
<property name="externalResourceManagementValidationStatusDefaultValue" value="${cmis.external.resource.management.status.default.value}"/>
<property name="externalResourceManagementValidationStatusPropertyName" value="${cmis.external.resource.management.validation.status.property.name}"/>
<property name="externalResourceManagementValidationStatusDefaultValue" value="${cmis.external.resource.management.validation.status.default.value}"/>

<property name="versioningEnabled" value="${cmis.versioning.enabled}"/>
<property name="versioningState" value="${cmis.versioning.state}"/>
Expand Down
Loading

0 comments on commit 682c86c

Please sign in to comment.