You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2020/03/12 23:38:29 UTC

[sling-org-apache-sling-scripting-bundle-tracker] branch master updated (ac7d153 -> fc38b64)

This is an automated email from the ASF dual-hosted git repository.

radu pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git.


    from ac7d153  SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines
     new 58ae67e  SLING-9159 - Switch to the LazyBindings implementation from org.apache.sling.api
     new ab81d98  SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines
     new fc38b64  SLING-9203 - Perform script / class lookup using the Sling script naming conventions

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../tracker/internal/BundledScriptFinder.java      | 102 ++++++++----------
 .../tracker/internal/BundledScriptTracker.java     |  14 +--
 .../{ResourceTypeParser.java => ResourceType.java} | 120 +++++++++++----------
 .../tracker/internal/ScriptContextProvider.java    |   2 +-
 .../bundle/tracker/internal/TypeProvider.java      |  21 ++--
 ...ceTypeParserTest.java => ResourceTypeTest.java} |  18 ++--
 6 files changed, 142 insertions(+), 135 deletions(-)
 rename src/main/java/org/apache/sling/scripting/bundle/tracker/internal/{ResourceTypeParser.java => ResourceType.java} (61%)
 rename src/test/java/org/apache/sling/scripting/bundle/tracker/internal/{ResourceTypeParserTest.java => ResourceTypeTest.java} (76%)


[sling-org-apache-sling-scripting-bundle-tracker] 02/03: SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git

commit ab81d98f7b9488ec980dc38097d3206f8e224ee1
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Mar 13 00:34:20 2020 +0100

    SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines
    
    * use the ScriptEngines extensions to perform the script / compiled class lookup
