SLING-9657 - Same-name JS Use dependencies are not always correctly resolved
* pick the dependency based on the resource type hierarchy, starting from
either the caller or the request driver - whichever is the deepest resource
in the resource type hierarchy
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
index 121ff77..bc1bee5 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
@@ -29,6 +29,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
@@ -61,45 +62,42 @@
// attempt to retrieve the dependency directly (as an absolute path or relative to the search paths)
Resource scriptResource = scriptingResourceResolver.getResource(dependency);
Resource caller = getCaller(bindings);
- if (scriptResource == null && caller != null) {
- Resource requestResource = (Resource) bindings.get(SlingBindings.RESOURCE);
- String type = requestResource.getResourceType();
- // look at the resource type hierarchy; a dependency closer to the current resource type has priority
- while (scriptResource == null && type != null) {
- Resource servletResource = null;
- if (!type.startsWith("/")) {
- for (String searchPath : scriptingResourceResolver.getSearchPath()) {
- String normalizedPath = ResourceUtil.normalize(searchPath + "/" + type);
- servletResource = resolveResource(normalizedPath);
- if (servletResource != null) {
- break;
+ if (caller != null) {
+ Resource callerType = caller.getParent();
+ if (scriptResource == null && callerType != null) {
+ SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+ String driverType = request.getResource().getResourceType();
+ Resource driver = resolveResource(driverType);
+ if (driver != null) {
+ Resource hierarchyResource = getChildResource(callerType, driver);
+ while (hierarchyResource != null && scriptResource == null) {
+ if (dependency.startsWith("..")) {
+ // relative path
+ String absolutePath = ResourceUtil.normalize(hierarchyResource.getPath() + "/" + dependency);
+ if (StringUtils.isNotEmpty(absolutePath)) {
+ scriptResource = resolveResource(absolutePath);
+ }
+ } else {
+ scriptResource = hierarchyResource.getChild(dependency);
+ }
+ String nextType = hierarchyResource.getResourceSuperType();
+ if (nextType != null) {
+ hierarchyResource = resolveResource(nextType);
+ } else {
+ hierarchyResource = null;
}
}
- } else {
- servletResource = resolveResource(type);
}
- if (servletResource != null) {
- scriptResource = servletResource.getChild(dependency);
- type = servletResource.getResourceSuperType();
- } else {
- type = null;
- }
- }
- // cannot find a dependency relative to the resource type; locate it solely based on the caller
- if (scriptResource == null) {
- if (dependency.startsWith("..")) {
- // relative path
- String absolutePath = ResourceUtil.normalize(caller.getPath() + "/" + dependency);
- if (StringUtils.isNotEmpty(absolutePath)) {
- scriptResource = resolveResource(absolutePath);
- }
- if (scriptResource == null) {
- scriptResource = caller.getChild(dependency);
- }
- } else {
- Resource callerParent = caller.getParent();
- if (callerParent != null) {
- scriptResource = callerParent.getChild(dependency);
+ // cannot find a dependency relative to the resource type; locate it solely based on the caller
+ if (scriptResource == null) {
+ if (dependency.startsWith("..")) {
+ // relative path
+ String absolutePath = ResourceUtil.normalize(caller.getPath() + "/" + dependency);
+ if (StringUtils.isNotEmpty(absolutePath)) {
+ scriptResource = resolveResource(absolutePath);
+ }
+ } else {
+ scriptResource = callerType.getChild(dependency);
}
}
}
@@ -124,9 +122,25 @@
}
private Resource resolveResource(String type) {
- Resource servletResource = scriptingResourceResolver.resolve(type);
- if (ResourceUtil.isNonExistingResource(servletResource)) {
- servletResource = scriptingResourceResolver.getResource(type);
+ Resource servletResource = null;
+ if (type.startsWith("/")) {
+ servletResource = scriptingResourceResolver.resolve(type);
+ if (ResourceUtil.isNonExistingResource(servletResource)) {
+ servletResource = scriptingResourceResolver.getResource(type);
+ }
+ } else {
+ for (String searchPath : scriptingResourceResolver.getSearchPath()) {
+ String absolutePath = ResourceUtil.normalize(searchPath + "/" + type);
+ if (absolutePath != null) {
+ servletResource = scriptingResourceResolver.resolve(absolutePath);
+ if (ResourceUtil.isNonExistingResource(servletResource)) {
+ servletResource = scriptingResourceResolver.getResource(type);
+ }
+ if (servletResource != null) {
+ return servletResource;
+ }
+ }
+ }
}
return servletResource;
}
@@ -146,4 +160,38 @@
return caller;
}
+ private Resource getChildResource(@NotNull Resource callerType, @NotNull Resource driverType) {
+ if (callerType.getPath().equals(driverType.getPath())) {
+ return callerType;
+ }
+ if (isResourceType(callerType, driverType.getPath())) {
+ return callerType;
+ }
+ if (isResourceType(driverType, callerType.getPath())) {
+ return driverType;
+ }
+ return null;
+ }
+
+ private boolean isResourceType(@NotNull Resource resource, String type) {
+ Resource typeResource = resolveResource(type);
+ if (typeResource != null) {
+ if (typeResource.getPath().equals(resource.getPath())) {
+ return true;
+ }
+ String resourceSuperType = resource.getResourceSuperType();
+ while (resourceSuperType != null) {
+ Resource intermediateType = resolveResource(resourceSuperType);
+ if (intermediateType != null) {
+ if (intermediateType.getPath().equals(typeResource.getPath())) {
+ return true;
+ }
+ resourceSuperType = intermediateType.getResourceSuperType();
+ } else {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
}