diff --git a/pdp-engine-oss-functional-benchmark/src/test/java/org/ow2/authzforce/core/pdp/benchmark/test/ComparativePdpTest.java b/pdp-engine-oss-functional-benchmark/src/test/java/org/ow2/authzforce/core/pdp/benchmark/test/ComparativePdpTest.java index 100bfbb3..2f5872ad 100644 --- a/pdp-engine-oss-functional-benchmark/src/test/java/org/ow2/authzforce/core/pdp/benchmark/test/ComparativePdpTest.java +++ b/pdp-engine-oss-functional-benchmark/src/test/java/org/ow2/authzforce/core/pdp/benchmark/test/ComparativePdpTest.java @@ -49,7 +49,7 @@ import org.ow2.authzforce.xacml.Xacml3JaxbHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import org.wso2.balana.ConfigurationStore; import org.wso2.balana.PDP; import org.wso2.balana.PDPConfig; @@ -358,7 +358,7 @@ public static Collection params() throws URISyntaxException, IOExcepti /* * Each sub-directory of the root directory is data for a specific test. So we configure a test for each directory */ - final URL testRootDir = ResourceUtils.getURL(TEST_RESOURCES_ROOT_DIRECTORY_LOCATION); + final URL testRootDir = ResourceLocationResolver.getUrl(TEST_RESOURCES_ROOT_DIRECTORY_LOCATION); final Path testRootPath = Paths.get(testRootDir.toURI()); final PdpEngineInvoker authzforcePdpEngineInvoker = new AuthzForcePdpEngineInvoker(testRootPath.resolve(AUTHZFORCE_CE_PDP_CONF_DIRNAME)); diff --git a/pdp-engine/pom.xml b/pdp-engine/pom.xml index c6a1f264..88104559 100644 --- a/pdp-engine/pom.xml +++ b/pdp-engine/pom.xml @@ -21,20 +21,10 @@ - - - org.slf4j - jcl-over-slf4j - org.eclipse.angus jakarta.mail - - - org.springframework - spring-core - xml-resolver diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/DefaultEnvironmentProperties.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/DefaultEnvironmentProperties.java index 1ca7c046..8a6c8596 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/DefaultEnvironmentProperties.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/DefaultEnvironmentProperties.java @@ -19,7 +19,6 @@ import org.ow2.authzforce.core.pdp.api.EnvironmentProperties; import org.ow2.authzforce.core.pdp.api.EnvironmentPropertyName; -import org.springframework.util.PropertyPlaceholderHelper; import java.util.Map; import java.util.Map.Entry; @@ -33,16 +32,11 @@ public final class DefaultEnvironmentProperties implements EnvironmentProperties { - private static final String PROPERTY_PLACEHOLDER_PREFIX = "${"; - private static final String PROPERTY_PLACEHOLDER_SUFFIX = "}"; /* * We cannot use ':' as default value separator because not valid in XML anyURI */ private static final String PROPERTY_PLACEHOLDER_DEFAULT_VALUE_SEPARATOR = "!"; - private static final PropertyPlaceholderHelper PROPERTY_PLACEHOLDER_HELPER = new PropertyPlaceholderHelper(PROPERTY_PLACEHOLDER_PREFIX, PROPERTY_PLACEHOLDER_SUFFIX, - PROPERTY_PLACEHOLDER_DEFAULT_VALUE_SEPARATOR, null, false); - private final Properties props = new Properties(); /** @@ -85,7 +79,7 @@ public String replacePlaceholders(final String input) return null; } - return PROPERTY_PLACEHOLDER_HELPER.replacePlaceholders(input, placeholderName -> { + return PlaceholderResolver.replace(input, PROPERTY_PLACEHOLDER_DEFAULT_VALUE_SEPARATOR, placeholderName -> { final String userDefinedPropVal = props.getProperty(placeholderName); if (userDefinedPropVal != null) diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpBean.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpBean.java index 39cb55e7..58474483 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpBean.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpBean.java @@ -21,7 +21,6 @@ import org.ow2.authzforce.core.pdp.api.policy.PrimaryPolicyMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.SystemPropertyUtils; import java.io.IOException; import java.util.Collection; @@ -56,14 +55,14 @@ public final class PdpBean implements PdpEngine * Configuration file. Only the 'defaultPDP' configuration will be loaded, i.e. 'pdp' element with 'name' matching the 'defaultPDP' attribute of the root 'config' element * * @param filePath - * configuration file path used as argument to {@link org.springframework.core.io.DefaultResourceLoader#getResource(String)} to resolve the resource; any placeholder ${...} in the path + * configuration file path (classpath resource, URL or file-system path); any placeholder ${...} in the path * will be replaced with the corresponding system property value * @throws java.lang.IllegalArgumentException * if there is an unresolvable placeholder in {@code filePath} */ public void setConfigFile(final String filePath) throws IllegalArgumentException { - confLocation = SystemPropertyUtils.resolvePlaceholders(filePath); + confLocation = resolveSystemPropertyPlaceholders(filePath); init(); } @@ -71,14 +70,14 @@ public void setConfigFile(final String filePath) throws IllegalArgumentException * Configuration schema file. Used only for validating XML configurations (enclosed with 'xml' tag) of PDP extension modules in PDP configuration file set with {@link #setConfigFile(String)} * * @param filePath - * configuration file path used as argument to {@link org.springframework.core.io.DefaultResourceLoader#getResource(String)} to resolve the resource; any placeholder ${...} in the path + * configuration schema path (classpath resource, URL or file-system path); any placeholder ${...} in the path * will be replaced with the corresponding system property value * @throws java.lang.IllegalArgumentException * if there is an unresolvable placeholder in {@code filePath} */ public void setSchemaFile(final String filePath) throws IllegalArgumentException { - extSchemaLocation = SystemPropertyUtils.resolvePlaceholders(filePath); + extSchemaLocation = resolveSystemPropertyPlaceholders(filePath); init(); } @@ -86,14 +85,14 @@ public void setSchemaFile(final String filePath) throws IllegalArgumentException * Set XML catalog for resolving XML entities used in XML schema * * @param filePath - * configuration file path used as argument to {@link org.springframework.core.io.DefaultResourceLoader#getResource(String)} to resolve the resource; any placeholder ${...} in the path + * XML catalog path (classpath resource, URL or file-system path); any placeholder ${...} in the path * will be replaced with the corresponding system property value * @throws java.lang.IllegalArgumentException * if there is an unresolvable placeholder in {@code filePath} */ public void setCatalogFile(final String filePath) throws IllegalArgumentException { - catalogLocation = SystemPropertyUtils.resolvePlaceholders(filePath); + catalogLocation = resolveSystemPropertyPlaceholders(filePath); init(); } @@ -117,6 +116,14 @@ private void init() } + private static String resolveSystemPropertyPlaceholders(final String value) + { + return PlaceholderResolver.replace(value, ":", placeholderName -> { + final String systemProperty = System.getProperty(placeholderName); + return systemProperty == null ? System.getenv(placeholderName) : systemProperty; + }); + } + @Override public DecisionRequestBuilder newRequestBuilder(final int expectedNumOfAttributeCategories, final int expectedTotalNumOfAttributes) { diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpEngineConfiguration.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpEngineConfiguration.java index 3e7a1390..3650886c 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpEngineConfiguration.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpEngineConfiguration.java @@ -48,7 +48,6 @@ import org.ow2.authzforce.xmlns.pdp.ext.AbstractPolicyProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; @@ -748,8 +747,7 @@ public static PdpEngineConfiguration getInstance(final File confFile, final PdpM } /** - * Create PDP instance. Locations here can be any resource string supported by Spring ResourceLoader. More info: Spring documentation - * /resources.html. + * Create PDP instance. Locations may be classpath resources, URLs or file-system paths. *

* To allow using file paths relative to the parent folder of the configuration file (located at confLocation) anywhere in this configuration file (including in PDP extensions'), we define a * property 'PARENT_DIR', so that the placeholder ${PARENT_DIR} can be used as prefix for file paths in the configuration file. E.g. if confLocation = 'file:///path/to/configurationfile', then @@ -775,7 +773,7 @@ public static PdpEngineConfiguration getInstance(final String confLocation, fina try { - final File confFile = ResourceUtils.getFile(confLocation); + final File confFile = ResourceLocationResolver.getFile(confLocation); return getInstance(confFile, modelHandler); } catch (final FileNotFoundException e) @@ -794,7 +792,7 @@ public static PdpEngineConfiguration getInstance(final String confLocation, fina final URL confUrl; try { - confUrl = ResourceUtils.getURL(confLocation); + confUrl = ResourceLocationResolver.getUrl(confLocation); } catch (final FileNotFoundException e) { @@ -811,8 +809,7 @@ public static PdpEngineConfiguration getInstance(final String confLocation, fina /** *

- * Create PDP instance. Locations here can be any resource string supported by Spring ResourceLoader. More info: Spring documentation - * /resources.html + * Create PDP instance. Locations may be classpath resources, URLs or file-system paths. *

*

* For example: classpath:com/myapp/aaa.xsd, file:///data/bbb.xsd, http://myserver/ccc.xsd... @@ -867,8 +864,7 @@ public static PdpEngineConfiguration getInstance(final File confFile, final Stri /** *

- * Create PDP instance. Locations here may be any resource string supported by Spring ResourceLoader. More info: Spring documentation - * /resources.html + * Create PDP instance. Locations may be classpath resources, URLs or file-system paths. *

*

* For example: classpath:com/myapp/aaa.xsd, file:///data/bbb.xsd, http://myserver/ccc.xsd... @@ -923,8 +919,8 @@ public static PdpEngineConfiguration getInstance(final String confLocation, fina * Create PDP instance. * * @param confLocation - * location of PDP configuration XML file, compliant with the PDP XML schema (pdp.xsd). This location may be any resource string supported by Spring ResourceLoader. For example: - * classpath:com/myapp/aaa.xsd, file:///data/bbb.xsd, http://myserver/ccc.xsd... More info: Spring documentation + * location of PDP configuration XML file, compliant with the PDP XML schema (pdp.xsd). It may be a classpath resource, URL or file-system path. For example: + * classpath:com/myapp/aaa.xsd, file:///data/bbb.xsd, http://myserver/ccc.xsd. * @return PDP instance * @throws IOException * I/O error reading from {@code confLocation} diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpModelHandler.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpModelHandler.java index 79553cf7..aa028ab1 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpModelHandler.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PdpModelHandler.java @@ -62,8 +62,7 @@ public final class PdpModelHandler private final JAXBContext confJaxbCtx; /** - * Load Configuration model handler. Parameters here are locations to XSD files. Locations can be any resource string supported by Spring ResourceLoader. - * More info. + * Load Configuration model handler. Parameters here are locations to XSD files. Locations may be classpath resources, URLs or file-system paths. *

* For example: classpath:com/myapp/aaa.xsd, file:///data/bbb.xsd, http://myserver/ccc.xsd... * diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PlaceholderResolver.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PlaceholderResolver.java new file mode 100644 index 00000000..b95cd65f --- /dev/null +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/PlaceholderResolver.java @@ -0,0 +1,108 @@ +/* + * Copyright 2012-2026 THALES. + * + * This file is part of AuthzForce CE. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ow2.authzforce.core.pdp.impl; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; + +/** Internal placeholder expansion support. */ +final class PlaceholderResolver +{ + private static final String PREFIX = "${"; + private static final char SUFFIX = '}'; + + private PlaceholderResolver() + { + // Utility class. + } + + static String replace(final String input, final String defaultValueSeparator, final Function valueResolver) + { + return replace(input, defaultValueSeparator, valueResolver, new HashSet<>()); + } + + private static String replace(final String input, final String defaultValueSeparator, final Function valueResolver, final Set activePlaceholders) + { + final StringBuilder output = new StringBuilder(input); + int startIndex = output.indexOf(PREFIX); + while (startIndex >= 0) + { + final int endIndex = findEndIndex(output, startIndex + PREFIX.length()); + if (endIndex < 0) + { + break; + } + + final String originalPlaceholder = output.substring(startIndex + PREFIX.length(), endIndex); + if (!activePlaceholders.add(originalPlaceholder)) + { + throw new IllegalArgumentException("Circular placeholder reference '" + originalPlaceholder + "'"); + } + + final String placeholder = replace(originalPlaceholder, defaultValueSeparator, valueResolver, activePlaceholders); + String value = valueResolver.apply(placeholder); + if (value == null && defaultValueSeparator != null) + { + final int separatorIndex = placeholder.indexOf(defaultValueSeparator); + if (separatorIndex >= 0) + { + value = valueResolver.apply(placeholder.substring(0, separatorIndex)); + if (value == null) + { + value = placeholder.substring(separatorIndex + defaultValueSeparator.length()); + } + } + } + + if (value == null) + { + throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'"); + } + + value = replace(value, defaultValueSeparator, valueResolver, activePlaceholders); + output.replace(startIndex, endIndex + 1, value); + activePlaceholders.remove(originalPlaceholder); + startIndex = output.indexOf(PREFIX, startIndex + value.length()); + } + + return output.toString(); + } + + private static int findEndIndex(final CharSequence input, final int contentStartIndex) + { + int nested = 0; + for (int index = contentStartIndex; index < input.length(); index++) + { + if (index + 1 < input.length() && input.charAt(index) == '$' && input.charAt(index + 1) == '{') + { + nested++; + index++; + } + else if (input.charAt(index) == SUFFIX) + { + if (nested == 0) + { + return index; + } + nested--; + } + } + return -1; + } +} diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/ResourceLocationResolver.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/ResourceLocationResolver.java new file mode 100644 index 00000000..9fdcf27c --- /dev/null +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/ResourceLocationResolver.java @@ -0,0 +1,116 @@ +/* + * Copyright 2012-2026 THALES. + * + * This file is part of AuthzForce CE. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ow2.authzforce.core.pdp.impl; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; + +/** Resolves classpath resources, URLs and file-system paths without a framework dependency. */ +public final class ResourceLocationResolver +{ + public static final String CLASSPATH_URL_PREFIX = "classpath:"; + public static final String FILE_URL_PREFIX = "file:"; + + private ResourceLocationResolver() + { + // Utility class. + } + + public static URL getUrl(final String location) throws FileNotFoundException + { + if (location == null) + { + throw new IllegalArgumentException("Resource location must not be null"); + } + + if (location.startsWith(CLASSPATH_URL_PREFIX)) + { + String resourcePath = location.substring(CLASSPATH_URL_PREFIX.length()); + while (resourcePath.startsWith("/")) + { + resourcePath = resourcePath.substring(1); + } + + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + final URL resourceUrl = contextClassLoader == null ? ClassLoader.getSystemResource(resourcePath) : contextClassLoader.getResource(resourcePath); + if (resourceUrl == null) + { + throw new FileNotFoundException("Class path resource [" + resourcePath + "] cannot be found"); + } + return resourceUrl; + } + + try + { + return new URL(location); + } + catch (final MalformedURLException e) + { + try + { + return new File(location).toURI().toURL(); + } + catch (final MalformedURLException impossible) + { + throw new IllegalArgumentException("Invalid resource location: " + location, impossible); + } + } + } + + public static File getFile(final String location) throws FileNotFoundException + { + if (location == null) + { + throw new IllegalArgumentException("Resource location must not be null"); + } + + if (!location.startsWith(CLASSPATH_URL_PREFIX)) + { + try + { + return getFile(new URL(location), location); + } + catch (final MalformedURLException e) + { + return new File(location); + } + } + + return getFile(getUrl(location), location); + } + + private static File getFile(final URL resourceUrl, final String description) throws FileNotFoundException + { + if (!"file".equals(resourceUrl.getProtocol())) + { + throw new FileNotFoundException(description + " cannot be resolved to an absolute file path because it does not reside in the file system"); + } + + try + { + return new File(resourceUrl.toURI()); + } + catch (final URISyntaxException e) + { + return new File(resourceUrl.getFile()); + } + } +} diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/SchemaHandler.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/SchemaHandler.java index da3cf1f8..9ce3c257 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/SchemaHandler.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/SchemaHandler.java @@ -22,7 +22,6 @@ import org.apache.xml.resolver.tools.CatalogResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.*; @@ -46,7 +45,7 @@ /** * - * XML schema handler that can load schema file(s) from location(s) supported by {@link ResourceUtils} using any OASIS catalog at any location supported by {@link ResourceUtils} as well. + * XML schema handler that can load schema files and OASIS catalogs from classpath resources, URLs or file-system paths. * * @version $Id: $ */ @@ -90,9 +89,8 @@ public LSInput resolveResource(final String type, final String namespaceURI, fin } if (resolvedLocation != null) { - // Fails with ResourceUtils.getFile(...) - // final File resourceFile = ResourceUtils.getFile(resolvedLocation); - final URL resourceURL = ResourceUtils.getURL(resolvedLocation); + // The resolved resource may be inside a JAR, so it cannot necessarily be converted to a File. + final URL resourceURL = ResourceLocationResolver.getUrl(resolvedLocation); return new LSInputImpl(publicId, systemId, new BufferedInputStream(resourceURL.openStream())); } } @@ -167,7 +165,7 @@ public String getResolvedEntity(final String publicId, final String systemId) { try { - final URL resourceURL = ResourceUtils.getURL(s); + final URL resourceURL = ResourceLocationResolver.getUrl(s); return resourceURL.toExternalForm(); } catch (final IOException e) @@ -398,7 +396,7 @@ public void setCertifiedText(final boolean certifiedText) private String catalogLocation; /** - * Sets (Spring-supported) locations to XML schema files + * Sets locations to XML schema files. Locations may be classpath resources, URLs or file-system paths. * * @param locations * XML schema locations @@ -409,7 +407,7 @@ public void setSchemaLocations(final List locations) } /** - * Sets (Spring-supported) locations to XML catalog files + * Sets locations to XML catalog files. Locations may be classpath resources, URLs or file-system paths. * * @param location * XML catalog location @@ -441,7 +439,7 @@ public Schema getSchema() public static Schema createSchema(final List schemaLocations, final String catalogLocation) { /* - * This is mostly similar to org.apache.cxf.jaxrs.utils.schemas.SchemaHandler#createSchema(), except we are using Spring ResourceUtils class to get Resource URLs, and we don't use any Bus + * This is mostly similar to org.apache.cxf.jaxrs.utils.schemas.SchemaHandler#createSchema(), except we resolve resource URLs directly, and we don't use any Bus * object. We are not using CXF's SchemaHandler class directly because it is part of cxf-rt-frontend-jaxrs which drags many dependencies on CXF we don't need, since it drags the full CXF JAX-RS framework actually. It would make more sense if SchemaHandler was part of some cxf common utility package, but it is not the case as of writing (December 2014). */ @@ -466,9 +464,9 @@ public static Schema createSchema(final List schemaLocations, final Stri try { /* - Fails with ResourceUtils.getFile(...) + The schema may be inside a JAR and therefore not resolvable to a File. */ - schemaURL = ResourceUtils.getURL(schemaLocation); + schemaURL = ResourceLocationResolver.getUrl(schemaLocation); } catch (final FileNotFoundException e) { @@ -498,7 +496,7 @@ public static Schema createSchema(final List schemaLocations, final Stri final URL catalogURL; try { - catalogURL = ResourceUtils.getURL(catalogLocation); + catalogURL = ResourceLocationResolver.getUrl(catalogLocation); } catch (final FileNotFoundException e) { diff --git a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/policy/CoreStaticPolicyProvider.java b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/policy/CoreStaticPolicyProvider.java index 975b419e..f3922901 100644 --- a/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/policy/CoreStaticPolicyProvider.java +++ b/pdp-engine/src/main/java/org/ow2/authzforce/core/pdp/impl/policy/CoreStaticPolicyProvider.java @@ -32,7 +32,7 @@ import org.ow2.authzforce.core.pdp.api.policy.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import java.io.FileNotFoundException; import java.io.IOException; @@ -50,7 +50,7 @@ /** * This is the core implementation of {@link BaseStaticPolicyProvider} that supports static retrieval of the policies referenced by Policy(Set)IdReference. It is configured by a list of locations that - * represent Spring-compatible resource URLs, corresponding to XACML Policy(Set) files - each file content is expected to be a XACML Policy(Set) document - when the module is initialized. Beyond this, + * represent classpath resources, URLs or file-system paths corresponding to XACML Policy(Set) files - each file content is expected to be a XACML Policy(Set) document - when the module is initialized. Beyond this, * there is no modifying or re-loading of the policies. *

* A policy location may also be a file pattern in the following form: "file://DIRECTORY_PATH/*SUFFIX" using wilcard character '*'; in which case the location is expanded to all regular files (not @@ -173,7 +173,7 @@ public CloseablePolicyProvider getInstance(final org.ow2.authzforce.core.xmln policyLocationPattern is handled like a URL pattern, e.g. file://path/to/policy(ies) Check whether the location is a file path pattern */ - if (policyLocationPattern.startsWith(ResourceUtils.FILE_URL_PREFIX)) + if (policyLocationPattern.startsWith(ResourceLocationResolver.FILE_URL_PREFIX)) { if (policyLocationPattern.endsWith("/")) { @@ -265,15 +265,15 @@ public CloseablePolicyProvider getInstance(final org.ow2.authzforce.core.xmln final URL policyURL; try { - // try to load the policy location as a Spring resource - policyURL = ResourceUtils.getURL(policyLocationPattern); + // Try classpath resources, URLs and file-system paths. + policyURL = ResourceLocationResolver.getUrl(policyLocationPattern); } catch (final FileNotFoundException e) { - throw new IllegalArgumentException("Error loading policy (as Spring resource) from the following URL: " + policyLocationPattern, e); + throw new IllegalArgumentException("Error loading policy from the following location: " + policyLocationPattern, e); } /* - If no exception occurred, ResourceUtils#getURL() returns non-null value + If no exception occurred, the resolver returns a non-null URL. */ providerParams.add(new PolicyLocationParam(policyURL)); } else diff --git a/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/DefaultEnvironmentPropertiesTest.java b/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/DefaultEnvironmentPropertiesTest.java index dee2368e..37bff007 100644 --- a/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/DefaultEnvironmentPropertiesTest.java +++ b/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/DefaultEnvironmentPropertiesTest.java @@ -72,7 +72,10 @@ public static Collection data() /* * Default value */ - { "${PARENT_DIR!/opt/driver-testbed-sec-authz-service/data}/a", null, null, "/opt/driver-testbed-sec-authz-service/data/a" }, + { "${PARENT_DIR!/opt/driver-testbed-sec-authz-service/data}/a", null, null, "/opt/driver-testbed-sec-authz-service/data/a" }, + + /* Nested placeholder name and recursively expanded value. */ + { "${${PARENT_DIR}}", ImmutableMap.of(EnvironmentPropertyName.PARENT_DIR, "sys.prop"), ImmutableMap.of("sys.prop", "${nested}", "nested", "resolved"), "resolved" }, /* * diff --git a/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/ResourceLocationResolverTest.java b/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/ResourceLocationResolverTest.java new file mode 100644 index 00000000..9c3badc9 --- /dev/null +++ b/pdp-engine/src/test/java/org/ow2/authzforce/core/pdp/impl/test/ResourceLocationResolverTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2026 THALES. + * + * This file is part of AuthzForce CE. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ow2.authzforce.core.pdp.impl.test; + +import org.junit.Assert; +import org.junit.Test; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.URL; + +public class ResourceLocationResolverTest +{ + @Test + public void resolveClasspathResource() throws Exception + { + final URL resource = ResourceLocationResolver.getUrl("classpath:logback.xml"); + Assert.assertNotNull(resource); + } + + @Test + public void resolveUrl() throws Exception + { + Assert.assertEquals("https", ResourceLocationResolver.getUrl("https://example.org/resource").getProtocol()); + } + + @Test + public void resolveFilePath() throws Exception + { + final File file = ResourceLocationResolver.getFile("relative/path.xml"); + Assert.assertEquals(new File("relative/path.xml"), file); + Assert.assertEquals("file", ResourceLocationResolver.getUrl("relative/path.xml").getProtocol()); + } + + @Test(expected = FileNotFoundException.class) + public void rejectNonFileUrlAsFile() throws Exception + { + ResourceLocationResolver.getFile("https://example.org/resource"); + } + + @Test(expected = FileNotFoundException.class) + public void rejectMissingClasspathResource() throws Exception + { + ResourceLocationResolver.getUrl("classpath:does/not/exist"); + } +} diff --git a/pdp-testutils/src/main/java/org/ow2/authzforce/core/pdp/testutil/XacmlXmlPdpTestHelper.java b/pdp-testutils/src/main/java/org/ow2/authzforce/core/pdp/testutil/XacmlXmlPdpTestHelper.java index e14b246b..b97a26e6 100644 --- a/pdp-testutils/src/main/java/org/ow2/authzforce/core/pdp/testutil/XacmlXmlPdpTestHelper.java +++ b/pdp-testutils/src/main/java/org/ow2/authzforce/core/pdp/testutil/XacmlXmlPdpTestHelper.java @@ -28,7 +28,7 @@ import org.ow2.authzforce.core.pdp.impl.io.PdpEngineAdapters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import java.io.File; import java.io.FileNotFoundException; @@ -245,7 +245,7 @@ public Optional test() throws IllegalArgumentException, IOException, JAX File pdpExtXsdFile = null; try { - pdpExtXsdFile = ResourceUtils.getFile(PDP_EXTENSION_XSD_LOCATION); + pdpExtXsdFile = ResourceLocationResolver.getFile(PDP_EXTENSION_XSD_LOCATION); } catch (final FileNotFoundException e) { @@ -314,4 +314,4 @@ public Optional test() throws IllegalArgumentException, IOException, JAX } } } -} \ No newline at end of file +} diff --git a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/MongoDbPolicyProviderTest.java b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/MongoDbPolicyProviderTest.java index ec4b155a..3126d9c7 100644 --- a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/MongoDbPolicyProviderTest.java +++ b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/MongoDbPolicyProviderTest.java @@ -60,7 +60,7 @@ import org.ow2.authzforce.core.xmlns.pdp.Pdp; import org.ow2.authzforce.xacml.Xacml3JaxbHelper; import org.ow2.authzforce.xmlns.pdp.ext.AbstractPolicyProvider; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import javax.xml.transform.stream.StreamSource; import java.io.File; @@ -138,7 +138,7 @@ public static void setUpBeforeClass() throws Exception db.listCollectionNames().forEach(s -> System.out.println("collection " + s)); // Load the JSON schema for policy documents in the MongoDB - final File mongodbDocumentSchemaFile = ResourceUtils.getFile("classpath:mongodb_policy_provider_doc_schema.json"); + final File mongodbDocumentSchemaFile = ResourceLocationResolver.getFile("classpath:mongodb_policy_provider_doc_schema.json"); final JsonObject mongodbDocumentSchema = new JsonObject(Files.readString(mongodbDocumentSchemaFile.toPath())); // Create the MongoDB collection of policy documents diff --git a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/conformance/ConformanceV3FromV2Test.java b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/conformance/ConformanceV3FromV2Test.java index d5775b6f..8387b2d5 100644 --- a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/conformance/ConformanceV3FromV2Test.java +++ b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/conformance/ConformanceV3FromV2Test.java @@ -33,7 +33,7 @@ import org.ow2.authzforce.core.pdp.testutil.TestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import java.io.File; import java.io.FileNotFoundException; @@ -256,7 +256,7 @@ public void test() throws Exception File pdpExtXsdFile = null; try { - pdpExtXsdFile = ResourceUtils.getFile(PDP_EXTENSION_XSD_LOCATION); + pdpExtXsdFile = ResourceLocationResolver.getFile(PDP_EXTENSION_XSD_LOCATION); } catch (final FileNotFoundException e) { LOGGER.debug("No PDP extension configuration file '{}' found -> JAXB-bound PDP extensions not allowed.", PDP_EXTENSION_XSD_LOCATION); @@ -348,4 +348,4 @@ else if (expectedResponse == null) } } }*/ -} \ No newline at end of file +} diff --git a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/json/XacmlJsonTest.java b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/json/XacmlJsonTest.java index 2836f4d5..3eb07026 100644 --- a/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/json/XacmlJsonTest.java +++ b/pdp-testutils/src/test/java/org/ow2/authzforce/core/pdp/testutil/test/json/XacmlJsonTest.java @@ -28,7 +28,7 @@ import org.ow2.authzforce.xacml.json.model.XacmlJsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; +import org.ow2.authzforce.core.pdp.impl.ResourceLocationResolver; import org.testng.Assert; import org.testng.annotations.Test; @@ -127,7 +127,7 @@ public static Collection getTestData(final String testRootDir, final S /* * Each sub-directory of the root directory is data for a specific test. So we configure a test for each directory */ - final URL testRootDirLocation = ResourceUtils.getURL(testRootDir); + final URL testRootDirLocation = ResourceLocationResolver.getUrl(testRootDir); final Path testRootDirPath = Paths.get(testRootDirLocation.toURI()); try (DirectoryStream stream = Files.newDirectoryStream(testRootDirPath, Files::isDirectory)) { @@ -293,7 +293,7 @@ public void test(final Path testDirectoryPath, final String reqFilterId) throws File pdpExtXsdFile = null; try { - pdpExtXsdFile = ResourceUtils.getFile(PDP_EXTENSION_XSD_LOCATION); + pdpExtXsdFile = ResourceLocationResolver.getFile(PDP_EXTENSION_XSD_LOCATION); } catch (final FileNotFoundException e) { LOGGER.debug("No PDP extension configuration file '{}' found -> JAXB-bound PDP extensions not allowed.", PDP_EXTENSION_XSD_LOCATION); @@ -358,4 +358,4 @@ else if (expectedResponse == null) throw e; } } -} \ No newline at end of file +}