---
 .../tracker/internal/BundledScriptFinder.java      | 53 +++++++++++-----------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index a5a3c82..ed25e30 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -63,33 +63,24 @@ public class BundledScriptFinder {
             scriptMatches = buildScriptMatches(request, provider.getResourceType());
             String scriptEngineName = getScriptEngineName(request, provider);
             if (StringUtils.isNotEmpty(scriptEngineName)) {
-                for (String match : scriptMatches) {
-                    URL bundledScriptURL;
-                    if (precompiledScripts) {
-                        String className = JavaEscapeHelper.makeJavaPackage(match);
-                        try {
-                            Class clazz = provider.getBundle().loadClass(className);
-                            return new PrecompiledScript(provider.getBundle(), scriptEngineManager.getEngineByName(scriptEngineName),
-                                    clazz.getDeclaredConstructor().newInstance());
-                        } catch (ClassNotFoundException e) {
-                            // do nothing here
-                        } catch (Exception e) {
-                            throw new RuntimeException("Cannot correctly instantiate class " + className + ".");
-                        }
-                    } else {
-                        ScriptEngine scriptEngine = null;
-                        List<String> scriptEngineExtensions = Collections.emptyList();
-                        for (ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
-                            for (String shortName : factory.getNames()) {
-                                if (shortName.equals(scriptEngineName)) {
-                                    scriptEngine = factory.getScriptEngine();
-                                    scriptEngineExtensions = factory.getExtensions();
-                                    break;
+                ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(scriptEngineName);
+                if (scriptEngine != null) {
+                    for (String match : scriptMatches) {
+                        URL bundledScriptURL;
+                        List<String> scriptEngineExtensions = getScriptEngineExtensions(scriptEngineName);
+                        for (String scriptEngineExtension : scriptEngineExtensions) {
+                            if (precompiledScripts) {
+                                String className = JavaEscapeHelper.makeJavaPackage(match + DOT + scriptEngineExtension);
+                                try {
+                                    Class clazz = provider.getBundle().loadClass(className);
+                                    return new PrecompiledScript(provider.getBundle(), scriptEngine,
+                                            clazz.getDeclaredConstructor().newInstance());
+                                } catch (ClassNotFoundException e) {
+                                    // do nothing here
+                                } catch (Exception e) {
+                                    throw new RuntimeException("Cannot correctly instantiate class " + className + ".");
                                 }
-                            }
-                        }
-                        if (scriptEngine != null) {
-                            for (String scriptEngineExtension : scriptEngineExtensions) {
+                            } else {
                                 bundledScriptURL =
                                         provider.getBundle()
                                                 .getEntry(NS_JAVAX_SCRIPT_CAPABILITY + SLASH + match + DOT + scriptEngineExtension);
@@ -185,4 +176,14 @@ public class BundledScriptFinder {
         }
         return scriptEngineName;
     }
+
+    private List<String> getScriptEngineExtensions(String scriptEngineName) {
+        for (ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
+            Set<String> factoryNames = new HashSet<>(factory.getNames());
+            if (factoryNames.contains(scriptEngineName)) {
+                return factory.getExtensions();
+            }
+        }
+        return Collections.emptyList();
+    }
 }


[sling-org-apache-sling-scripting-bundle-tracker] 01/03: SLING-9159 - Switch to the LazyBindings implementation from org.apache.sling.api

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git

commit 58ae67e8ccb43a98f5fe23dd3d984d52f05656ce
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Mar 13 00:31:26 2020 +0100

    SLING-9159 - Switch to the LazyBindings implementation from org.apache.sling.api
    
    * the suppliers map should be modifiable
---
 .../sling/scripting/bundle/tracker/internal/ScriptContextProvider.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java
index 85b0f98..3ab0ffd 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java
@@ -97,7 +97,7 @@ public class ScriptContextProvider {
         Map<String, LazyBindings.Supplier> slingBindingsSuppliers = new HashMap<>();
         slingBindingsSuppliers.put(SlingScriptConstants.ATTR_SCRIPT_RESOURCE_RESOLVER,
                 () -> scriptingResourceResolverProvider.getRequestScopedResourceResolver());
-        LazyBindings slingScopeBindings = new LazyBindings(Collections.unmodifiableMap(slingBindingsSuppliers));
+        LazyBindings slingScopeBindings = new LazyBindings(slingBindingsSuppliers);
         scriptContext.setBindings(slingScopeBindings, SlingScriptConstants.SLING_SCOPE);
         scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
         scriptContext.setWriter(response.getWriter());


[sling-org-apache-sling-scripting-bundle-tracker] 03/03: SLING-9203 - Perform script / class lookup using the Sling script naming conventions

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git

commit fc38b64ea59cc1585e8ac1968339528449bdd9cf
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Mar 13 00:38:03 2020 +0100

    SLING-9203 - Perform script / class lookup using the Sling script naming conventions
---
 .../tracker/internal/BundledScriptFinder.java      |  49 ++++-----
 .../tracker/internal/BundledScriptTracker.java     |  14 +--
 .../{ResourceTypeParser.java => ResourceType.java} | 120 +++++++++++----------
 .../bundle/tracker/internal/TypeProvider.java      |  21 ++--
 ...ceTypeParserTest.java => ResourceTypeTest.java} |  18 ++--
 5 files changed, 114 insertions(+), 108 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index ed25e30..0c6b926 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -52,7 +52,6 @@ public class BundledScriptFinder {
     private static final String NS_JAVAX_SCRIPT_CAPABILITY = "javax.script";
     private static final String SLASH = "/";
     private static final String DOT = ".";
-    private static final Set<String> DEFAULT_METHODS = new HashSet<>(Arrays.asList("GET", "HEAD"));
 
     @Reference
     private ScriptEngineManager scriptEngineManager;
@@ -96,48 +95,38 @@ public class BundledScriptFinder {
         return null;
     }
 
-    private List<String> buildScriptMatches(SlingHttpServletRequest request, ResourceTypeParser.ResourceType resourceType) {
+    private List<String> buildScriptMatches(SlingHttpServletRequest request, ResourceType resourceType) {
         List<String> matches = new ArrayList<>();
         String method = request.getMethod();
-        boolean defaultMethod = DEFAULT_METHODS.contains(method);
         String extension = request.getRequestPathInfo().getExtension();
         String[] selectors = request.getRequestPathInfo().getSelectors();
         if (selectors.length > 0) {
             for (int i = selectors.length - 1; i >= 0; i--) {
-                String scriptForMethod = resourceType.getType() +
+                String base =
+                resourceType.getType() +
                         (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
-                        method + DOT + String.join(SLASH, Arrays.copyOf(selectors, i + 1));
-                String scriptNoMethod = resourceType.getType() +
-                        (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
-                        String.join
-                                (SLASH, Arrays.copyOf(selectors, i + 1));
-                if (StringUtils.isNotEmpty(extension)) {
-                    if (defaultMethod) {
-                        matches.add(scriptNoMethod + DOT + extension);
-                    }
-                    matches.add(scriptForMethod + DOT + extension);
-                }
-                if (defaultMethod) {
-                    matches.add(scriptNoMethod);
+                        String.join(SLASH, Arrays.copyOf(selectors, i + 1));
+                if (StringUtils.isNotEmpty(extension)){
+                    matches.add(base + DOT + extension + DOT + method);
+                    matches.add(base + DOT + extension);
                 }
-                matches.add(scriptForMethod);
+                matches.add(base + DOT + method);
+                matches.add(base);
             }
         }
-        String scriptForMethod = resourceType.getType() +
-                (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) + method;
-        String scriptNoMethod = resourceType.getType() +
-                (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
-                resourceType.getResourceLabel();
+        String base = resourceType.getType() +
+                (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() : StringUtils.EMPTY);
+
         if (StringUtils.isNotEmpty(extension)) {
-            if (defaultMethod) {
-                matches.add(scriptNoMethod + DOT + extension);
-            }
-            matches.add(scriptForMethod + DOT + extension);
+            matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + extension + DOT + method);
+            matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + extension);
         }
-        if (defaultMethod) {
-            matches.add(scriptNoMethod);
+        matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + method);
+        matches.add(base + SLASH + resourceType.getResourceLabel());
+        matches.add(base + SLASH + method);
+        if (StringUtils.isNotEmpty(extension)) {
+            matches.add(base + SLASH + extension);
         }
-        matches.add(scriptForMethod);
         return Collections.unmodifiableList(matches);
     }
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index 1d69b3a..f9c1661 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -171,8 +171,8 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
 
                     List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
                     LinkedHashSet<TypeProvider> wiredProviders = new LinkedHashSet<>();
-                    wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(resourceType), bundle));
-                    wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(resourceTypeString), bundle));
+                    wiredProviders.add(new TypeProvider(ResourceType.parseResourceType(resourceType), bundle));
+                    wiredProviders.add(new TypeProvider(ResourceType.parseResourceType(resourceTypeString), bundle));
                     if (optionalWire.isPresent()) {
                         BundleWire extendsWire = optionalWire.get();
                         Bundle providerBundle = extendsWire.getProvider().getBundle();
@@ -181,8 +181,8 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                         Version wireResourceTypeVersion = (Version) wireCapabilityAttributes.get(AT_VERSION);
                         String wireResourceTypeString = wireResourceType + (wireResourceTypeVersion != null ? "/" +
                                 wireResourceTypeVersion.toString() : "");
-                        wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(wireResourceType), providerBundle));
-                        wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(wireResourceTypeString), providerBundle));
+                        wiredProviders.add(new TypeProvider(ResourceType.parseResourceType(wireResourceType), providerBundle));
+                        wiredProviders.add(new TypeProvider(ResourceType.parseResourceType(wireResourceTypeString), providerBundle));
                         properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, wireResourceTypeString);
                     }
                     populateWiredProviders(wiredProviders);
@@ -224,7 +224,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                                 .AT_VERSION);
                         if (!initialResourceTypes.contains(resourceType)) {
                             initialProviders.add(new TypeProvider(
-                                    ResourceTypeParser.parseResourceType(resourceType + (version == null ? "" : "/" + version.toString())),
+                                    ResourceType.parseResourceType(resourceType + (version == null ? "" : "/" + version.toString())),
                                     bundleWire.getProvider().getBundle()));
                         }
                     }
@@ -291,14 +291,14 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
     private String getResourceType(Hashtable<String, Object> props) {
         String[] values = PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
         String resourceTypeValue = values[0];
-        ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(resourceTypeValue);
+        ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
         return resourceType.getType();
     }
 
     private String getResourceTypeVersion(ServiceReference<?> ref) {
         String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
         String resourceTypeValue = values[0];
-        ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(resourceTypeValue);
+        ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
         return resourceType.getVersion();
     }
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceType.java
similarity index 61%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
rename to src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceType.java
index 0dbe226..a8b6ff5 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceType.java
@@ -18,6 +18,8 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.scripting.bundle.tracker.internal;
 
+import java.util.Objects;
+
 import org.apache.commons.lang3.StringUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -35,68 +37,60 @@ import org.osgi.framework.Version;
  * <li><tt>a</tt> - flat (sub-set of path-based)</li>
  * </ol>
  */
-final class ResourceTypeParser {
+final class ResourceType {
+
+    private final String type;
+    private final String version;
+    private final String resourceLabel;
 
-    private ResourceTypeParser() {
+    private ResourceType(@NotNull String type, @Nullable String version) {
+        this.type = type;
+        this.version = version;
+        if (type.lastIndexOf('/') != -1) {
+            resourceLabel = type.substring(type.lastIndexOf('/') + 1);
+        } else if (type.lastIndexOf('.') != -1) {
+            resourceLabel = type.substring(type.lastIndexOf('.') + 1);
+        } else {
+            resourceLabel = type;
+        }
     }
 
     /**
-     * The {@code ResourceType} class encapsulates the details about a resource type.
+     * Returns a resource type's label. The label is important for script selection, since it will provide the name of the main script
+     * for this resource type. For more details check the Apache Sling
+     * <a href="https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html#scripts-for-get-requests">URL to
+     * Script Resolution</a> page
+     *
+     * @return the resource type label
      */
-    static class ResourceType {
-        private final String type;
-        private final String version;
-        private final String resourceLabel;
-
-        private ResourceType(@NotNull String type, @Nullable String version) {
-            this.type = type;
-            this.version = version;
-            if (type.lastIndexOf('/') != -1) {
-                resourceLabel = type.substring(type.lastIndexOf('/') + 1);
-            } else if (type.lastIndexOf('.') != -1) {
-                resourceLabel = type.substring(type.lastIndexOf('.') + 1);
-            } else {
-                resourceLabel = type;
-            }
-        }
-
-        /**
-         * Returns a resource type's label. The label is important for script selection, since it will provide the name of the main script
-         * for this resource type. For more details check the Apache Sling
-         * <a href="https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html#scripts-for-get-requests">URL to
-         * Script Resolution</a> page
-         *
-         * @return the resource type label
-         */
-        @NotNull
-        public String getResourceLabel() {
-            return resourceLabel;
-        }
+    @NotNull
+    public String getResourceLabel() {
+        return resourceLabel;
+    }
 
-        /**
-         * Returns the resource type string, without any version information.
-         *
-         * @return the resource type string
-         */
-        @NotNull
-        String getType() {
-            return type;
-        }
+    /**
+     * Returns the resource type string, without any version information.
+     *
+     * @return the resource type string
+     */
+    @NotNull
+    String getType() {
+        return type;
+    }
 
-        /**
-         * Returns the version, if available.
-         *
-         * @return the version, if available; {@code null} otherwise
-         */
-        @Nullable
-        String getVersion() {
-            return version;
-        }
+    /**
+     * Returns the version, if available.
+     *
+     * @return the version, if available; {@code null} otherwise
+     */
+    @Nullable
+    String getVersion() {
+        return version;
+    }
 
-        @Override
-        public String toString() {
-            return type + (version == null ? "" : "/" + version);
-        }
+    @Override
+    public String toString() {
+        return type + (version == null ? "" : "/" + version);
     }
 
     /**
@@ -136,4 +130,22 @@ final class ResourceTypeParser {
         }
         return new ResourceType(type, version);
     }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, version, resourceLabel);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ResourceType) {
+            ResourceType other = (ResourceType) obj;
+            return Objects.equals(type, other.type) && Objects.equals(version, other.version) && Objects.equals(resourceLabel,
+                    other.resourceLabel);
+        }
+        return false;
+    }
 }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
index d1db81d..befdc5f 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
@@ -18,6 +18,8 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.scripting.bundle.tracker.internal;
 
+import java.util.Objects;
+
 import org.osgi.framework.Bundle;
 
 /**
@@ -25,7 +27,7 @@ import org.osgi.framework.Bundle;
  */
 public class TypeProvider {
 
-    private final ResourceTypeParser.ResourceType resourceType;
+    private final ResourceType resourceType;
     private final Bundle bundle;
 
     /**
@@ -34,7 +36,7 @@ public class TypeProvider {
      * @param resourceType   the resource type
      * @param bundle the bundle that provides the resource type
      */
-    TypeProvider(ResourceTypeParser.ResourceType resourceType, Bundle bundle) {
+    TypeProvider(ResourceType resourceType, Bundle bundle) {
         this.resourceType = resourceType;
         this.bundle = bundle;
     }
@@ -44,7 +46,7 @@ public class TypeProvider {
      *
      * @return the resource type
      */
-    ResourceTypeParser.ResourceType getResourceType() {
+    ResourceType getResourceType() {
         return resourceType;
     }
 
@@ -59,15 +61,18 @@ public class TypeProvider {
 
     @Override
     public int hashCode() {
-        return resourceType.hashCode() ^ bundle.hashCode();
+        return Objects.hash(bundle, resourceType);
     }
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof TypeProvider)) {
-            return false;
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof TypeProvider) {
+            TypeProvider other = (TypeProvider) obj;
+            return Objects.equals(bundle, other.bundle) && Objects.equals(resourceType, other.resourceType);
         }
-        TypeProvider other = (TypeProvider) obj;
-        return other.bundle.equals(bundle) && other.resourceType.equals(resourceType);
+        return false;
     }
 }
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeTest.java
similarity index 76%
rename from src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java
rename to src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeTest.java
index 47f92ef..e8a6a6b 100644
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java
+++ b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeTest.java
@@ -24,11 +24,11 @@ import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-public class ResourceTypeParserTest {
+public class ResourceTypeTest {
 
     @Test
     public void testSlashNoVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/b/c");
+        ResourceType t1 = ResourceType.parseResourceType("a/b/c");
         assertEquals("a/b/c", t1.getType());
         assertEquals("c", t1.getResourceLabel());
         assertNull(t1.getVersion());
@@ -36,7 +36,7 @@ public class ResourceTypeParserTest {
 
     @Test
     public void testSlashVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/b/c/1.0.0");
+        ResourceType t1 = ResourceType.parseResourceType("a/b/c/1.0.0");
         assertEquals("a/b/c", t1.getType());
         assertEquals("c", t1.getResourceLabel());
         assertEquals("1.0.0", t1.getVersion());
@@ -44,7 +44,7 @@ public class ResourceTypeParserTest {
 
     @Test
     public void testOneSegmentNoVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a");
+        ResourceType t1 = ResourceType.parseResourceType("a");
         assertEquals("a", t1.getType());
         assertEquals("a", t1.getResourceLabel());
         assertNull(t1.getVersion());
@@ -52,7 +52,7 @@ public class ResourceTypeParserTest {
 
     @Test
     public void testOneSegmentVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/1.2.3");
+        ResourceType t1 = ResourceType.parseResourceType("a/1.2.3");
         assertEquals("a", t1.getType());
         assertEquals("a", t1.getResourceLabel());
         assertEquals("1.2.3", t1.getVersion());
@@ -60,7 +60,7 @@ public class ResourceTypeParserTest {
 
     @Test
     public void testDotNoVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a.b.c");
+        ResourceType t1 = ResourceType.parseResourceType("a.b.c");
         assertEquals("a.b.c", t1.getType());
         assertEquals("c", t1.getResourceLabel());
         assertNull(t1.getVersion());
@@ -68,7 +68,7 @@ public class ResourceTypeParserTest {
 
     @Test
     public void testDotVersion() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a.b.c/42.0.0");
+        ResourceType t1 = ResourceType.parseResourceType("a.b.c/42.0.0");
         assertEquals("a.b.c", t1.getType());
         assertEquals("c", t1.getResourceLabel());
         assertEquals("42.0.0", t1.getVersion());
@@ -76,12 +76,12 @@ public class ResourceTypeParserTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void testEmptyString() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType(StringUtils.EMPTY);
+        ResourceType t1 = ResourceType.parseResourceType(StringUtils.EMPTY);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testNull() {
-        ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType(null);
+        ResourceType t1 = ResourceType.parseResourceType(null);
     }
 
 }