From e28f57791004ebe68c3eb6e4b1df2064a9d7fe2b Mon Sep 17 00:00:00 2001 From: PeetKes Date: Sat, 6 Jan 2024 16:09:53 +0100 Subject: [PATCH 1/2] Added glob transformer for regexes in properties file --- ...PropertiesDrivenDocumentFileProcessor.java | 100 ++++++++++++++++++ .../CollectionsFileDocumentFileProcessor.java | 18 ++-- .../PermissionsFileDocumentFileProcessor.java | 27 ++--- ...lectionsFileDocumentFileProcessorTest.java | 9 ++ ...missionsFileDocumentFileProcessorTest.java | 10 +- .../wildcard-test/collections.properties | 1 + .../wildcard-test/permissions.properties | 1 + .../process-files/wildcard-test/test-1.json | 3 + 8 files changed, 144 insertions(+), 25 deletions(-) create mode 100644 src/test/resources/process-files/wildcard-test/test-1.json diff --git a/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java index d171619..81c1dd3 100644 --- a/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java @@ -98,4 +98,104 @@ public boolean isCascadingEnabled() { public void setCascadingEnabled(boolean cascadingEnabled) { this.cascadingEnabled = cascadingEnabled; } + + /** + * Converts a standard POSIX Shell globbing pattern into a regular expression + * pattern. The result can be used with the standard {@link java.util.regex} API to + * recognize strings which match the glob pattern. + *

+ * See also, the POSIX Shell language: + * http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01 + * + * @param pattern A glob pattern. + * @return A regex pattern to recognize the given glob pattern. + */ + public String convertGlobToRegex(String pattern) { + StringBuilder sb = new StringBuilder(pattern.length()); + int inGroup = 0; + int inClass = 0; + int firstIndexInClass = -1; + char[] arr = pattern.toCharArray(); + for (int i = 0; i < arr.length; i++) { + char ch = arr[i]; + switch (ch) { + case '\\': + if (++i >= arr.length) { + sb.append('\\'); + } else { + char next = arr[i]; + switch (next) { + case ',': + // escape not needed + break; + case 'Q': + case 'E': + // extra escape needed + sb.append('\\'); + default: + sb.append('\\'); + } + sb.append(next); + } + break; + case '*': + if (inClass == 0) + sb.append(".*"); + else + sb.append('*'); + break; + case '?': + if (inClass == 0) + sb.append('.'); + else + sb.append('?'); + break; + case '[': + inClass++; + firstIndexInClass = i+1; + sb.append('['); + break; + case ']': + inClass--; + sb.append(']'); + break; + case '.': + case '(': + case ')': + case '+': + case '|': + case '^': + case '$': + case '@': + case '%': + if (inClass == 0 || (firstIndexInClass == i && ch == '^')) + sb.append('\\'); + sb.append(ch); + break; + case '!': + if (firstIndexInClass == i) + sb.append('^'); + else + sb.append('!'); + break; + case '{': + inGroup++; + sb.append('('); + break; + case '}': + inGroup--; + sb.append(')'); + break; + case ',': + if (inGroup > 0) + sb.append('|'); + else + sb.append(','); + break; + default: + sb.append(ch); + } + } + return sb.toString(); + } } diff --git a/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java index 28d09e2..c92528e 100644 --- a/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java @@ -15,6 +15,9 @@ */ package com.marklogic.client.ext.file; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; import java.util.Properties; /** @@ -37,14 +40,13 @@ public CollectionsFileDocumentFileProcessor(String propertiesFilename) { @Override protected void processProperties(DocumentFile documentFile, Properties properties) { String name = documentFile.getFile().getName(); - if (properties.containsKey(name)) { - String value = getPropertyValue(properties, name); - documentFile.getDocumentMetadata().withCollections(value.split(delimiter)); - } - - if (properties.containsKey(WILDCARD_KEY)) { - String value = getPropertyValue(properties, WILDCARD_KEY); - documentFile.getDocumentMetadata().withCollections(value.split(delimiter)); + Enumeration keys = properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + if (name.matches(convertGlobToRegex(key))) { + String value = getPropertyValue(properties, key); + documentFile.getDocumentMetadata().withCollections(value.split(delimiter)); + } } } diff --git a/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java index b92db8e..35f5b01 100644 --- a/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java @@ -17,6 +17,7 @@ import com.marklogic.client.ext.util.DocumentPermissionsParser; +import java.util.Enumeration; import java.util.Properties; /** @@ -49,22 +50,16 @@ public PermissionsFileDocumentFileProcessor(String propertiesFilename, DocumentP @Override protected void processProperties(DocumentFile documentFile, Properties properties) { String name = documentFile.getFile().getName(); - if (properties.containsKey(name)) { - String value = getPropertyValue(properties, name); - if (documentPermissionsParser != null) { - documentPermissionsParser.parsePermissions(value, documentFile.getDocumentMetadata().getPermissions()); - } else { - documentFile.getDocumentMetadata().getPermissions().addFromDelimitedString(value); - } - - } - - if (properties.containsKey(WILDCARD_KEY)) { - String value = getPropertyValue(properties, WILDCARD_KEY); - if (documentPermissionsParser != null) { - documentPermissionsParser.parsePermissions(value, documentFile.getDocumentMetadata().getPermissions()); - } else { - documentFile.getDocumentMetadata().getPermissions().addFromDelimitedString(value); + Enumeration keys = properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + if (name.matches(convertGlobToRegex(key))) { + String value = getPropertyValue(properties, key); + if (documentPermissionsParser != null) { + documentPermissionsParser.parsePermissions(value, documentFile.getDocumentMetadata().getPermissions()); + } else { + documentFile.getDocumentMetadata().getPermissions().addFromDelimitedString(value); + } } } } diff --git a/src/test/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessorTest.java b/src/test/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessorTest.java index e33939f..b36a657 100644 --- a/src/test/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessorTest.java +++ b/src/test/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessorTest.java @@ -38,12 +38,21 @@ public void wildcard() throws IOException { DocumentFile file = new DocumentFile("/test.json", new File(testDir, "test.json")); processor.processDocumentFile(file); assertTrue(file.getDocumentMetadata().getCollections().contains("json-data")); + assertTrue(file.getDocumentMetadata().getCollections().contains("json-data-wildcard")); + assertFalse(file.getDocumentMetadata().getCollections().contains("xml-data")); + assertTrue(file.getDocumentMetadata().getCollections().contains("global")); + + file = new DocumentFile("/test-1.json", new File(testDir, "test-1.json")); + processor.processDocumentFile(file); + assertFalse(file.getDocumentMetadata().getCollections().contains("json-data")); + assertTrue(file.getDocumentMetadata().getCollections().contains("json-data-wildcard")); assertFalse(file.getDocumentMetadata().getCollections().contains("xml-data")); assertTrue(file.getDocumentMetadata().getCollections().contains("global")); file = new DocumentFile("/test.xml", new File(testDir, "test.xml")); processor.processDocumentFile(file); assertFalse(file.getDocumentMetadata().getCollections().contains("json-data")); + assertFalse(file.getDocumentMetadata().getCollections().contains("json-data-wildcard")); assertTrue(file.getDocumentMetadata().getCollections().contains("xml-data")); assertTrue(file.getDocumentMetadata().getCollections().contains("global")); } diff --git a/src/test/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessorTest.java b/src/test/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessorTest.java index 64c9ade..44bd32c 100644 --- a/src/test/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessorTest.java +++ b/src/test/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessorTest.java @@ -47,7 +47,15 @@ public void wildcard() throws IOException { assertTrue(permissions.get("manage-user").contains(DocumentMetadataHandle.Capability.READ)); assertTrue(permissions.get("manage-user").contains(DocumentMetadataHandle.Capability.UPDATE)); assertTrue(permissions.get("manage-admin").contains(DocumentMetadataHandle.Capability.UPDATE)); - assertNull(permissions.get("qconsole-user")); + assertTrue(permissions.get("qconsole-user").contains(DocumentMetadataHandle.Capability.READ)); + + file = new DocumentFile("/test-1.json", new File(testDir, "test-1.json")); + processor.processDocumentFile(file); + permissions = file.getDocumentMetadata().getPermissions(); + assertTrue(permissions.get("manage-user").contains(DocumentMetadataHandle.Capability.READ)); + assertFalse(permissions.get("manage-user").contains(DocumentMetadataHandle.Capability.UPDATE)); + assertNull(permissions.get("manage-admin")); + assertTrue(permissions.get("qconsole-user").contains(DocumentMetadataHandle.Capability.READ)); file = new DocumentFile("/test.xml", new File(testDir, "test.xml")); processor.processDocumentFile(file); diff --git a/src/test/resources/process-files/wildcard-test/collections.properties b/src/test/resources/process-files/wildcard-test/collections.properties index d44c90f..5a556e0 100644 --- a/src/test/resources/process-files/wildcard-test/collections.properties +++ b/src/test/resources/process-files/wildcard-test/collections.properties @@ -1,3 +1,4 @@ *=global test.json=json-data +*.json=json-data-wildcard test.xml=xml-data diff --git a/src/test/resources/process-files/wildcard-test/permissions.properties b/src/test/resources/process-files/wildcard-test/permissions.properties index ba233c0..abaacec 100644 --- a/src/test/resources/process-files/wildcard-test/permissions.properties +++ b/src/test/resources/process-files/wildcard-test/permissions.properties @@ -1,3 +1,4 @@ *=manage-user,read test.json=manage-user,update,manage-admin,update +*.json=qconsole-user,read test.xml=qconsole-user,update diff --git a/src/test/resources/process-files/wildcard-test/test-1.json b/src/test/resources/process-files/wildcard-test/test-1.json new file mode 100644 index 0000000..9859cd3 --- /dev/null +++ b/src/test/resources/process-files/wildcard-test/test-1.json @@ -0,0 +1,3 @@ +{ + "test": "test-1" +} From f5edffb22e81656cfbeb1ac4194d654d742af8ea Mon Sep 17 00:00:00 2001 From: Peter Kester Date: Mon, 8 Jan 2024 17:47:47 +0100 Subject: [PATCH 2/2] #196 reworked the processProperties function in the CollectionsFileDocumentFileProcessor and PermissionsFileDocumentFileProcessor to work with the PathMatcher class to match wildcarded property keys --- ...PropertiesDrivenDocumentFileProcessor.java | 99 ------------------- .../CollectionsFileDocumentFileProcessor.java | 11 ++- .../PermissionsFileDocumentFileProcessor.java | 9 +- 3 files changed, 14 insertions(+), 105 deletions(-) diff --git a/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java index 81c1dd3..2119a18 100644 --- a/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/CascadingPropertiesDrivenDocumentFileProcessor.java @@ -99,103 +99,4 @@ public void setCascadingEnabled(boolean cascadingEnabled) { this.cascadingEnabled = cascadingEnabled; } - /** - * Converts a standard POSIX Shell globbing pattern into a regular expression - * pattern. The result can be used with the standard {@link java.util.regex} API to - * recognize strings which match the glob pattern. - *

- * See also, the POSIX Shell language: - * http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01 - * - * @param pattern A glob pattern. - * @return A regex pattern to recognize the given glob pattern. - */ - public String convertGlobToRegex(String pattern) { - StringBuilder sb = new StringBuilder(pattern.length()); - int inGroup = 0; - int inClass = 0; - int firstIndexInClass = -1; - char[] arr = pattern.toCharArray(); - for (int i = 0; i < arr.length; i++) { - char ch = arr[i]; - switch (ch) { - case '\\': - if (++i >= arr.length) { - sb.append('\\'); - } else { - char next = arr[i]; - switch (next) { - case ',': - // escape not needed - break; - case 'Q': - case 'E': - // extra escape needed - sb.append('\\'); - default: - sb.append('\\'); - } - sb.append(next); - } - break; - case '*': - if (inClass == 0) - sb.append(".*"); - else - sb.append('*'); - break; - case '?': - if (inClass == 0) - sb.append('.'); - else - sb.append('?'); - break; - case '[': - inClass++; - firstIndexInClass = i+1; - sb.append('['); - break; - case ']': - inClass--; - sb.append(']'); - break; - case '.': - case '(': - case ')': - case '+': - case '|': - case '^': - case '$': - case '@': - case '%': - if (inClass == 0 || (firstIndexInClass == i && ch == '^')) - sb.append('\\'); - sb.append(ch); - break; - case '!': - if (firstIndexInClass == i) - sb.append('^'); - else - sb.append('!'); - break; - case '{': - inGroup++; - sb.append('('); - break; - case '}': - inGroup--; - sb.append(')'); - break; - case ',': - if (inGroup > 0) - sb.append('|'); - else - sb.append(','); - break; - default: - sb.append(ch); - } - } - return sb.toString(); - } } diff --git a/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java index c92528e..2756d6b 100644 --- a/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/CollectionsFileDocumentFileProcessor.java @@ -15,9 +15,10 @@ */ package com.marklogic.client.ext.file; -import java.util.ArrayList; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.PathMatcher; import java.util.Enumeration; -import java.util.List; import java.util.Properties; /** @@ -39,11 +40,13 @@ public CollectionsFileDocumentFileProcessor(String propertiesFilename) { @Override protected void processProperties(DocumentFile documentFile, Properties properties) { - String name = documentFile.getFile().getName(); + Path name = documentFile.getFile().toPath().getFileName(); Enumeration keys = properties.propertyNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); - if (name.matches(convertGlobToRegex(key))) { + PathMatcher matcher = + FileSystems.getDefault().getPathMatcher( "glob:" + key); + if (matcher.matches(name)) { String value = getPropertyValue(properties, key); documentFile.getDocumentMetadata().withCollections(value.split(delimiter)); } diff --git a/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java b/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java index 35f5b01..94c8778 100644 --- a/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java +++ b/src/main/java/com/marklogic/client/ext/file/PermissionsFileDocumentFileProcessor.java @@ -17,6 +17,9 @@ import com.marklogic.client.ext.util.DocumentPermissionsParser; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.PathMatcher; import java.util.Enumeration; import java.util.Properties; @@ -49,11 +52,13 @@ public PermissionsFileDocumentFileProcessor(String propertiesFilename, DocumentP @Override protected void processProperties(DocumentFile documentFile, Properties properties) { - String name = documentFile.getFile().getName(); + Path name = documentFile.getFile().toPath().getFileName(); Enumeration keys = properties.propertyNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); - if (name.matches(convertGlobToRegex(key))) { + PathMatcher matcher = + FileSystems.getDefault().getPathMatcher( "glob:" + key); + if (matcher.matches(name)) { String value = getPropertyValue(properties, key); if (documentPermissionsParser != null) { documentPermissionsParser.parsePermissions(value, documentFile.getDocumentMetadata().getPermissions());