SLING-11311 : Improve org-apache-sling-jcr-resource
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java b/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java
index 3c6eda4..207edf8 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/HelperData.java
@@ -25,6 +25,8 @@
 
 import org.apache.sling.api.resource.external.URIProvider;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * This is a helper class used to pass several services/data to the resource
@@ -39,20 +41,20 @@
 
     private volatile String[] namespacePrefixes;
 
-    public HelperData(final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference, AtomicReference<URIProvider[]> uriProviderReference) {
+    public HelperData(@NotNull final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference, 
+                      @NotNull AtomicReference<URIProvider[]> uriProviderReference) {
         this.dynamicClassLoaderManagerReference = dynamicClassLoaderManagerReference;
         this.uriProviderReference = uriProviderReference;
     }
 
-    public String[] getNamespacePrefixes(final Session session)
-    throws RepositoryException {
+    public String[] getNamespacePrefixes(@NotNull final Session session) throws RepositoryException {
         if ( this.namespacePrefixes == null ) {
             this.namespacePrefixes = session.getNamespacePrefixes();
         }
         return this.namespacePrefixes;
     }
 
-    public ClassLoader getDynamicClassLoader() {
+    public @Nullable ClassLoader getDynamicClassLoader() {
         final DynamicClassLoaderManager dclm = this.dynamicClassLoaderManagerReference.get();
         if ( dclm == null ) {
             return null;
@@ -60,9 +62,9 @@
         return dclm.getDynamicClassLoader();
     }
 
-    public URIProvider[] getURIProviders() {
+    public @NotNull URIProvider[] getURIProviders() {
         URIProvider[] ups = this.uriProviderReference.get();
-        if ( ups == null) {
+        if (ups == null) {
             ups = EMPTY_URLPROVIDERS;
         }
         return ups;
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
index b0c9529..a0e8db7 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
@@ -46,17 +46,14 @@
  */
 public class JcrListenerBaseConfig implements Closeable {
 
-    private final Logger logger = LoggerFactory.getLogger(JcrResourceListener.class);
+    private final Logger logger = LoggerFactory.getLogger(JcrListenerBaseConfig.class);
 
     private final Session session;
 
     private final ObservationReporter reporter;
 
     @SuppressWarnings("deprecation")
-    public JcrListenerBaseConfig(
-                    final ObservationReporter reporter,
-                    final SlingRepository repository)
-    throws RepositoryException {
+    public JcrListenerBaseConfig(final ObservationReporter reporter, final SlingRepository repository) throws RepositoryException {
         this.reporter = reporter;
         // The session should have read access on the whole repository
         this.session = repository.loginService("observation", repository.getDefaultWorkspace());
@@ -67,7 +64,7 @@
      * Close session.
      */
     @Override
-    public void close() throws IOException {
+    public void close() {
         this.session.logout();
     }
 
@@ -77,16 +74,15 @@
      * @param config The configuration
      * @throws RepositoryException If registration fails.
      */
-    public void register(final EventListener listener, final ObserverConfiguration config)
-    throws RepositoryException {
+    public void register(final EventListener listener, final ObserverConfiguration config) throws RepositoryException {
         final ObservationManager mgr = this.session.getWorkspace().getObservationManager();
-        if ( mgr instanceof JackrabbitObservationManager ) {
+        if (mgr instanceof JackrabbitObservationManager) {
             final OakEventFilter filter = FilterFactory.wrap(new JackrabbitEventFilter());
             // paths
             final Set<String> paths = config.getPaths().toStringSet();
             int globCount = 0, pathCount = 0;
-            for(final String p : paths) {
-                if ( p.startsWith(Path.GLOB_PREFIX )) {
+            for (final String p : paths) {
+                if (p.startsWith(Path.GLOB_PREFIX)) {
                     globCount++;
                 } else {
                     pathCount++;
@@ -98,8 +94,8 @@
             globCount = 0;
 
             // create arrays and remove global prefix
-            for(final String p : paths) {
-                if ( p.startsWith(Path.GLOB_PREFIX )) {
+            for (final String p : paths) {
+                if (p.startsWith(Path.GLOB_PREFIX)) {
                     globArray[globCount] = p.substring(Path.GLOB_PREFIX.length());
                     globCount++;
                 } else {
@@ -107,17 +103,17 @@
                     pathCount++;
                 }
             }
-            if ( globArray != null ) {
+            if (globArray != null) {
                 filter.withIncludeGlobPaths(globArray);
             }
-            if ( pathArray != null ) {
+            if (pathArray != null) {
                 filter.setAdditionalPaths(pathArray);
             }
             filter.setIsDeep(true);
 
             // exclude paths
             final Set<String> excludePaths = config.getExcludedPaths().toStringSet();
-            if ( !excludePaths.isEmpty() ) {
+            if (!excludePaths.isEmpty()) {
                 filter.setExcludedPaths(excludePaths.toArray(new String[excludePaths.size()]));
             }
 
@@ -128,12 +124,12 @@
             filter.setEventTypes(this.getTypes(config));
 
             // nt:file handling
-            filter.withNodeTypeAggregate(new String[] {"nt:file"}, new String[] {"", "jcr:content"});
+            filter.withNodeTypeAggregate(new String[]{"nt:file"}, new String[]{"", "jcr:content"});
 
             // ancestors remove
             filter.withIncludeAncestorsRemove();
 
-            ((JackrabbitObservationManager)mgr).addEventListener(listener, filter);
+            ((JackrabbitObservationManager) mgr).addEventListener(listener, filter);
         } else {
             throw new RepositoryException("Observation manager is not a JackrabbitObservationManager");
         }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMap.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMap.java
index d28afdd..90e88f7 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMap.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMap.java
@@ -32,9 +32,7 @@
 /**
  * Modifiable value map implementation leveraging the base class
  */
-public class JcrModifiableValueMap
-    extends JcrValueMap
-    implements ModifiableValueMap {
+public class JcrModifiableValueMap extends JcrValueMap implements ModifiableValueMap {
 
     /**
      * Constructor
@@ -51,10 +49,10 @@
     @Override
     public Object put(final String aKey, final Object value) {
         final String key = checkKey(aKey);
-        if ( key.indexOf('/') != -1 ) {
+        if (key.indexOf('/') != -1) {
             throw new IllegalArgumentException("Invalid key: " + key);
         }
-        if ( value == null ) {
+        if (value == null) {
             throw new NullPointerException("Value should not be null (key = " + key + ")");
         }
         readFully();
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceChange.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceChange.java
index 205c8d3..219239b 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceChange.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceChange.java
@@ -19,6 +19,8 @@
 package org.apache.sling.jcr.resource.internal;
 
 import org.apache.sling.api.resource.observation.ResourceChange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Extension of {@code ResourceChange} to support user id (if available)
@@ -27,16 +29,16 @@
 
     private final String userId;
 
-    public JcrResourceChange(final ResourceChange.ChangeType changeType,
-            final String path,
-            final boolean isExternal,
-            final String userId) {
+    public JcrResourceChange(@NotNull final ResourceChange.ChangeType changeType,
+                             @NotNull final String path,
+                             final boolean isExternal,
+                             @Nullable final String userId) {
         super(changeType, path, isExternal);
         this.userId = userId;
     }
 
     @Override
-    public String getUserId() {
+    public @Nullable String getUserId() {
         return userId;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java
index 01958f7..90c755c 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java
@@ -41,6 +41,7 @@
 import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
 import org.apache.sling.spi.resource.provider.ObservationReporter;
 import org.apache.sling.spi.resource.provider.ObserverConfiguration;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * The <code>JcrResourceListener</code> listens for JCR observation
@@ -53,9 +54,8 @@
 
     private final JcrListenerBaseConfig baseConfig;
 
-    public JcrResourceListener(final JcrListenerBaseConfig listenerConfig,
-                    final ObserverConfiguration config)
-    throws RepositoryException {
+    public JcrResourceListener(@NotNull final JcrListenerBaseConfig listenerConfig, 
+                               @NotNull final ObserverConfiguration config) throws RepositoryException {
         this.baseConfig = listenerConfig;
         this.config = config;
         this.baseConfig.register(this, config);
@@ -82,7 +82,7 @@
      * Dispose this listener.
      */
     @Override
-    public void close() throws IOException {
+    public void close() {
         // unregister from observations
         this.baseConfig.unregister(this);
     }
@@ -92,18 +92,18 @@
      */
     @Override
     public void onEvent(final EventIterator events) {
-        final Map<String, ResourceChange> addedEvents = new HashMap<String, ResourceChange>();
-        final Map<String, ResourceChange> changedEvents = new HashMap<String, ResourceChange>();
-        final Map<String, ResourceChange> removedEvents = new HashMap<String, ResourceChange>();
+        final Map<String, ResourceChange> addedEvents = new HashMap<>();
+        final Map<String, ResourceChange> changedEvents = new HashMap<>();
+        final Map<String, ResourceChange> removedEvents = new HashMap<>();
 
-        while ( events.hasNext() ) {
+        while (events.hasNext()) {
             final Event event = events.nextEvent();
 
             final String identifier;
             final String path;
             try {
                 identifier = event.getIdentifier();
-                path =  event.getPath();
+                path = event.getPath();
             } catch (final RepositoryException e) {
                 // event.getPath or event.getIdentifier threw an exception
                 // there is nothing we can do about it anyway
@@ -113,34 +113,34 @@
             final String eventPath = (identifier != null && identifier.startsWith("/") ? identifier : path);
             final int type = event.getType();
 
-            if ( type == PROPERTY_ADDED && path.endsWith("/jcr:primaryType") ) {
+            if (type == PROPERTY_ADDED && path.endsWith("/jcr:primaryType")) {
                 final int lastSlash = path.lastIndexOf('/');
                 final String rsrcPath = path.substring(0, lastSlash);
 
                 // add is stronger than update
                 changedEvents.remove(rsrcPath);
                 addedEvents.put(rsrcPath, createResourceChange(event, rsrcPath, ChangeType.ADDED));
-            } else if ( type == PROPERTY_ADDED
-                     || type == PROPERTY_REMOVED
-                     || type == PROPERTY_CHANGED ) {
+            } else if (type == PROPERTY_ADDED
+                    || type == PROPERTY_REMOVED
+                    || type == PROPERTY_CHANGED) {
                 final String rsrcPath;
-                if ( identifier == null || !identifier.startsWith("/") ) {
+                if (identifier == null || !identifier.startsWith("/")) {
                     final int lastSlash = eventPath.lastIndexOf('/');
                     rsrcPath = eventPath.substring(0, lastSlash);
                 } else {
                     rsrcPath = eventPath;
                 }
-                if ( !addedEvents.containsKey(rsrcPath)
-                  && !removedEvents.containsKey(rsrcPath)
-                  && !changedEvents.containsKey(rsrcPath) ) {
+                if (!addedEvents.containsKey(rsrcPath)
+                        && !removedEvents.containsKey(rsrcPath)
+                        && !changedEvents.containsKey(rsrcPath)) {
 
                     changedEvents.put(rsrcPath, createResourceChange(event, rsrcPath, ChangeType.CHANGED));
                 }
-            } else if ( type == NODE_ADDED ) {
+            } else if (type == NODE_ADDED) {
                 // add is stronger than update
                 changedEvents.remove(eventPath);
                 addedEvents.put(eventPath, createResourceChange(event, eventPath, ChangeType.ADDED));
-            } else if ( type == NODE_REMOVED) {
+            } else if (type == NODE_REMOVED) {
                 // remove is stronger than add and change
                 addedEvents.remove(eventPath);
                 changedEvents.remove(eventPath);
@@ -148,7 +148,7 @@
             }
         }
 
-        final List<ResourceChange> changes = new ArrayList<ResourceChange>();
+        final List<ResourceChange> changes = new ArrayList<>();
         changes.addAll(addedEvents.values());
         changes.addAll(removedEvents.values());
         changes.addAll(changedEvents.values());
@@ -156,23 +156,22 @@
 
     }
 
-    private ResourceChange createResourceChange(final Event event,
-            final String path,
-            final ChangeType changeType) {
-        final String fullPath = path;
-        final boolean isExternal = this.isExternal(event);
+    private static @NotNull ResourceChange createResourceChange(@NotNull final Event event,
+                                                                @NotNull final String path,
+                                                                @NotNull final ChangeType changeType) {
+        final boolean isExternal = isExternal(event);
         final String userId;
         if (!isExternal) {
             userId = event.getUserID();
         } else {
             userId = null;
         }
-        return new JcrResourceChange(changeType, fullPath, isExternal, userId);
+        return new JcrResourceChange(changeType, path, isExternal, userId);
     }
 
-    private boolean isExternal(final Event event) {
-        if ( event instanceof JackrabbitEvent) {
-            final JackrabbitEvent jEvent = (JackrabbitEvent)event;
+    private static boolean isExternal(@NotNull final Event event) {
+        if (event instanceof JackrabbitEvent) {
+            final JackrabbitEvent jEvent = (JackrabbitEvent) event;
             return jEvent.isExternal();
         }
         return false;
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidator.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidator.java
index b748ac5..e340268 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidator.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidator.java
@@ -17,7 +17,6 @@
 package org.apache.sling.jcr.resource.internal;
 
 import java.lang.reflect.Method;
-import java.security.Principal;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
@@ -79,8 +78,8 @@
 
     private final Method isSystemUserMethod;
 
-    private final Set<String> validIds = new CopyOnWriteArraySet<String>();
-    private final Set<String> validPrincipalNames = new CopyOnWriteArraySet<String>();
+    private final Set<String> validIds = new CopyOnWriteArraySet<>();
+    private final Set<String> validPrincipalNames = new CopyOnWriteArraySet<>();
 
     private boolean allowOnlySystemUsers;
 
@@ -206,12 +205,7 @@
                         }
                     }
 
-                    Authorizable authorizable = userManager.getAuthorizable(new Principal() {
-                        @Override
-                        public String getName() {
-                            return pName;
-                        }
-                    });
+                    Authorizable authorizable = userManager.getAuthorizable(() -> pName);
                     if (isValidSystemUser(authorizable)) {
                         validPrincipalNames.add(pName);
                         log.debug("The provided service principal name {} is a known JCR system user", pName);
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java b/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java
index ac9dc78..e4ccdd5 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java
@@ -38,6 +38,8 @@
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * This implementation of the value map allows to change
@@ -50,10 +52,10 @@
     protected final Node node;
 
     /** A cache for the properties. */
-    protected final Map<String, JcrPropertyMapCacheEntry> cache = new LinkedHashMap<String, JcrPropertyMapCacheEntry>();
+    protected final Map<String, JcrPropertyMapCacheEntry> cache = new LinkedHashMap<>();
 
     /** A cache for the values. */
-    protected final Map<String, Object> valueCache = new LinkedHashMap<String, Object>();
+    protected final Map<String, Object> valueCache = new LinkedHashMap<>();
 
     /** Has the node been read completely? */
     private boolean fullyRead = false;
@@ -73,11 +75,11 @@
 
     // ---------- ValueMap
 
-    protected String checkKey(final String key) {
-        if ( key == null ) {
+    protected @NotNull String checkKey(@Nullable final String key) {
+        if (key == null) {
             throw new NullPointerException("Key must not be null.");
         }
-        if ( key.startsWith("./") ) {
+        if (key.startsWith("./")) {
             return key.substring(2);
         }
         return key;
@@ -88,14 +90,14 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T get(final String aKey, final Class<T> type) {
+    public @Nullable <T> T get(@NotNull final String aKey, @NotNull final Class<T> type) {
         final String key = checkKey(aKey);
         if (type == null) {
             return (T) get(key);
         }
 
         final JcrPropertyMapCacheEntry entry = this.read(key);
-        if ( entry == null ) {
+        if (entry == null) {
             return null;
         }
         return entry.convertToType(type, node, helper.getDynamicClassLoader());
@@ -106,7 +108,7 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T get(final String aKey,final T defaultValue) {
+    public @NotNull <T> T get(@NotNull final String aKey, @NotNull final T defaultValue) {
         final String key = checkKey(aKey);
         if (defaultValue == null) {
             return (T) get(key);
@@ -133,8 +135,7 @@
     public Object get(final Object aKey) {
         final String key = checkKey(aKey.toString());
         final JcrPropertyMapCacheEntry entry = this.read(key);
-        final Object value = (entry == null ? null : entry.getPropertyValueOrNull());
-        return value;
+        return (entry == null ? null : entry.getPropertyValueOrNull());
     }
 
     /**
@@ -175,7 +176,7 @@
      * @see java.util.Map#entrySet()
      */
     @Override
-    public Set<java.util.Map.Entry<String, Object>> entrySet() {
+    public @NotNull Set<java.util.Map.Entry<String, Object>> entrySet() {
         readFully();
         final Map<String, Object> sourceMap;
         if (cache.size() == valueCache.size()) {
@@ -190,7 +191,7 @@
      * @see java.util.Map#keySet()
      */
     @Override
-    public Set<String> keySet() {
+    public @NotNull Set<String> keySet() {
         readFully();
         return Collections.unmodifiableSet(cache.keySet());
     }
@@ -199,7 +200,7 @@
      * @see java.util.Map#values()
      */
     @Override
-    public Collection<Object> values() {
+    public @NotNull Collection<Object> values() {
         readFully();
         final Map<String, Object> sourceMap;
         if (cache.size() == valueCache.size()) {
@@ -232,24 +233,24 @@
      * @return
      * @throws IllegalArgumentException if a repository exception occurs
      */
-    private JcrPropertyMapCacheEntry cacheProperty(final Property prop) {
+    private @NotNull JcrPropertyMapCacheEntry cacheProperty(final Property prop) {
         try {
             // calculate the key
             final String name = prop.getName();
             String key = null;
-            if ( name.indexOf("_x") != -1 ) {
+            if (name.indexOf("_x") != -1) {
                 // for compatibility with older versions we use the (wrong)
                 // ISO9075 path encoding
                 key = ISO9075.decode(name);
-                if ( key.equals(name) ) {
+                if (key.equals(name)) {
                     key = null;
                 }
             }
-            if ( key == null ) {
+            if (key == null) {
                 key = Text.unescapeIllegalJcrChars(name);
             }
             JcrPropertyMapCacheEntry entry = cache.get(key);
-            if ( entry == null ) {
+            if (entry == null) {
                 entry = new JcrPropertyMapCacheEntry(prop);
                 cache.put(key, entry);
 
@@ -270,16 +271,16 @@
      */
     JcrPropertyMapCacheEntry read(final String name) {
         // check for empty key
-        if ( name.length() == 0 ) {
+        if (name.length() == 0) {
             return null;
         }
         // if the name is a path, we should handle this differently
-        if ( name.indexOf('/') != -1 ) {
+        if (name.indexOf('/') != -1) {
             // first a compatibility check with the old (wrong) ISO9075
             // encoding
             final String path = ISO9075.encodePath(name);
             try {
-                if ( node.hasProperty(path) ) {
+                if (node.hasProperty(path)) {
                     return new JcrPropertyMapCacheEntry(node.getProperty(path));
                 }
             } catch (final RepositoryException re) {
@@ -289,9 +290,9 @@
             final StringBuilder sb = new StringBuilder();
             int pos = 0;
             int lastPos = -1;
-            while ( pos < name.length() ) {
-                if ( name.charAt(pos) == '/' ) {
-                    if ( lastPos + 1 < pos ) {
+            while (pos < name.length()) {
+                if (name.charAt(pos) == '/') {
+                    if (lastPos + 1 < pos) {
                         sb.append(Text.escapeIllegalJcrChars(name.substring(lastPos + 1, pos)));
                     }
                     sb.append('/');
@@ -299,12 +300,12 @@
                 }
                 pos++;
             }
-            if ( lastPos + 1 < pos ) {
+            if (lastPos + 1 < pos) {
                 sb.append(Text.escapeIllegalJcrChars(name.substring(lastPos + 1)));
             }
             final String newPath = sb.toString();
             try {
-                if ( node.hasProperty(newPath) ) {
+                if (node.hasProperty(newPath)) {
                     return new JcrPropertyMapCacheEntry(node.getProperty(newPath));
                 }
             } catch (final RepositoryException re) {
@@ -316,7 +317,7 @@
 
         // check cache
         JcrPropertyMapCacheEntry cachedValued = cache.get(name);
-        if ( fullyRead || cachedValued != null ) {
+        if (fullyRead || cachedValued != null) {
             return cachedValued;
         }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/NodeUtil.java b/src/main/java/org/apache/sling/jcr/resource/internal/NodeUtil.java
index df852a1..595e756 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/NodeUtil.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/NodeUtil.java
@@ -25,6 +25,7 @@
 import static javax.jcr.nodetype.NodeType.NT_FROZEN_NODE;
 import static javax.jcr.nodetype.NodeType.NT_LINKED_FILE;
 
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -38,6 +39,8 @@
 import org.jetbrains.annotations.NotNull;
 
 public abstract class NodeUtil {
+    
+    private NodeUtil() {}
 
     /**
      * Update the mixin node types
@@ -46,26 +49,23 @@
      * @param mixinTypes the mixins
      * @throws RepositoryException if the repository's namespaced prefixes cannot be retrieved
      */
-    public static void handleMixinTypes(final Node node, final String[] mixinTypes)
-    throws RepositoryException {
-        final Set<String> newTypes = new HashSet<String>();
-        if ( mixinTypes != null ) {
-            for(final String value : mixinTypes ) {
-                newTypes.add(value);
-            }
+    public static void handleMixinTypes(final Node node, final String[] mixinTypes) throws RepositoryException {
+        final Set<String> newTypes = new HashSet<>();
+        if (mixinTypes != null) {
+            Collections.addAll(newTypes, mixinTypes);
         }
-        final Set<String> oldTypes = new HashSet<String>();
-        for(final NodeType mixinType : node.getMixinNodeTypes()) {
+        final Set<String> oldTypes = new HashSet<>();
+        for (final NodeType mixinType : node.getMixinNodeTypes()) {
             oldTypes.add(mixinType.getName());
         }
-        for(final String name : oldTypes) {
-            if ( !newTypes.contains(name) ) {
+        for (final String name : oldTypes) {
+            if (!newTypes.contains(name)) {
                 node.removeMixin(name);
             } else {
                 newTypes.remove(name);
             }
         }
-        for(final String name : newTypes) {
+        for (final String name : newTypes) {
             node.addMixin(name);
         }
     }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/BooleanConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/BooleanConverter.java
index 7c9e20e..dfd5fe0 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/BooleanConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/BooleanConverter.java
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.math.BigDecimal;
 import java.time.ZonedDateTime;
 import java.util.Calendar;
@@ -30,7 +32,7 @@
 
     private final Boolean value;
 
-    public BooleanConverter(final Boolean val) {
+    public BooleanConverter(@NotNull final Boolean val) {
         this.value = val;
     }
 
@@ -42,61 +44,61 @@
         return this.value.toString();
     }
 
-    private Integer getNumber() {
+    private @NotNull Integer getNumber() {
         return ( value.booleanValue() ? 1 : 0);
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toLong()
      */
-    public Long toLong() {
+    public @NotNull Long toLong() {
         return this.getNumber().longValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toByte()
      */
-    public Byte toByte() {
+    public @NotNull Byte toByte() {
         return this.getNumber().byteValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toShort()
      */
-    public Short toShort() {
+    public @NotNull Short toShort() {
         return this.getNumber().shortValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toInteger()
      */
-    public Integer toInteger() {
-        return this.getNumber().intValue();
+    public @NotNull Integer toInteger() {
+        return getNumber().intValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDouble()
      */
-    public Double toDouble() {
+    public @NotNull Double toDouble() {
         return this.getNumber().doubleValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toFloat()
      */
-    public Float toFloat() {
+    public @NotNull Float toFloat() {
         return this.getNumber().floatValue();
     }
 
     @Override
-    public ZonedDateTime toZonedDateTime() {
+    public @NotNull ZonedDateTime toZonedDateTime() {
         return new CalendarConverter(toCalendar()).toZonedDateTime();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toCalendar()
      */
-    public Calendar toCalendar() {
+    public @NotNull Calendar toCalendar() {
         final Calendar c = Calendar.getInstance();
         c.setTimeInMillis(this.toLong());
         return c;
@@ -105,21 +107,21 @@
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDate()
      */
-    public Date toDate() {
+    public @NotNull Date toDate() {
         return new Date(this.toLong());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toBoolean()
      */
-    public Boolean toBoolean() {
+    public @NotNull Boolean toBoolean() {
         return this.value;
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toBigDecimal()
      */
-    public BigDecimal toBigDecimal() {
+    public @NotNull BigDecimal toBigDecimal() {
         return new BigDecimal(this.getNumber().toString());
     }
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/CalendarConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/CalendarConverter.java
index cf24f18..4374db7 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/CalendarConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/CalendarConverter.java
@@ -23,6 +23,7 @@
 import java.util.Date;
 
 import org.apache.jackrabbit.util.ISO8601;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * A converter for Calendar
@@ -31,13 +32,13 @@
 
     private final Calendar value;
 
-    public CalendarConverter(final Calendar val) {
+    public CalendarConverter(@NotNull final Calendar val) {
         super(val.getTimeInMillis());
         this.value = val;
     }
 
     @Override
-    public ZonedDateTime toZonedDateTime() {
+    public @NotNull ZonedDateTime toZonedDateTime() {
         return ZonedDateTime.ofInstant(this.value.toInstant(), this.value.getTimeZone().toZoneId().normalized());
     }
 
@@ -45,7 +46,7 @@
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toCalendar()
      */
     @Override
-    public Calendar toCalendar() {
+    public @NotNull Calendar toCalendar() {
         return this.value;
     }
 
@@ -53,7 +54,7 @@
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDate()
      */
     @Override
-    public Date toDate() {
+    public @NotNull Date toDate() {
         return this.value.getTime();
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/Converter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/Converter.java
index 50acb7c..e1c1fd8 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/Converter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/Converter.java
@@ -18,13 +18,13 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
 
 import java.math.BigDecimal;
 import java.time.ZonedDateTime;
 import java.util.Calendar;
 import java.util.Date;
 
-
 /**
  * A converter converts a value to a specific target type.
  */
@@ -35,75 +35,75 @@
      * @return Long representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Long toLong();
+    @NotNull Long toLong();
 
     /**
      * Convert to Byte.
      * @return Byte representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Byte toByte();
+    @NotNull Byte toByte();
 
     /**
      * Convert to Short.
      * @return Short representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Short toShort();
+    @NotNull Short toShort();
 
     /**
      * Convert to Integer.
      * @return Integer representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Integer toInteger();
+    @NotNull Integer toInteger();
 
     /**
      * Convert to Double.
      * @return Double representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Double toDouble();
+    @NotNull Double toDouble();
 
     /**
      * Convert to Float.
      * @return Float representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    Float toFloat();
+    @NotNull Float toFloat();
 
     /**
      * Convert to ZonedDateTime.
      * @return Calendar representation of the converted value
      * @throws IllegalArgumentException  if the value cannot be parsed into a calendar
      */
-    ZonedDateTime toZonedDateTime();
+    @NotNull ZonedDateTime toZonedDateTime();
 
     /**
      * Convert to Calendar.
      * @return Calendar representation of the converted value
      * @throws IllegalArgumentException  if the value cannot be parsed into a calendar
      */
-    Calendar toCalendar();
+    @NotNull Calendar toCalendar();
 
     /**
      * Convert to Date.
      * @return Date representation of the converted value
      * @throws IllegalArgumentException  if the value cannot be parsed into a date
      */
-    Date toDate();
+    @NotNull Date toDate();
 
     /**
      * Convert to boolean.
      * @return  Boolean representation of the converted value
      */
-    Boolean toBoolean();
+    @NotNull Boolean toBoolean();
 
     /**
      * Convert to BigDecimal.
      * @return BigDecimal representation of the converted value
      * @throws NumberFormatException if the conversion fails
      */
-    BigDecimal toBigDecimal();
+    @NotNull BigDecimal toBigDecimal();
 
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/DateConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/DateConverter.java
index 9fdb0ff..da70240 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/DateConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/DateConverter.java
@@ -23,6 +23,7 @@
 import java.util.Date;
 
 import org.apache.jackrabbit.util.ISO8601;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * A converter for Date
@@ -31,13 +32,13 @@
 
     private final Date value;
 
-    public DateConverter(final Date val) {
+    public DateConverter(@NotNull final Date val) {
         super(val.getTime());
         this.value = val;
     }
 
     @Override
-    public ZonedDateTime toZonedDateTime() {
+    public @NotNull ZonedDateTime toZonedDateTime() {
         return new CalendarConverter(toCalendar()).toZonedDateTime();
     }
 
@@ -45,7 +46,7 @@
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toCalendar()
      */
     @Override
-    public Calendar toCalendar() {
+    public @NotNull Calendar toCalendar() {
         final Calendar c = Calendar.getInstance();
         c.setTimeInMillis(this.toLong());
         return c;
@@ -55,7 +56,7 @@
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDate()
      */
     @Override
-    public Date toDate() {
+    public @NotNull Date toDate() {
         return this.value;
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java
index 2fe32eb..2045746 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java
@@ -26,6 +26,7 @@
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -41,13 +42,15 @@
 import javax.jcr.ValueFormatException;
 
 import org.apache.commons.lang3.ArrayUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class JcrPropertyMapCacheEntry {
 
     /** Global logger */
-    private static Logger LOGGER = LoggerFactory.getLogger(JcrPropertyMapCacheEntry.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(JcrPropertyMapCacheEntry.class);
 
     /** The JCR property - only set for existing values. */
     private final Property property;
@@ -64,8 +67,7 @@
      * @param prop the property
      * @throws RepositoryException if the provided property cannot be converted to a Java Object
      */
-    public JcrPropertyMapCacheEntry(final Property prop)
-    throws RepositoryException {
+    public JcrPropertyMapCacheEntry(@NotNull final Property prop) throws RepositoryException {
         this.property = prop;
         this.isArray = prop.isMultiple();
         if (property.getType() != PropertyType.BINARY) {
@@ -81,31 +83,29 @@
      * @param node the node
      * @throws RepositoryException if the provided value cannot be stored
      */
-    public JcrPropertyMapCacheEntry(final Object value, final Node node)
-    throws RepositoryException {
+    public JcrPropertyMapCacheEntry(@NotNull final Object value, @NotNull final Node node) throws RepositoryException {
         this.property = null;
         this.propertyValue = value;
         this.isArray = value.getClass().isArray();
         // check if values can be stored in JCR
-        if ( isArray ) {
+        if (isArray) {
             final Object[] values = convertToObjectArray(value);
-            for(int i=0; i<values.length; i++) {
-                failIfCannotStore(values[i], node);
+            for (Object o : values) {
+                failIfCannotStore(o, node);
             }
         } else {
             failIfCannotStore(value, node);
         }
      }
 
-    private void failIfCannotStore(final Object value, final Node node)
-    throws RepositoryException {
+    private static void failIfCannotStore(@NotNull final Object value, @NotNull final Node node) throws RepositoryException {
         if (value instanceof InputStream) {
             // InputStream is storable and calling createValue for nothing
             // eats its contents
             return;
         }
-        final Value val = this.createValue(value, node);
-        if ( val == null ) {
+        final Value val = createValue(value, node);
+        if (val == null) {
             throw new IllegalArgumentException("Value can't be stored in the repository: " + value);
         }
     }
@@ -120,11 +120,10 @@
      * @param  node the node
      * @return the converted value
      */
-    private Value createValue(final Object obj, final Node node)
-    throws RepositoryException {
+    private static @Nullable Value createValue(@NotNull final Object obj, @NotNull final Node node) throws RepositoryException {
         final Session session = node.getSession();
         Value value = JcrResourceUtil.createValue(obj, session);
-        if ( value == null && obj instanceof Serializable ) {
+        if (value == null && obj instanceof Serializable) {
             try {
                 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 final ObjectOutputStream oos = new ObjectOutputStream(baos);
@@ -144,24 +143,24 @@
      * @param value The array
      * @return an object array
      */
-    private Object[] convertToObjectArray(final Object value) {
+    private static @NotNull Object[] convertToObjectArray(@NotNull final Object value) {
         final Object[] values;
         if (value instanceof long[]) {
-            values = ArrayUtils.toObject((long[])value);
+            values = ArrayUtils.toObject((long[]) value);
         } else if (value instanceof int[]) {
-            values = ArrayUtils.toObject((int[])value);
+            values = ArrayUtils.toObject((int[]) value);
         } else if (value instanceof double[]) {
-            values = ArrayUtils.toObject((double[])value);
+            values = ArrayUtils.toObject((double[]) value);
         } else if (value instanceof byte[]) {
-            values = ArrayUtils.toObject((byte[])value);
+            values = ArrayUtils.toObject((byte[]) value);
         } else if (value instanceof float[]) {
-            values = ArrayUtils.toObject((float[])value);
+            values = ArrayUtils.toObject((float[]) value);
         } else if (value instanceof short[]) {
-            values = ArrayUtils.toObject((short[])value);
+            values = ArrayUtils.toObject((short[]) value);
         } else if (value instanceof boolean[]) {
-            values = ArrayUtils.toObject((boolean[])value);
+            values = ArrayUtils.toObject((boolean[]) value);
         } else if (value instanceof char[]) {
-            values = ArrayUtils.toObject((char[])value);
+            values = ArrayUtils.toObject((char[]) value);
         } else {
             values = (Object[]) value;
         }
@@ -181,7 +180,7 @@
      * @return The current value
      * @throws RepositoryException If something goes wrong
      */
-    public Object getPropertyValue() throws RepositoryException {
+    public @NotNull Object getPropertyValue() throws RepositoryException {
         return this.propertyValue != null ? this.propertyValue : JcrResourceUtil.toJavaObject(property);
     }
 
@@ -189,7 +188,7 @@
      * Get the current property value.
      * @return The current value or {@code null} if not possible.
      */
-    public Object getPropertyValueOrNull() {
+    public @Nullable Object getPropertyValueOrNull() {
         try {
             return getPropertyValue();
         } catch (final RepositoryException e) {
@@ -207,8 +206,8 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T convertToType(final Class<T> type,
-            final Node node,
-            final ClassLoader dynamicClassLoader) {
+                               final Node node,
+                               final ClassLoader dynamicClassLoader) {
         T result = null;
 
         try {
@@ -227,23 +226,16 @@
 
                 final Object sourceObject = this.getPropertyValue();
                 if (targetIsArray) {
-                    result = (T) convertToArray(new Object[] {sourceObject}, type.getComponentType(), node, dynamicClassLoader);
+                    result = (T) convertToArray(new Object[]{sourceObject}, type.getComponentType(), node, dynamicClassLoader);
                 } else {
                     result = convertToType(-1, sourceObject, type, node, dynamicClassLoader);
                 }
             }
 
-        } catch (final NumberFormatException vfe) {
-            LOGGER.info("converToType: Cannot convert value of " + this.getPropertyValueOrNull()
-                    + " to " + type, vfe);
-        } catch (final IllegalArgumentException vfe) {
-            LOGGER.info("converToType: Cannot convert value of " + this.getPropertyValueOrNull()
-                    + " to " + type, vfe);
-        } catch (final ValueFormatException vfe) {
-            LOGGER.info("converToType: Cannot convert value of " + this.getPropertyValueOrNull()
-                + " to " + type, vfe);
+        } catch (final IllegalArgumentException | ValueFormatException vfe) {
+            LOGGER.info("converToType: Cannot convert value of {} to {}", getPropertyValueOrNull(), type, vfe);
         } catch (RepositoryException re) {
-            LOGGER.info("converToType: Cannot get value of " + this.getPropertyValueOrNull(), re);
+            LOGGER.info("converToType: Cannot get value of {}", getPropertyValueOrNull(), re);
         }
 
         // fall back to nothing
@@ -251,10 +243,9 @@
     }
 
     private <T> T[] convertToArray(final Object[] sourceArray,
-            final Class<T> type,
-            final Node node,
-            final ClassLoader dynamicClassLoader)
-    throws RepositoryException {
+                                   final Class<T> type,
+                                   final Node node,
+                                   final ClassLoader dynamicClassLoader) throws RepositoryException {
         List<T> values = new ArrayList<>();
         for (int i = 0; i < sourceArray.length; i++) {
             T value = convertToType(i, sourceArray[i], type, node, dynamicClassLoader);
@@ -274,8 +265,7 @@
                                 final Object initialValue,
                                 final Class<T> type,
                                 final Node node,
-                                final ClassLoader dynamicClassLoader)
-    throws RepositoryException {
+                                final ClassLoader dynamicClassLoader) throws RepositoryException {
         if ( type.isInstance(initialValue) ) {
             return (T) initialValue;
         }
@@ -312,7 +302,7 @@
                             baos.write(buffer, 0, l);
                         }
                     }
-                    value = new String(baos.toByteArray(), "UTF-8");
+                    value = new String(baos.toByteArray(), StandardCharsets.UTF_8);
                 } catch (final IOException e) {
                     throw new IllegalArgumentException(e);
                 } finally {
@@ -333,10 +323,8 @@
                         return (T)obj;
                     }
                     value = obj;
-                } catch (final ClassNotFoundException cnfe) {
+                } catch (final ClassNotFoundException | IOException cnfe) {
                      // ignore and use fallback
-                } catch (final IOException ioe) {
-                    // ignore and use fallback
                 } finally {
                     if ( ois != null ) {
                         try {
@@ -387,7 +375,7 @@
             return (T) ZonedDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId().normalized());
 
         } else if (Value.class == type) {
-            return (T) this.createValue(value, node);
+            return (T) createValue(value, node);
 
         } else if (Property.class == type) {
             return (T) this.property;
@@ -402,18 +390,18 @@
      * @param value  The object to convert
      * @return  A converter for {@code value}
      */
-    private Converter getConverter(final Object value) {
-        if ( value instanceof Number ) {
+    private static @NotNull Converter getConverter(@NotNull final Object value) {
+        if (value instanceof Number) {
             // byte, short, int, long, double, float, BigDecimal
-            return new NumberConverter((Number)value);
-        } else if ( value instanceof Boolean ) {
-            return new BooleanConverter((Boolean)value);
-        } else if ( value instanceof Date ) {
-            return new DateConverter((Date)value);
-        } else if ( value instanceof Calendar ) {
-            return new CalendarConverter((Calendar)value);
-        } else if ( value instanceof ZonedDateTime ) {
-            return new ZonedDateTimeConverter((ZonedDateTime)value);
+            return new NumberConverter((Number) value);
+        } else if (value instanceof Boolean) {
+            return new BooleanConverter((Boolean) value);
+        } else if (value instanceof Date) {
+            return new DateConverter((Date) value);
+        } else if (value instanceof Calendar) {
+            return new CalendarConverter((Calendar) value);
+        } else if (value instanceof ZonedDateTime) {
+            return new ZonedDateTimeConverter((ZonedDateTime) value);
         }
         // default string based
         return new StringConverter(value);
@@ -427,7 +415,7 @@
 
         private final ClassLoader classloader;
 
-        public PropertyObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException {
+        public PropertyObjectInputStream(@NotNull final InputStream in, @Nullable final ClassLoader classLoader) throws IOException {
             super(in);
             this.classloader = classLoader;
         }
@@ -436,9 +424,8 @@
          * @see java.io.ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
          */
         @Override
-        protected Class<?> resolveClass(final ObjectStreamClass classDesc)
-        throws IOException, ClassNotFoundException {
-            if ( this.classloader != null ) {
+        protected Class<?> resolveClass(final ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
+            if (this.classloader != null) {
                 return this.classloader.loadClass(classDesc.getName());
             }
             return super.resolveClass(classDesc);
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
index 76b7718..2907a06 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
@@ -18,6 +18,9 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.time.ZonedDateTime;
@@ -41,6 +44,8 @@
  */
 public class JcrResourceUtil {
 
+    private JcrResourceUtil() {}
+    
     /**
      * Helper method to execute a JCR query.
      *
@@ -50,8 +55,7 @@
      * @return the query's result
      * @throws RepositoryException if the {@link QueryManager} cannot be retrieved
      */
-    public static QueryResult query(Session session, String query,
-            String language) throws RepositoryException {
+    public static @NotNull QueryResult query(@NotNull Session session, @NotNull String query, @NotNull String language) throws RepositoryException {
         QueryManager qManager = session.getWorkspace().getQueryManager();
         Query q = qManager.createQuery(query, language);
         return q.execute();
@@ -64,7 +68,7 @@
      * @return the Java Object
      * @throws RepositoryException if the value cannot be converted
      */
-    public static Object toJavaObject(Value value) throws RepositoryException {
+    public static @NotNull Object toJavaObject(@NotNull Value value) throws RepositoryException {
         switch (value.getType()) {
             case PropertyType.DECIMAL:
                 return value.getDecimal();
@@ -97,24 +101,23 @@
      * @throws RepositoryException if the conversion cannot take place
      * @return the Object resulting from the conversion
      */
-    public static Object toJavaObject(Property property)
-            throws RepositoryException {
+    public static @NotNull Object toJavaObject(@NotNull Property property) throws RepositoryException {
         // multi-value property: return an array of values
         if (property.isMultiple()) {
             Value[] values = property.getValues();
             final Object firstValue = values.length > 0 ? toJavaObject(values[0]) : null;
             final Object[] result;
-            if ( firstValue instanceof Boolean ) {
+            if (firstValue instanceof Boolean) {
                 result = new Boolean[values.length];
-            } else if ( firstValue instanceof Calendar ) {
+            } else if (firstValue instanceof Calendar) {
                 result = new Calendar[values.length];
-            } else if ( firstValue instanceof Double ) {
+            } else if (firstValue instanceof Double) {
                 result = new Double[values.length];
-            } else if ( firstValue instanceof Long ) {
+            } else if (firstValue instanceof Long) {
                 result = new Long[values.length];
-            } else if ( firstValue instanceof BigDecimal) {
+            } else if (firstValue instanceof BigDecimal) {
                 result = new BigDecimal[values.length];
-            } else if ( firstValue instanceof InputStream) {
+            } else if (firstValue instanceof InputStream) {
                 result = new Object[values.length];
             } else {
                 result = new String[values.length];
@@ -143,32 +146,31 @@
      * @return the value or null if not convertible to a valid PropertyType
      * @throws RepositoryException in case of error, accessing the Repository
      */
-    public static Value createValue(final Object value, final Session session)
-    throws RepositoryException {
+    public static @Nullable Value createValue(@NotNull final Object value, @NotNull final Session session) throws RepositoryException {
         Value val;
         ValueFactory fac = session.getValueFactory();
-        if(value instanceof ZonedDateTime) {
-            val = fac.createValue(new ZonedDateTimeConverter((ZonedDateTime)value).toCalendar());
-        } else if(value instanceof Calendar) {
-            val = fac.createValue((Calendar)value);
+        if (value instanceof ZonedDateTime) {
+            val = fac.createValue(new ZonedDateTimeConverter((ZonedDateTime) value).toCalendar());
+        } else if (value instanceof Calendar) {
+            val = fac.createValue((Calendar) value);
         } else if (value instanceof InputStream) {
-            val = fac.createValue(fac.createBinary((InputStream)value));
+            val = fac.createValue(fac.createBinary((InputStream) value));
         } else if (value instanceof Node) {
-            val = fac.createValue((Node)value);
+            val = fac.createValue((Node) value);
         } else if (value instanceof BigDecimal) {
-            val = fac.createValue((BigDecimal)value);
+            val = fac.createValue((BigDecimal) value);
         } else if (value instanceof Long) {
-            val = fac.createValue((Long)value);
+            val = fac.createValue((Long) value);
         } else if (value instanceof Short) {
-            val = fac.createValue((Short)value);
+            val = fac.createValue((Short) value);
         } else if (value instanceof Integer) {
-            val = fac.createValue((Integer)value);
+            val = fac.createValue((Integer) value);
         } else if (value instanceof Number) {
-            val = fac.createValue(((Number)value).doubleValue());
+            val = fac.createValue(((Number) value).doubleValue());
         } else if (value instanceof Boolean) {
             val = fac.createValue((Boolean) value);
-        } else if ( value instanceof String ) {
-            val = fac.createValue((String)value);
+        } else if (value instanceof String) {
+            val = fac.createValue((String) value);
         } else {
             val = null;
         }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/LazyInputStream.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/LazyInputStream.java
index 9f4ab31..0ea91cb 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/LazyInputStream.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/LazyInputStream.java
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -36,7 +38,7 @@
     /** The inputstream created on demand, null if not used */
     private InputStream delegatee;
 
-    public LazyInputStream(Value value) {
+    public LazyInputStream(@NotNull Value value) {
         this.value = value;
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/NumberConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/NumberConverter.java
index dd0fc28..ce40596 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/NumberConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/NumberConverter.java
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.math.BigDecimal;
 import java.time.ZonedDateTime;
 import java.util.Calendar;
@@ -30,7 +32,7 @@
 
     private final Number value;
 
-    public NumberConverter(final Number val) {
+    public NumberConverter(@NotNull final Number val) {
         this.value = val;
     }
 
@@ -45,42 +47,42 @@
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toLong()
      */
-    public Long toLong() {
+    public @NotNull Long toLong() {
         return this.value.longValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toByte()
      */
-    public Byte toByte() {
+    public @NotNull Byte toByte() {
         return this.value.byteValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toShort()
      */
-    public Short toShort() {
+    public @NotNull Short toShort() {
         return this.value.shortValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toInteger()
      */
-    public Integer toInteger() {
+    public @NotNull Integer toInteger() {
         return this.value.intValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDouble()
      */
-    public Double toDouble() {
+    public @NotNull Double toDouble() {
         return this.value.doubleValue();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toFloat()
      */
-    public Float toFloat() {
+    public @NotNull Float toFloat() {
         return this.value.floatValue();
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/StringConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/StringConverter.java
index 9b0ef07..e289886 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/StringConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/StringConverter.java
@@ -24,6 +24,7 @@
 import java.util.Date;
 
 import org.apache.jackrabbit.util.ISO8601;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * A converter for any object based on toString()
@@ -32,7 +33,7 @@
 
     private final Object value;
 
-    public StringConverter(final Object val) {
+    public StringConverter(@NotNull final Object val) {
         this.value = val;
     }
 
@@ -47,54 +48,54 @@
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toLong()
      */
-    public Long toLong() {
+    public @NotNull Long toLong() {
         return Long.parseLong(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toByte()
      */
-    public Byte toByte() {
+    public @NotNull Byte toByte() {
         return Byte.parseByte(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toShort()
      */
-    public Short toShort() {
+    public @NotNull Short toShort() {
         return Short.parseShort(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toInteger()
      */
-    public Integer toInteger() {
+    public @NotNull Integer toInteger() {
         return Integer.parseInt(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDouble()
      */
-    public Double toDouble() {
+    public @NotNull Double toDouble() {
         return Double.parseDouble(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toFloat()
      */
-    public Float toFloat() {
+    public @NotNull Float toFloat() {
         return Float.parseFloat(this.toString());
     }
 
     @Override
-    public ZonedDateTime toZonedDateTime() {
+    public @NotNull ZonedDateTime toZonedDateTime() {
         return new CalendarConverter(toCalendar()).toZonedDateTime();
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toCalendar()
      */
-    public Calendar toCalendar() {
+    public @NotNull Calendar toCalendar() {
         final Calendar c = ISO8601.parse(toString());
         if (c == null) {
             throw new IllegalArgumentException("Not a date string: " + toString());
@@ -105,7 +106,7 @@
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toDate()
      */
-    public Date toDate() {
+    public @NotNull Date toDate() {
         final Calendar c = this.toCalendar();
         return c.getTime();
     }
@@ -113,14 +114,14 @@
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toBoolean()
      */
-    public Boolean toBoolean() {
+    public @NotNull Boolean toBoolean() {
         return Boolean.valueOf(this.toString());
     }
 
     /**
      * @see org.apache.sling.jcr.resource.internal.helper.Converter#toBigDecimal()
      */
-    public BigDecimal toBigDecimal() {
+    public @NotNull BigDecimal toBigDecimal() {
         return new BigDecimal(this.toString());
     }
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/ZonedDateTimeConverter.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/ZonedDateTimeConverter.java
index d86acf1..848f6c0 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/ZonedDateTimeConverter.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/ZonedDateTimeConverter.java
@@ -18,12 +18,14 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.time.ZonedDateTime;
 import java.util.GregorianCalendar;
 
 public class ZonedDateTimeConverter extends CalendarConverter {
 
-    public ZonedDateTimeConverter(ZonedDateTime value) {
+    public ZonedDateTimeConverter(@NotNull ZonedDateTime value) {
         super(GregorianCalendar.from(value));
     }
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java
index 35f9849..8a085cd 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java
@@ -24,6 +24,7 @@
 import java.util.NoSuchElementException;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryResult;
@@ -40,9 +41,13 @@
 import org.apache.sling.spi.resource.provider.ProviderContext;
 import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
 import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.jcr.resource.internal.helper.jcr.ContextUtil.getHelperData;
+import static org.apache.sling.jcr.resource.internal.helper.jcr.ContextUtil.getSession;
+
 public class BasicQueryLanguageProvider implements QueryLanguageProvider<JcrProviderState> {
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -59,29 +64,29 @@
     /** The provider context. */
     private final ProviderContext providerContext;
 
-    public BasicQueryLanguageProvider(final ProviderContext ctx) {
+    public BasicQueryLanguageProvider(@NotNull final ProviderContext ctx) {
         this.providerContext = ctx;
     }
 
     @Override
-    public String[] getSupportedLanguages(final ResolveContext<JcrProviderState> ctx) {
+    public @NotNull String[] getSupportedLanguages(@NotNull final ResolveContext<JcrProviderState> ctx) {
         try {
-            return ctx.getProviderState().getSession().getWorkspace().getQueryManager().getSupportedQueryLanguages();
+            return getSession(ctx).getWorkspace().getQueryManager().getSupportedQueryLanguages();
         } catch (final RepositoryException e) {
             throw new SlingException("Unable to discover supported query languages", e);
         }
     }
 
     @Override
-    public Iterator<Resource> findResources(final ResolveContext<JcrProviderState> ctx,
-            final String query,
-            final String language) {
+    public @NotNull Iterator<Resource> findResources(@NotNull final ResolveContext<JcrProviderState> ctx,
+                                                     @NotNull final String query,
+                                                     @NotNull final String language) {
         try {
-            final QueryResult res = JcrResourceUtil.query(ctx.getProviderState().getSession(), query, language);
+            final QueryResult res = JcrResourceUtil.query(getSession(ctx), query, language);
             return new JcrNodeResourceIterator(ctx.getResourceResolver(),
                     null, null,
                     res.getNodes(),
-                    ctx.getProviderState().getHelperData(),
+                    getHelperData(ctx),
                     this.providerContext.getExcludedPaths());
         } catch (final javax.jcr.query.InvalidQueryException iqe) {
             throw new QuerySyntaxException(iqe.getMessage(), query, language, iqe);
@@ -91,13 +96,13 @@
     }
 
     @Override
-    public Iterator<ValueMap> queryResources(final ResolveContext<JcrProviderState> ctx,
-            final String query,
-            final String language) {
+    public @NotNull Iterator<ValueMap> queryResources(@NotNull final ResolveContext<JcrProviderState> ctx,
+                                                      @NotNull final String query,
+                                                      @NotNull final String language) {
         final String queryLanguage = ArrayUtils.contains(getSupportedLanguages(ctx), language) ? language : DEFAULT_QUERY_LANGUAGE;
 
         try {
-            final QueryResult result = JcrResourceUtil.query(ctx.getProviderState().getSession(), query, queryLanguage);
+            final QueryResult result = JcrResourceUtil.query(getSession(ctx), query, queryLanguage);
             final String[] colNames = result.getColumnNames();
             final RowIterator rows = result.getRows();
 
@@ -112,7 +117,7 @@
                 @Override
                 public boolean hasNext() {
                     return next != null;
-                };
+                }
 
                 @Override
                 public ValueMap next() {
@@ -174,12 +179,9 @@
                 }
             };
         } catch (final javax.jcr.query.InvalidQueryException iqe) {
-            throw new QuerySyntaxException(iqe.getMessage(), query, language,
-                iqe);
+            throw new QuerySyntaxException(iqe.getMessage(), query, language, iqe);
         } catch (final RepositoryException re) {
             throw new SlingException(re.getMessage(), re);
         }
-
     }
-
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProvider.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProvider.java
index 3aa5abb..3c765ee 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProvider.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProvider.java
@@ -23,7 +23,6 @@
 import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
 
 import org.apache.jackrabbit.api.binary.BinaryDownload;
 import org.apache.jackrabbit.api.binary.BinaryDownloadOptions;
@@ -105,11 +104,11 @@
         return NodeUtil.getPrimaryProperty(node);
     }
 
-    private boolean isRelevantScopeAndOperation(@NotNull Scope scope, @NotNull Operation operation) {
+    private static boolean isRelevantScopeAndOperation(@NotNull Scope scope, @NotNull Operation operation) {
        return ((Scope.PUBLIC.equals(scope) || Scope.EXTERNAL.equals(scope)) && Operation.READ.equals(operation));
     }
 
-    private @NotNull URI getUriFromProperty(@NotNull Resource resource, @NotNull Node node, @NotNull Property binaryProperty) throws ValueFormatException, RepositoryException {
+    private @NotNull URI getUriFromProperty(@NotNull Resource resource, @NotNull Node node, @NotNull Property binaryProperty) throws RepositoryException {
         Binary binary = binaryProperty.getBinary();
         if (!(binary instanceof BinaryDownload)) {
             binary.dispose();
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ContextUtil.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ContextUtil.java
new file mode 100644
index 0000000..4845875
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ContextUtil.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.sling.jcr.resource.internal.helper.jcr;
+
+import org.apache.sling.jcr.resource.internal.HelperData;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.jetbrains.annotations.NotNull;
+
+import javax.jcr.Session;
+
+final class ContextUtil {
+
+    private ContextUtil() {}
+    
+    static @NotNull Session getSession(@NotNull ResolveContext<JcrProviderState> ctx) {
+        // NOTE: as long as the provider is active there is a state available.
+        return ctx.getProviderState().getSession();
+    }
+    
+    static @NotNull JcrItemResourceFactory getResourceFactory(@NotNull ResolveContext<JcrProviderState> ctx) {
+        // NOTE: as long as the provider is active there is a state available.
+        return ctx.getProviderState().getResourceFactory();
+    }
+
+    static @NotNull HelperData getHelperData(@NotNull ResolveContext<JcrProviderState> ctx) {
+        // NOTE: as long as the provider is active there is a state available.
+        return ctx.getProviderState().getHelperData();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java
index 94d461b..d2cab6a 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrExternalizableInputStream.java
@@ -17,9 +17,8 @@
 
 package org.apache.sling.jcr.resource.internal.helper.jcr;
 
-
-
 import org.apache.sling.api.resource.external.ExternalizableInputStream;
+import org.jetbrains.annotations.NotNull;
 
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
@@ -47,7 +46,7 @@
      * @param data the binary JCR property.
      * @param uri a public URI.
      */
-    JcrExternalizableInputStream(Property data, URI uri) {
+    JcrExternalizableInputStream(@NotNull Property data, @NotNull URI uri) {
         this.data = data;
         this.uri = uri;
     }
@@ -57,8 +56,8 @@
         return getInputStream().read();
     }
 
-    private InputStream getInputStream() throws IOException {
-        if ( inputStream == null) {
+    private @NotNull InputStream getInputStream() throws IOException {
+        if (inputStream == null) {
             try {
                 // perform lazy initialisation so that a consumer of
                 // this object can use the getURI method without triggering
@@ -74,7 +73,7 @@
     }
 
     @Override
-    public URI getURI() {
+    public @NotNull URI getURI() {
         return uri;
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
index f02a170..9d134d7 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
@@ -33,6 +33,8 @@
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,12 +56,11 @@
 
     private final ResourceMetadata metadata;
 
-    protected JcrItemResource(final ResourceResolver resourceResolver,
-                              final String path,
-                              final String version,
-                              final T item,
-                              final ResourceMetadata metadata) {
-
+    protected JcrItemResource(@NotNull final ResourceResolver resourceResolver,
+                              @NotNull final String path,
+                              @Nullable final String version,
+                              @NotNull final T item,
+                              @NotNull final ResourceMetadata metadata) {
         this.resourceResolver = resourceResolver;
         this.path = path;
         this.version = version;
@@ -71,7 +72,7 @@
      * @see org.apache.sling.api.resource.Resource#getResourceResolver()
      */
     @Override
-    public ResourceResolver getResourceResolver() {
+    public @NotNull ResourceResolver getResourceResolver() {
         return resourceResolver;
     }
 
@@ -79,7 +80,7 @@
      * @see org.apache.sling.api.resource.Resource#getPath()
      */
     @Override
-    public String getPath() {
+    public @NotNull String getPath() {
         if (version == null) {
             return path;
         } else if (version.contains(".")) {
@@ -93,7 +94,7 @@
      * @see org.apache.sling.api.resource.Resource#getResourceMetadata()
      */
     @Override
-    public ResourceMetadata getResourceMetadata() {
+    public @NotNull ResourceMetadata getResourceMetadata() {
         return metadata;
     }
 
@@ -160,6 +161,6 @@
      * Returns an iterator over the child resources or <code>null</code> if
      * there are none.
      */
-    abstract Iterator<Resource> listJcrChildren();
+    @Nullable abstract Iterator<Resource> listJcrChildren();
 
 }
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactory.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactory.java
index 6858f19..4949802 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactory.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactory.java
@@ -70,8 +70,7 @@
      */
     public JcrItemResource<?> createResource(final ResourceResolver resourceResolver, final String resourcePath,
             final Resource parent, final Map<String, String> parameters) throws RepositoryException {
-        final String jcrPath = resourcePath;
-        if (jcrPath == null) {
+        if (resourcePath == null) {
             log.debug("createResource: {} maps to an empty JCR path", resourcePath);
             return null;
         }
@@ -98,7 +97,7 @@
             }
             item = getSubitem(parentNode, subPath);
         } else {
-            item = getItemOrNull(jcrPath);
+            item = getItemOrNull(resourcePath);
         }
 
         if (item != null && version != null) {
@@ -106,7 +105,7 @@
         }
 
         if (item == null) {
-            log.debug("createResource: No JCR Item exists at path '{}'", jcrPath);
+            log.debug("createResource: No JCR Item exists at path '{}'", resourcePath);
             return null;
         } else {
             final JcrItemResource<?> resource;
@@ -141,7 +140,7 @@
         return null;
     }
 
-    private static Item getSubitem(Node node, String relPath) throws RepositoryException {
+    private static Item getSubitem(Node node, String relPath) {
         try {
             if (relPath.length() == 0) { // not using isEmpty() due to 1.5 compatibility
                 return node;
@@ -153,8 +152,7 @@
                 return null;
             }
         } catch(RepositoryException e) {
-            log.debug("getSubitem: Can't get subitem {} of {}: {}",
-                    new Object[] { relPath, node.toString(), e.toString() });
+            log.debug("getSubitem: Can't get subitem {} of {}: {}", relPath, node, e);
             return null;
         }
     }
@@ -175,7 +173,7 @@
         return item.isNode() && ((Node) item).isNodeType(NodeType.MIX_VERSIONABLE);
     }
 
-    Item getItemOrNull(String path) throws RepositoryException {
+    Item getItemOrNull(String path) {
         // Check first if the path is absolute. If it isn't, then we return null because the previous itemExists method,
         // which was replaced by this method, would have returned null as well (instead of throwing an exception).
         if (path.isEmpty() || path.charAt(0) != '/') {
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
index 2e21900..724bf07 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
@@ -25,10 +25,8 @@
 import javax.jcr.Item;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
 
 import org.apache.sling.adapter.annotations.Adaptable;
 import org.apache.sling.adapter.annotations.Adapter;
@@ -43,6 +41,7 @@
 import org.apache.sling.jcr.resource.internal.JcrModifiableValueMap;
 import org.apache.sling.jcr.resource.internal.JcrValueMap;
 import org.apache.sling.jcr.resource.internal.NodeUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,15 +70,15 @@
      * Constructor
      * @param resourceResolver
      * @param path The path of the resource (lazily initialized if null)
+     * @param version
      * @param node The Node underlying this resource
-     * @param dynamicClassLoader Dynamic class loader for loading serialized objects.
-     * @throws RepositoryException
+     * @param helper the helper data providing access to the dynamic class loader for loading serialized objects.
      */
-    public JcrNodeResource(final ResourceResolver resourceResolver,
-                           final String path,
-                           final String version,
-                           final Node node,
-                           final HelperData helper) {
+    public JcrNodeResource(@NotNull final ResourceResolver resourceResolver,
+                           @NotNull final String path,
+                           @Nullable final String version,
+                           @NotNull final Node node,
+                           @NotNull final HelperData helper) {
         super(resourceResolver, path, version, node, new JcrNodeResourceMetadata(node));
         this.helper = helper;
         this.resourceSuperType = UNSET_RESOURCE_SUPER_TYPE;
@@ -89,7 +88,7 @@
      * @see org.apache.sling.api.resource.Resource#getResourceType()
      */
     @Override
-    public String getResourceType() {
+    public @NotNull String getResourceType() {
         if ( this.resourceType == null ) {
             try {
                 this.resourceType = getResourceTypeForNode(getNode());
@@ -105,7 +104,7 @@
      * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
      */
     @Override
-    public String getResourceSuperType() {
+    public @Nullable String getResourceSuperType() {
         // Yes, this isn't how you're supposed to compare Strings, but this is intentional.
         if ( resourceSuperType == UNSET_RESOURCE_SUPER_TYPE ) {
             try {
@@ -164,7 +163,7 @@
 
     // ---------- internal -----------------------------------------------------
 
-    private Node getNode() {
+    private @NotNull Node getNode() {
         return getItem();
     }
 
@@ -173,32 +172,29 @@
      * {@link #getNode() node} is an <em>nt:file</em> or <em>nt:resource</em>
      * node. Otherwise returns <code>null</code>.
      */
-    private InputStream getInputStream() {
+    private @Nullable InputStream getInputStream() {
         // implement this for nt:file only
         final Node node = getNode();
-        if (node != null) {
+        try {
+            Property data;
             try {
-                Property data;
-                try {
-                    data = NodeUtil.getPrimaryProperty(node);
-                } catch (ItemNotFoundException infe) {
-                    // we don't actually care, but log for completeness
-                    LOGGER.debug("getInputStream: No primary items for {}", toString(), infe);
-                    data = null;
-                }
-                
-                URI uri =  convertToPublicURI();
-                if ( uri != null ) {
-                    return new JcrExternalizableInputStream(data, uri);
-                }
-                if (data != null) {
-                    return data.getBinary().getStream();
-                }
-
-            } catch (RepositoryException re) {
-                LOGGER.error("getInputStream: Cannot get InputStream for " + this,
-                    re);
+                data = NodeUtil.getPrimaryProperty(node);
+            } catch (ItemNotFoundException infe) {
+                // we don't actually care, but log for completeness
+                LOGGER.debug("getInputStream: No primary items for {}", this, infe);
+                data = null;
             }
+
+            URI uri = convertToPublicURI();
+            if (uri != null && data != null) {
+                return new JcrExternalizableInputStream(data, uri);
+            }
+            if (data != null) {
+                return data.getBinary().getStream();
+            }
+
+        } catch (RepositoryException re) { 
+            LOGGER.error("getInputStream: Cannot get InputStream for {}", this, re);
         }
 
         // fallback to non-streamable resource
@@ -210,7 +206,7 @@
      * public URI provided.
      * @return a public URI.
      */
-    private URI convertToPublicURI() {
+    private @Nullable URI convertToPublicURI() {
         for (URIProvider up : helper.getURIProviders()) {
             try {
                 return up.toURI(this, URIProvider.Scope.EXTERNAL, URIProvider.Operation.READ);
@@ -225,7 +221,7 @@
     // ---------- Descendable interface ----------------------------------------
 
     @Override
-    Iterator<Resource> listJcrChildren() {
+    @Nullable Iterator<Resource> listJcrChildren() {
         try {
             if (getNode().hasNodes()) {
                 return new JcrNodeResourceIterator(getResourceResolver(), path, version,
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java
index d23aae9..5511f44 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java
@@ -117,16 +117,15 @@
             try {
                 final Node n = nodes.nextNode();
                 final String path = getPath(n);
-                if ( path != null && this.excludedPaths.matches(path) == null ) {
-                    final Resource resource = new JcrNodeResource(resourceResolver,
-                        path, parentVersion, n, helper);
+                if (path != null && this.excludedPaths.matches(path) == null) {
+                    final Resource resource = new JcrNodeResource(resourceResolver, path, parentVersion, n, helper);
                     LOGGER.debug("seek: Returning Resource {}", resource);
                     return resource;
                 }
             } catch (final Throwable t) {
                 LOGGER.error(
-                    "seek: Problem creating Resource for next node, skipping",
-                    t);
+                        "seek: Problem creating Resource for next node, skipping",
+                        t);
             }
         }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceMetadata.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceMetadata.java
index e1bff89..6ad105b 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceMetadata.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceMetadata.java
@@ -39,6 +39,8 @@
 import javax.jcr.ValueFormatException;
 
 import org.apache.sling.api.resource.ResourceMetadata;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,7 +49,7 @@
     private static final long serialVersionUID = 1L;
 
     /** default log */
-    private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResource.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResourceMetadata.class);
 
     private final Node node;
     private Node contentNode;
@@ -89,9 +91,7 @@
         } catch (RepositoryException e) {
             // ignore
         }
-        LOGGER.info(
-            "setMetaData: Problem extracting metadata information for "
-                    + nodePath, re);
+        LOGGER.info("setMetaData: Problem extracting metadata information for {}", nodePath, re);
     }
 
     @Override
@@ -182,8 +182,7 @@
         return null;
     }
 
-    private Item getPrimaryItem(final Node node)
-    throws RepositoryException {
+    private static @Nullable Item getPrimaryItem(final @NotNull Node node) throws RepositoryException {
         String name = node.getPrimaryNodeType().getPrimaryItemName();
         if (name == null) {
             return null;
@@ -210,19 +209,19 @@
     }
 
     @Override
-    public Set<Map.Entry<String, Object>> entrySet() {
+    public @NotNull Set<Map.Entry<String, Object>> entrySet() {
         populate();
         return super.entrySet();
     }
 
     @Override
-    public Set<String> keySet() {
+    public @NotNull Set<String> keySet() {
         populate();
         return super.keySet();
     }
 
     @Override
-    public Collection<Object> values() {
+    public @NotNull Collection<Object> values() {
         populate();
         return super.values();
     }
@@ -243,14 +242,11 @@
         if (super.containsKey(key)) {
             return true;
         }
-        if (CREATION_TIME.equals(key) ||
-            CONTENT_TYPE.equals(key) ||
-            CHARACTER_ENCODING.equals(key) ||
-            MODIFICATION_TIME.equals(key) ||
-            CONTENT_LENGTH.equals(key)) {
-            return true;
-        }
-        return false;
+        return CREATION_TIME.equals(key) ||
+                CONTENT_TYPE.equals(key) ||
+                CHARACTER_ENCODING.equals(key) ||
+                MODIFICATION_TIME.equals(key) ||
+                CONTENT_LENGTH.equals(key);
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
index 5daf088..8cecb13 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
@@ -36,6 +36,8 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,11 +53,10 @@
 
     private final String resourceType;
 
-    public JcrPropertyResource(final ResourceResolver resourceResolver,
-                               final String path,
-                               final String version,
-                               final Property property)
-    throws RepositoryException {
+    public JcrPropertyResource(@NotNull final ResourceResolver resourceResolver,
+                               @NotNull final String path,
+                               @Nullable final String version,
+                               @NotNull final Property property) throws RepositoryException {
         super(resourceResolver, path, version, property, new ResourceMetadata());
         this.resourceType = getResourceTypeForNode(property.getParent())
                 + "/" + property.getName();
@@ -67,11 +68,11 @@
         this.getResourceMetadata().setContentLength(getContentLength(property));
     }
 
-    public String getResourceType() {
+    public @NotNull String getResourceType() {
         return resourceType;
     }
 
-    public String getResourceSuperType() {
+    public @Nullable String getResourceSuperType() {
         return null;
     }
 
@@ -208,13 +209,12 @@
             + ", path=" + getPath();
     }
 
-    private Property getProperty() {
+    private @NotNull Property getProperty() {
         return getItem();
     }
 
     private InputStream getInputStream() {
         Property prop = getProperty();
-
         try {
             return prop.getBinary().getStream();
         } catch (RepositoryException re) {
@@ -227,7 +227,7 @@
     }
 
     @Override
-    Iterator<Resource> listJcrChildren() {
+    @Nullable Iterator<Resource> listJcrChildren() {
         return null;
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderState.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderState.java
index b19e530..9d6edc0 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderState.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderState.java
@@ -19,12 +19,13 @@
 package org.apache.sling.jcr.resource.internal.helper.jcr;
 
 import java.io.Closeable;
-import java.io.IOException;
 
 import javax.jcr.Session;
 
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.resource.internal.HelperData;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
@@ -42,15 +43,15 @@
 
     private final HelperData helperData;
 
-    JcrProviderState(final Session session, final HelperData helperData, final boolean logout) {
+    JcrProviderState(@NotNull final Session session, @NotNull final HelperData helperData, final boolean logout) {
         this(session, helperData, logout, null, null);
     }
 
-    JcrProviderState(final Session session,
-            final HelperData helperData,
+    JcrProviderState(@NotNull final Session session,
+            @NotNull final HelperData helperData,
             final boolean logout,
-            final BundleContext bundleContext,
-            final ServiceReference<SlingRepository> repositoryRef) {
+            @Nullable final BundleContext bundleContext,
+            @Nullable final ServiceReference<SlingRepository> repositoryRef) {
         this.session = session;
         this.bundleContext = bundleContext;
         this.repositoryRef = repositoryRef;
@@ -59,20 +60,20 @@
         this.resourceFactory = new JcrItemResourceFactory(session, helperData);
     }
 
-    Session getSession() {
+    @NotNull Session getSession() {
         return session;
     }
 
-    JcrItemResourceFactory getResourceFactory() {
+    @NotNull JcrItemResourceFactory getResourceFactory() {
         return resourceFactory;
     }
 
-    HelperData getHelperData() {
+    @NotNull HelperData getHelperData() {
         return helperData;
     }
 
     @Override
-    public void close() throws IOException {
+    public void close() {
         logout();
     }
 
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java
index eb31c37..9cad076 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrProviderStateFactory.java
@@ -58,8 +58,8 @@
     private final AtomicReference<URIProvider[]> uriProviderReference;
 
     public JcrProviderStateFactory(final ServiceReference<SlingRepository> repositoryReference,
-            final SlingRepository repository,
-            final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference,
+                                   final SlingRepository repository,
+                                   final AtomicReference<DynamicClassLoaderManager> dynamicClassLoaderManagerReference,
                                    final AtomicReference<URIProvider[]> uriProviderReference) {
         this.repository = repository;
         this.repositoryReference = repositoryReference;
@@ -71,7 +71,7 @@
      *  @throws LoginException if no calling bundle info provided
      */
     @Nullable
-    private Bundle extractCallingBundle(@NotNull Map<String, Object> authenticationInfo) throws LoginException {
+    private static Bundle extractCallingBundle(@NotNull Map<String, Object> authenticationInfo) throws LoginException {
         final Object obj = authenticationInfo.get(ResourceProvider.AUTH_SERVICE_BUNDLE);
         if(obj != null && !(obj instanceof Bundle)) {
             throw new LoginException("Invalid calling bundle object in authentication info");
@@ -80,7 +80,7 @@
     }
 
     @SuppressWarnings("deprecation")
-    JcrProviderState createProviderState(final @NotNull Map<String, Object> authenticationInfo) throws LoginException {
+    @NotNull JcrProviderState createProviderState(final @NotNull Map<String, Object> authenticationInfo) throws LoginException {
         boolean isLoginAdministrative = Boolean.TRUE.equals(authenticationInfo.get(ResourceProvider.AUTH_ADMIN));
 
         // check whether a session is provided in the authenticationInfo
@@ -138,12 +138,11 @@
         return createJcrProviderState(session, true, authenticationInfo, bc);
     }
 
-    private JcrProviderState createJcrProviderState(
+    private @NotNull JcrProviderState createJcrProviderState(
             @NotNull final Session session,
             final boolean logoutSession,
             @NotNull final Map<String, Object> authenticationInfo,
-            @Nullable final BundleContext ctx
-    ) throws LoginException {
+            @Nullable final BundleContext ctx) throws LoginException {
         boolean explicitSessionUsed = (getSession(authenticationInfo) != null);
         final Session impersonatedSession = handleImpersonation(session, authenticationInfo, logoutSession, explicitSessionUsed);
         if (impersonatedSession != session && explicitSessionUsed) {
@@ -178,7 +177,7 @@
      *             If something goes wrong.
      */
     private static Session handleImpersonation(final Session session, final Map<String, Object> authenticationInfo,
-            final boolean logoutSession, boolean explicitSessionUsed) throws LoginException {
+                                               final boolean logoutSession, boolean explicitSessionUsed) throws LoginException {
         final String sudoUser = getSudoUser(authenticationInfo);
         // Do we need session.impersonate() because we are asked to impersonate another user?
         boolean needsSudo = (sudoUser != null) && !session.getUserID().equals(sudoUser);
@@ -310,7 +309,7 @@
      * @throws NullPointerException
      *             if <code>name</code> is <code>null</code>
      */
-    private static boolean isAttributeVisible(final String name) {
+    private static boolean isAttributeVisible(@NotNull final String name) {
         return !name.equals(JcrResourceConstants.AUTHENTICATION_INFO_CREDENTIALS) && !name.contains("password");
     }
 
@@ -322,7 +321,7 @@
      *            Authentication info (not {@code null}).
      * @return The configured sudo user information or <code>null</code>
      */
-    private static String getSudoUser(final Map<String, Object> authenticationInfo) {
+    private static @Nullable String getSudoUser(@NotNull final Map<String, Object> authenticationInfo) {
         final Object sudoObject = authenticationInfo.get(ResourceResolverFactory.USER_IMPERSONATION);
         if (sudoObject instanceof String) {
             return (String) sudoObject;
@@ -339,7 +338,7 @@
      *            Authentication info (not {@code null}).
      * @return The user.jcr.session property or <code>null</code>
      */
-    private static Session getSession(final Map<String, Object> authenticationInfo) {
+    private static @Nullable Session getSession(@NotNull final Map<String, Object> authenticationInfo) {
         final Object sessionObject = authenticationInfo.get(JcrResourceConstants.AUTHENTICATION_INFO_SESSION);
         if (sessionObject instanceof Session) {
             return (Session) sessionObject;
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
index f28774f..841f509 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
@@ -75,6 +75,10 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.jcr.resource.internal.helper.jcr.ContextUtil.getHelperData;
+import static org.apache.sling.jcr.resource.internal.helper.jcr.ContextUtil.getResourceFactory;
+import static org.apache.sling.jcr.resource.internal.helper.jcr.ContextUtil.getSession;
+
 @Component(name="org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderFactory",
            service = ResourceProvider.class,
            property = {
@@ -148,6 +152,7 @@
         this.stateFactory = null;
     }
 
+    @SuppressWarnings("unused")
     @Reference(name = "dynamicClassLoaderManager",
             service = DynamicClassLoaderManager.class,
             cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
@@ -155,6 +160,7 @@
         this.classLoaderManagerReference.set(dynamicClassLoaderManager);
     }
 
+    @SuppressWarnings("unused")
     protected void unbindDynamicClassLoaderManager(final DynamicClassLoaderManager dynamicClassLoaderManager) {
         this.classLoaderManagerReference.compareAndSet(dynamicClassLoaderManager, null);
     }
@@ -167,11 +173,14 @@
             bind = "bindUriProvider",
             unbind = "unbindUriProvider"
     )
+
+    @SuppressWarnings("unused")
     private void bindUriProvider(ServiceReference<URIProvider> srUriProvider, URIProvider uriProvider) {
         providers.put(srUriProvider, uriProvider);
         updateURIProviders();
     }
 
+    @SuppressWarnings("unused")
     private void unbindUriProvider(ServiceReference<URIProvider> srUriProvider) {
         providers.remove(srUriProvider);
         updateURIProviders();
@@ -225,8 +234,7 @@
                     this.repository);
                 for(final ObserverConfiguration config : this.getProviderContext().getObservationReporter().getObserverConfigurations()) {
                     logger.debug("Registering listener for {}", config.getPaths());
-                    final Closeable listener = new JcrResourceListener(this.listenerConfig,
-                            config);
+                    final Closeable listener = new JcrResourceListener(this.listenerConfig, config);
                     this.listeners.put(config, listener);
                 }
             } catch (final RepositoryException e) {
@@ -251,11 +259,7 @@
         }
         this.listeners.clear();
         if ( this.listenerConfig != null ) {
-            try {
-                this.listenerConfig.close();
-            } catch (final IOException e) {
-                // ignore this as the method above does not throw it
-            }
+            this.listenerConfig.close();
             this.listenerConfig = null;
         }
         logger.debug("Unregistered resource listeners");
@@ -305,32 +309,34 @@
      * authentication info in order to create a new resolver as needed.
      */
     @Override
-    @NotNull public JcrProviderState authenticate(final @NotNull Map<String, Object> authenticationInfo)
+    public @NotNull JcrProviderState authenticate(final @NotNull Map<String, Object> authenticationInfo)
     throws LoginException {
         return stateFactory.createProviderState(authenticationInfo);
     }
 
     @Override
-    public void logout(final @NotNull JcrProviderState state) {
-        state.logout();
+    public void logout(final @Nullable JcrProviderState state) {
+        if (state != null) {
+            state.logout();
+        }
     }
 
     @Override
     public boolean isLive(final @NotNull ResolveContext<JcrProviderState> ctx) {
-        return ctx.getProviderState().getSession().isLive();
+        return getSession(ctx).isLive();
     }
 
     @Override
-    public Resource getResource(ResolveContext<JcrProviderState> ctx, String path, ResourceContext rCtx, Resource parent) {
+    public @Nullable Resource getResource(@NotNull ResolveContext<JcrProviderState> ctx, @NotNull String path, @NotNull ResourceContext rCtx, @Nullable Resource parent) {
         try {
-            return ctx.getProviderState().getResourceFactory().createResource(ctx.getResourceResolver(), path, parent, rCtx.getResolveParameters());
+            return getResourceFactory(ctx).createResource(ctx.getResourceResolver(), path, parent, rCtx.getResolveParameters());
         } catch (RepositoryException e) {
             throw new SlingException("Can't get resource", e);
         }
     }
 
     @Override
-    public Iterator<Resource> listChildren(ResolveContext<JcrProviderState> ctx, Resource parent) {
+    public @Nullable Iterator<Resource> listChildren(@NotNull ResolveContext<JcrProviderState> ctx, @NotNull Resource parent) {
         JcrItemResource<?> parentItemResource;
 
         // short cut for known JCR resources
@@ -340,7 +346,7 @@
             // try to get the JcrItemResource for the parent path to list
             // children
             try {
-                parentItemResource = ctx.getProviderState().getResourceFactory().createResource(
+                parentItemResource = getResourceFactory(ctx).createResource(
                         parent.getResourceResolver(), parent.getPath(), null,
                         parent.getResourceMetadata().getParameterMap());
             } catch (RepositoryException re) {
@@ -365,9 +371,9 @@
                 String parentPath = ResourceUtil.getParent(child.getPath());
                 if (parentPath != null) {
                     Item childItem = ((JcrItemResource) child).getItem();
-                    Node parentNode = ctx.getProviderState().getResourceFactory().getParentOrNull(childItem, parentPath);
+                    Node parentNode = getResourceFactory(ctx).getParentOrNull(childItem, parentPath);
                     if (parentNode != null) {
-                        return new JcrNodeResource(ctx.getResourceResolver(), parentPath, null, parentNode, ctx.getProviderState().getHelperData());
+                        return new JcrNodeResource(ctx.getResourceResolver(), parentPath, null, parentNode, getHelperData(ctx));
                     }
                 }
             }
@@ -377,9 +383,9 @@
     }
 
     @Override
-    public Collection<String> getAttributeNames(final @NotNull ResolveContext<JcrProviderState> ctx) {
-        final Set<String> names = new HashSet<String>();
-        final String[] sessionNames = ctx.getProviderState().getSession().getAttributeNames();
+    public @NotNull Collection<String> getAttributeNames(final @NotNull ResolveContext<JcrProviderState> ctx) {
+        final Set<String> names = new HashSet<>();
+        final String[] sessionNames = getSession(ctx).getAttributeNames();
         for(final String name : sessionNames) {
             if ( isAttributeVisible(name) ) {
                 names.add(name);
@@ -389,81 +395,80 @@
     }
 
     @Override
-    public Object getAttribute(final @NotNull ResolveContext<JcrProviderState> ctx, final @NotNull String name) {
+    public @Nullable Object getAttribute(final @NotNull ResolveContext<JcrProviderState> ctx, final @NotNull String name) {
         if (isAttributeVisible(name)) {
             if (ResourceResolverFactory.USER.equals(name)) {
-                return ctx.getProviderState().getSession().getUserID();
+                return getSession(ctx).getUserID();
             }
-            return ctx.getProviderState().getSession().getAttribute(name);
+            return getSession(ctx).getAttribute(name);
         }
         return null;
     }
 
     @Override
-    public Resource create(final @NotNull ResolveContext<JcrProviderState> ctx, final String path, final Map<String, Object> properties)
-    throws PersistenceException {
+    public Resource create(final @NotNull ResolveContext<JcrProviderState> ctx, final String path, final Map<String, Object> properties) throws PersistenceException {
         // check for node type
         final Object nodeObj = (properties != null ? properties.get(JcrConstants.JCR_PRIMARYTYPE) : null);
         // check for sling:resourcetype
         final String nodeType;
-        if ( nodeObj != null ) {
+        if (nodeObj != null) {
             nodeType = nodeObj.toString();
         } else {
-            final Object rtObj =  (properties != null ? properties.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) : null);
+            final Object rtObj = (properties != null ? properties.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) : null);
             boolean isNodeType = false;
-            if ( rtObj != null ) {
+            if (rtObj != null) {
                 final String resourceType = rtObj.toString();
-                if ( resourceType.indexOf(':') != -1 && resourceType.indexOf('/') == -1 ) {
+                if (resourceType.indexOf(':') != -1 && resourceType.indexOf('/') == -1) {
                     try {
-                        ctx.getProviderState().getSession().getWorkspace().getNodeTypeManager().getNodeType(resourceType);
+                        getSession(ctx).getWorkspace().getNodeTypeManager().getNodeType(resourceType);
                         isNodeType = true;
                     } catch (final RepositoryException ignore) {
                         // we expect this, if this isn't a valid node type, therefore ignoring
                     }
                 }
             }
-            if ( isNodeType ) {
+            if (isNodeType) {
                 nodeType = rtObj.toString();
             } else {
                 nodeType = null;
             }
         }
         final String jcrPath = path;
-        if ( jcrPath == null ) {
+        if (jcrPath == null) {
             throw new PersistenceException("Unable to create node at " + path, null, path, null);
         }
         Node node = null;
         try {
             final int lastPos = jcrPath.lastIndexOf('/');
             final Node parent;
-            if ( lastPos == 0 ) {
-                parent = ctx.getProviderState().getSession().getRootNode();
+            if (lastPos == 0) {
+                parent = getSession(ctx).getRootNode();
             } else {
-                parent = (Node) ctx.getProviderState().getSession().getItem(jcrPath.substring(0, lastPos));
+                parent = (Node) getSession(ctx).getItem(jcrPath.substring(0, lastPos));
             }
             final String name = jcrPath.substring(lastPos + 1);
-            if ( nodeType != null ) {
+            if (nodeType != null) {
                 node = parent.addNode(name, nodeType);
             } else {
                 node = parent.addNode(name);
             }
 
-            if ( properties != null ) {
+            if (properties != null) {
                 // create modifiable map
-                final JcrModifiableValueMap jcrMap = new JcrModifiableValueMap(node, ctx.getProviderState().getHelperData());
+                final JcrModifiableValueMap jcrMap = new JcrModifiableValueMap(node, getHelperData(ctx));
                 // check mixin types first
                 final Object value = properties.get(JcrConstants.JCR_MIXINTYPES);
-                if ( value != null ) {
+                if (value != null) {
                     jcrMap.put(JcrConstants.JCR_MIXINTYPES, value);
                 }
-                for(final Map.Entry<String, Object> entry : properties.entrySet()) {
-                    if ( !IGNORED_PROPERTIES.contains(entry.getKey()) ) {
+                for (final Map.Entry<String, Object> entry : properties.entrySet()) {
+                    if (!IGNORED_PROPERTIES.contains(entry.getKey())) {
                         try {
                             jcrMap.put(entry.getKey(), entry.getValue());
                         } catch (final IllegalArgumentException iae) {
                             try {
                                 node.remove();
-                            } catch ( final RepositoryException re) {
+                            } catch (final RepositoryException re) {
                                 // we ignore this
                             }
                             throw new PersistenceException(iae.getMessage(), iae, path, entry.getKey());
@@ -472,7 +477,7 @@
                 }
             }
 
-            return new JcrNodeResource(ctx.getResourceResolver(), path, null, node, ctx.getProviderState().getHelperData());
+            return new JcrNodeResource(ctx.getResourceResolver(), path, null, node, getHelperData(ctx));
         } catch (final RepositoryException e) {
             throw new PersistenceException("Unable to create node at " + jcrPath, e, path, null);
         }
@@ -528,7 +533,7 @@
                     logger.debug("delete: {} maps to an empty JCR path", resource.getPath());
                     throw new PersistenceException("Unable to delete resource", null, resource.getPath(), null);
                 }
-                item = ctx.getProviderState().getSession().getItem(jcrPath);
+                item = getSession(ctx).getItem(jcrPath);
             }
             item.remove();
         } catch (final RepositoryException e) {
@@ -539,7 +544,7 @@
     @Override
     public void revert(final @NotNull ResolveContext<JcrProviderState> ctx) {
         try {
-            ctx.getProviderState().getSession().refresh(false);
+            getSession(ctx).refresh(false);
         } catch (final RepositoryException ignore) {
             logger.warn("Unable to revert pending changes.", ignore);
         }
@@ -549,7 +554,7 @@
     public void commit(final @NotNull ResolveContext<JcrProviderState> ctx)
     throws PersistenceException {
         try {
-            ctx.getProviderState().getSession().save();
+            getSession(ctx).save();
         } catch (final RepositoryException e) {
             throw new PersistenceException("Unable to commit changes to session.", e);
         }
@@ -558,7 +563,7 @@
     @Override
     public boolean hasChanges(final @NotNull ResolveContext<JcrProviderState> ctx) {
         try {
-            return ctx.getProviderState().getSession().hasPendingChanges();
+            return getSession(ctx).hasPendingChanges();
         } catch (final RepositoryException ignore) {
             logger.warn("Unable to check session for pending changes.", ignore);
         }
@@ -568,7 +573,7 @@
     @Override
     public void refresh(final @NotNull ResolveContext<JcrProviderState> ctx) {
         try {
-            ctx.getProviderState().getSession().refresh(true);
+            getSession(ctx).refresh(true);
         } catch (final RepositoryException ignore) {
             logger.warn("Unable to refresh session.", ignore);
         }
@@ -578,7 +583,7 @@
     @Override
     public @Nullable <AdapterType> AdapterType adaptTo(final @NotNull ResolveContext<JcrProviderState> ctx,
             final @NotNull Class<AdapterType> type) {
-        Session session = ctx.getProviderState().getSession();
+        Session session = getSession(ctx);
         if (type == Session.class) {
             return (AdapterType) session;
         } else if (type == Principal.class) {
@@ -602,20 +607,19 @@
     }
 
     @Override
-    public boolean copy(final  @NotNull ResolveContext<JcrProviderState> ctx,
-            final String srcAbsPath,
-            final String destAbsPath) throws PersistenceException {
+    public boolean copy(final @NotNull ResolveContext<JcrProviderState> ctx,
+                        final @NotNull String srcAbsPath,
+                        final @NotNull String destAbsPath) {
         return false;
     }
 
     @Override
-    public boolean move(final  @NotNull ResolveContext<JcrProviderState> ctx,
-            final String srcAbsPath,
-            final String destAbsPath) throws PersistenceException {
-        final String srcNodePath = srcAbsPath;
+    public boolean move(final @NotNull ResolveContext<JcrProviderState> ctx,
+                        final @NotNull String srcAbsPath,
+                        final @NotNull String destAbsPath) throws PersistenceException {
         final String dstNodePath = destAbsPath + '/' + ResourceUtil.getName(srcAbsPath);
         try {
-            ctx.getProviderState().getSession().move(srcNodePath, dstNodePath);
+            getSession(ctx).move(srcAbsPath, dstNodePath);
             return true;
         } catch (final RepositoryException e) {
             throw new PersistenceException("Unable to move resource to " + destAbsPath, e, srcAbsPath, null);
@@ -625,7 +629,7 @@
     @Override
     public @Nullable QueryLanguageProvider<JcrProviderState> getQueryLanguageProvider() {
         final ProviderContext ctx = this.getProviderContext();
-        if ( ctx != null ) {
+        if (ctx != null) {
             return new BasicQueryLanguageProvider(ctx);
         }
         return null;
diff --git a/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java b/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java
index f4882ec..f8801dc 100644
--- a/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java
+++ b/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java
@@ -50,8 +50,7 @@
                 bindings.put(PROP_CURRENT_NODE, node);
             }
             if (bindings.get(PROP_CURRENT_SESSION) == null) {
-                final Session session = resource.getResourceResolver().adaptTo(
-                        Session.class);
+                final Session session = resource.getResourceResolver().adaptTo(Session.class);
                 if (session != null) {
                     bindings.put(PROP_CURRENT_SESSION, session);
                 }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/AssertCalendar.java b/src/test/java/org/apache/sling/jcr/resource/internal/AssertCalendar.java
index b151853..652c38b 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/AssertCalendar.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/AssertCalendar.java
@@ -21,6 +21,8 @@
 import java.util.Calendar;
 
 public final class AssertCalendar {
+    
+    private AssertCalendar() {}
 
     /**
      * Asserts that two calendars are equal.
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java
index 073e7e8..e5ca3df 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiableValueMapTest.java
@@ -49,14 +49,10 @@
 import org.apache.jackrabbit.util.Text;
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.internal.helper.jcr.SlingRepositoryTestBase;
 
 public class JcrModifiableValueMapTest extends SlingRepositoryTestBase {
 
-    private String rootPath;
-
     private Node rootNode;
 
     public static final byte[] TEST_BYTE_ARRAY = {'T', 'e', 's', 't'};
@@ -65,21 +61,20 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        rootPath = "/test_" + System.currentTimeMillis();
+        String rootPath = "/test_" + System.currentTimeMillis();
         rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
             "nt:unstructured");
 
         final Map<String, Object> values = this.initialSet();
         for(Map.Entry<String, Object> entry : values.entrySet()) {
-            setProperty(rootNode, entry.getKey().toString(), entry.getValue());
+            setProperty(rootNode, entry.getKey(), entry.getValue());
         }
         getSession().save();
     }
 
     private void setProperty(final Node node,
             final String propertyName,
-            final Object propertyValue)
-    throws RepositoryException {
+            final Object propertyValue) throws RepositoryException {
         if ( propertyValue == null ) {
             node.setProperty(propertyName, (String)null);
         } else if ( propertyValue.getClass().isArray() ) {
@@ -134,12 +129,12 @@
         super.tearDown();
     }
 
-    private HelperData getHelperData() throws Exception {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
+    private HelperData getHelperData() {
+        return new HelperData(new AtomicReference<>(), new AtomicReference<>());
     }
 
     private Map<String, Object> initialSet() {
-        final Map<String, Object> values = new HashMap<String, Object>();
+        final Map<String, Object> values = new HashMap<>();
         values.put("string", "test");
         values.put("long", 1L);
         values.put("bool", Boolean.TRUE);
@@ -152,8 +147,7 @@
         pvm.put("binary", stream);
         getSession().save();
         final ValueMap valueMap2 = new JcrValueMap(this.rootNode, getHelperData());
-        assertTrue("The read stream is not what we wrote.", IOUtils.toString(valueMap2.get("binary", InputStream.class)).equals
-                (TEST_BYTE_ARRAY_TO_STRING));
+        assertEquals("The read stream is not what we wrote.", IOUtils.toString(valueMap2.get("binary", InputStream.class)), TEST_BYTE_ARRAY_TO_STRING);
     }
 
     public void testPut()
@@ -191,7 +185,7 @@
 
         final Object removedValue = pvm.remove(key);
         assertTrue(removedValue instanceof Long);
-        assertTrue(removedValue == longValue);
+        assertSame(removedValue, longValue);
         assertFalse(pvm.containsKey(key));
     }
 
@@ -203,7 +197,7 @@
         assertNull(pvm.get("something"));
 
         // now put a serializable object
-        final List<String> strings = new ArrayList<String>();
+        final List<String> strings = new ArrayList<>();
         strings.add("a");
         strings.add("b");
         pvm.put("something", strings);
@@ -241,7 +235,7 @@
     }
 
     private Set<String> getMixinNodeTypes(final Node node) throws RepositoryException {
-        final Set<String> mixinTypes = new HashSet<String>();
+        final Set<String> mixinTypes = new HashSet<>();
         for(final NodeType mixinNodeType : node.getMixinNodeTypes() ) {
             mixinTypes.add(mixinNodeType.getName());
         }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerScalabilityTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerScalabilityTest.java
deleted file mode 100644
index 9a896ed..0000000
--- a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerScalabilityTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.sling.jcr.resource.internal;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Workspace;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.ObservationManager;
-
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.jcr.resource.internal.helper.jcr.SlingRepositoryProvider;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ObserverConfiguration;
-import org.apache.sling.spi.resource.provider.ProviderContext;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.osgi.framework.InvalidSyntaxException;
-
-/**
- * This test case asserts that JcrResourceListener scales to an
- * arbitrary number of events.
- */
-public class JcrResourceListenerScalabilityTest {
-
-    private JcrListenerBaseConfig config;
-
-    private JcrResourceListener jcrResourceListener;
-
-    private EventIterator events;
-
-    @SuppressWarnings("deprecation")
-    @Before
-    public void setUp() throws Exception {
-        ObservationManager observationManager = mock(ObservationManager.class);
-
-        Workspace workspace = mock(Workspace.class);
-        when(workspace.getObservationManager()).thenReturn(observationManager);
-
-        Session session = mock(Session.class);
-        when(session.getWorkspace()).thenReturn(workspace);
-
-        SlingRepository repository = mock(SlingRepository.class);
-        when(repository.loginAdministrative(null)).thenReturn(session);
-
-        final ProviderContext ctx = new SimpleProviderContext();
-        this.config = new JcrListenerBaseConfig(ctx.getObservationReporter(),
-                SlingRepositoryProvider.getRepository());
-        jcrResourceListener = new JcrResourceListener(this.config, ctx.getObservationReporter().getObserverConfigurations().get(0));
-
-        Event event = mock(MockEvent.class);
-        events = mock(EventIterator.class);
-        when(events.hasNext()).thenReturn(true);
-        when(event.getPath()).thenCallRealMethod();
-        when(event.getType()).thenReturn(Event.NODE_ADDED);
-        when(events.nextEvent()).thenReturn(event);
-    }
-
-    @Ignore("SLING-3399")  // FIXME SLING-3399
-    @Test
-    public void testManyEvents() throws RepositoryException, InterruptedException, InvalidSyntaxException {
-        jcrResourceListener.onEvent(events);
-    }
-
-    private abstract static class MockEvent implements Event {
-        int count;
-
-        @Override
-        public String getPath() throws RepositoryException {
-            return "path-" + count++;
-        }
-    }
-
-    private static class SimpleProviderContext implements ProviderContext {
-        @Override
-        public ObservationReporter getObservationReporter() {
-            return new ObservationReporter() {
-
-                @Override
-                public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) {
-                }
-
-                @Override
-                public void reportChanges(ObserverConfiguration config, Iterable<ResourceChange> changes,
-                        boolean distribute) {
-                }
-
-                @Override
-                public List<ObserverConfiguration> getObserverConfigurations() {
-                    ObserverConfiguration config = new ObserverConfiguration() {
-
-                        @Override
-                        public boolean includeExternal() {
-                            return true;
-                        }
-
-                        @Override
-                        public PathSet getPaths() {
-                            return PathSet.fromStrings("/");
-                        }
-
-                        @Override
-                        public PathSet getExcludedPaths() {
-                            return PathSet.fromPaths();
-                        }
-
-                        @Override
-                        public Set<ChangeType> getChangeTypes() {
-                            return EnumSet.allOf(ChangeType.class);
-                        }
-
-                        @Override
-                        public boolean matches(String path) {
-                            return true;
-                        }
-
-                        @Override
-                        public Set<String> getPropertyNamesHint() {
-                            return new HashSet<String>();
-                        }
-                    };
-                    return Collections.singletonList(config);
-                }
-            };
-        }
-
-        @Override
-        public PathSet getExcludedPaths() {
-            return PathSet.fromPaths();
-        }
-    }
-}
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
index d491210..43a8765 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
@@ -30,8 +30,6 @@
 import java.util.Set;
 
 import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -44,6 +42,7 @@
 import org.apache.sling.jcr.resource.internal.helper.jcr.SlingRepositoryProvider;
 import org.apache.sling.spi.resource.provider.ObservationReporter;
 import org.apache.sling.spi.resource.provider.ObserverConfiguration;
+import org.jetbrains.annotations.NotNull;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -59,13 +58,13 @@
 
     private Session adminSession;
 
-    private String createdPath = "/test" + System.currentTimeMillis() + "-create";
+    private final String createdPath = "/test" + System.currentTimeMillis() + "-create";
 
-    private String pathToDelete = "/test" + System.currentTimeMillis() + "-delete";
+    private final String pathToDelete = "/test" + System.currentTimeMillis() + "-delete";
 
-    private String pathToModify = "/test" + System.currentTimeMillis() + "-modify";
+    private final String pathToModify = "/test" + System.currentTimeMillis() + "-modify";
 
-    private final List<ResourceChange> events = synchronizedList(new ArrayList<ResourceChange>());
+    private final List<ResourceChange> events = synchronizedList(new ArrayList<>());
 
     SlingRepository repository;
 
@@ -79,23 +78,22 @@
                 new SlingRepository() {
 
                     @Override
-                    public Session login(Credentials credentials, String workspaceName)
-                            throws LoginException, NoSuchWorkspaceException, RepositoryException {
+                    public Session login(Credentials credentials, String workspaceName) throws RepositoryException {
                         return repository.login(credentials, workspaceName);
                     }
 
                     @Override
-                    public Session login(String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
+                    public Session login(String workspaceName) throws RepositoryException {
                         return repository.login(workspaceName);
                     }
 
                     @Override
-                    public Session login(Credentials credentials) throws LoginException, RepositoryException {
+                    public Session login(Credentials credentials) throws RepositoryException {
                         return repository.login(credentials);
                     }
 
                     @Override
-                    public Session login() throws LoginException, RepositoryException {
+                    public Session login() throws RepositoryException {
                         return repository.login();
                     }
 
@@ -130,12 +128,12 @@
                     }
 
                     @Override
-                    public Session loginService(String subServiceName, String workspace) throws LoginException, RepositoryException {
+                    public Session loginService(String subServiceName, String workspace) throws RepositoryException {
                         return repository.loginAdministrative(workspace);
                     }
 
                     @Override
-                    public Session loginAdministrative(String workspace) throws LoginException, RepositoryException {
+                    public Session loginAdministrative(String workspace) throws RepositoryException {
                         return repository.loginAdministrative(workspace);
                     }
 
@@ -150,7 +148,7 @@
     }
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         if ( adminSession != null ) {
             adminSession.logout();
             adminSession = null;
@@ -169,9 +167,9 @@
     public void testSimpleOperations() throws Exception {
         generateEvents(adminSession);
         assertEquals("Received: " + events, 5, events.size());
-        final Set<String> addPaths = new HashSet<String>();
-        final Set<String> modifyPaths = new HashSet<String>();
-        final Set<String> removePaths = new HashSet<String>();
+        final Set<String> addPaths = new HashSet<>();
+        final Set<String> modifyPaths = new HashSet<>();
+        final Set<String> removePaths = new HashSet<>();
 
         for (final ResourceChange event : events) {
             if (event.getType() == ChangeType.ADDED) {
@@ -229,7 +227,7 @@
 
             @Override
             public Set<String> getPropertyNamesHint() {
-                return null;
+                return Collections.emptySet();
             }
         };
         this.config.unregister(this.listener);
@@ -250,11 +248,11 @@
 
         this.events.clear();
 
-        try ( final JcrResourceListener l = new JcrResourceListener(this.config, observerConfig)) {
+        try (final JcrResourceListener l = new JcrResourceListener(this.config, observerConfig)) {
             final String rootName = "test_" + System.currentTimeMillis();
-            for ( final String path : new String[] {"/libs", "/", "/apps", "/content"}) {
+            for (final String path : new String[]{"/libs", "/", "/apps", "/content"}) {
                 final Node parent;
-                if ( !session.nodeExists(path) ) {
+                if (!session.nodeExists(path)) {
                     parent = createNode(session, path);
                 } else {
                     parent = session.getNode(path);
@@ -270,9 +268,9 @@
             }
             System.out.println("Events = " + events);
             assertEquals("Received: " + events, 6, events.size());
-            final Set<String> addPaths = new HashSet<String>();
-            final Set<String> modifyPaths = new HashSet<String>();
-            final Set<String> removePaths = new HashSet<String>();
+            final Set<String> addPaths = new HashSet<>();
+            final Set<String> modifyPaths = new HashSet<>();
+            final Set<String> removePaths = new HashSet<>();
 
             for (final ResourceChange event : events) {
                 if (event.getType() == ChangeType.ADDED) {
@@ -342,7 +340,7 @@
         }
 
         @Override
-        public List<ObserverConfiguration> getObserverConfigurations() {
+        public @NotNull List<ObserverConfiguration> getObserverConfigurations() {
             ObserverConfiguration config = new ObserverConfiguration() {
 
                 @Override
@@ -372,14 +370,14 @@
 
                 @Override
                 public Set<String> getPropertyNamesHint() {
-                    return new HashSet<String>();
+                    return Collections.emptySet();
                 }
             };
             return Collections.singletonList(config);
         }
 
         @Override
-        public void reportChanges(ObserverConfiguration config, Iterable<ResourceChange> changes, boolean distribute) {
+        public void reportChanges(@NotNull ObserverConfiguration config, @NotNull Iterable<ResourceChange> changes, boolean distribute) {
             this.reportChanges(changes, distribute);
         }
     }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidatorTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidatorTest.java
index 6a9c3bd..ad34fbd 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidatorTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/JcrSystemUserValidatorTest.java
@@ -18,15 +18,14 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.util.Collections;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.naming.NamingException;
 
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.user.Group;
@@ -54,17 +53,18 @@
     public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
 
     @Before
-    public void setUp() throws IllegalArgumentException, IllegalAccessException, RepositoryException, NamingException,
-            NoSuchFieldException, SecurityException {
+    public void setUp() throws Exception {
         jcrSystemUserValidator = new JcrSystemUserValidator();
         final Field repositoryField = jcrSystemUserValidator.getClass().getDeclaredField("repository");
         repositoryField.setAccessible(true);
 
         final SlingRepository repository = context.getService(SlingRepository.class);
+        assertNotNull(repository);
         assertEquals("Apache Jackrabbit Oak", repository.getDescriptor("jcr.repository.name"));
         repositoryField.set(jcrSystemUserValidator, repository);
 
         session = (JackrabbitSession) context.resourceResolver().adaptTo(Session.class);
+        assertNotNull(session);
         UserManager userManager = session.getUserManager();
         group = userManager.createGroup(GROUP_ADMINISTRATORS);
         systemUser = userManager.createSystemUser(SYSTEM_USER_ID, null);
@@ -80,7 +80,7 @@
         session.save();
     }
 
-    private void setAllowOnlySystemUsers(boolean allowOnlySystemUsers) throws Exception {
+    private void setAllowOnlySystemUsers(boolean allowOnlySystemUsers) {
         final JcrSystemUserValidator.Config config = new JcrSystemUserValidator.Config() {
             @Override
             public Class<? extends Annotation> annotationType() {
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
index 1e93ed8..95f67ed 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
@@ -31,8 +31,6 @@
 import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.internal.HelperData;
 import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResourceIterator;
 import org.apache.sling.testing.mock.jcr.MockJcr;
@@ -42,7 +40,7 @@
 public class JcrNodeResourceIteratorTest extends TestCase {
 
     private HelperData getHelperData() {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
+        return new HelperData(new AtomicReference<>(), new AtomicReference<>());
     }
 
     public void testEmpty() {
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntryTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntryTest.java
index 34e4719..11ea94e 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntryTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntryTest.java
@@ -18,60 +18,73 @@
  */
 package org.apache.sling.jcr.resource.internal.helper;
 
-import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
 
 import org.junit.Test;
 
+import javax.jcr.Node;
+
 /**
  * Testcase for {@link JcrPropertyMapCacheEntry}
  */
 public class JcrPropertyMapCacheEntryTest {
+    
+    private final Node node = mock(Node.class);
 
     @Test
     public void testByteArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Byte[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new byte[0], null));
+        new JcrPropertyMapCacheEntry(new Byte[0], node);
+        new JcrPropertyMapCacheEntry(new byte[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testShortArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Short[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new short[0], null));
+        new JcrPropertyMapCacheEntry(new Short[0], node);
+        new JcrPropertyMapCacheEntry(new short[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testIntArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Integer[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new int[0], null));
+        new JcrPropertyMapCacheEntry(new Integer[0], node);
+        new JcrPropertyMapCacheEntry(new int[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testLongArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Long[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new long[0], null));
+        new JcrPropertyMapCacheEntry(new Long[0], node);
+        new JcrPropertyMapCacheEntry(new long[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testFloatArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Float[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new float[0], null));
+        new JcrPropertyMapCacheEntry(new Float[0], node);
+        new JcrPropertyMapCacheEntry(new float[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testDoubleArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Double[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new double[0], null));
+        new JcrPropertyMapCacheEntry(new Double[0], node);
+        new JcrPropertyMapCacheEntry(new double[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testBooleanArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Boolean[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new boolean[0], null));
+        new JcrPropertyMapCacheEntry(new Boolean[0], node);
+        new JcrPropertyMapCacheEntry(new boolean[0], node);
+        verifyZeroInteractions(node);
     }
 
     @Test
     public void testCharArray() throws Exception {
-        assertNotNull(new JcrPropertyMapCacheEntry(new Character[0], null));
-        assertNotNull(new JcrPropertyMapCacheEntry(new char[0], null));
+        new JcrPropertyMapCacheEntry(new Character[0], node);
+        new JcrPropertyMapCacheEntry(new char[0], node);
+        verifyZeroInteractions(node);
     }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProviderTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProviderTest.java
index 00d1ba5..1d77f66 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProviderTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/BinaryDownloadUriProviderTest.java
@@ -19,6 +19,7 @@
 package org.apache.sling.jcr.resource.internal.helper.jcr;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 
@@ -32,7 +33,6 @@
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.ValueFormatException;
 
 import org.apache.jackrabbit.api.binary.BinaryDownload;
 import org.apache.jackrabbit.api.binary.BinaryDownloadOptions;
@@ -42,6 +42,7 @@
 import org.apache.sling.api.resource.external.URIProvider.Scope;
 import org.apache.sling.testing.mock.sling.ResourceResolverType;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.jetbrains.annotations.NotNull;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -58,7 +59,6 @@
     @Rule
     public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
 
-    private Session session;
     private BinaryDownloadUriProvider uriProvider;
     private Resource fileResource;
 
@@ -71,7 +71,8 @@
     @Before
     public void setUp() throws IOException, RepositoryException {
         uriProvider = new BinaryDownloadUriProvider(false);
-        session = context.resourceResolver().adaptTo(Session.class);
+        Session session = context.resourceResolver().adaptTo(Session.class);
+        assertNotNull(session);
         try (InputStream input = this.getClass().getResourceAsStream("/SLING-INF/nodetypes/folder.cnd")) {
             JcrUtils.putFile(session.getRootNode(), "test", "myMimeType", input);
         }
@@ -79,10 +80,10 @@
     }
 
     @Test
-    public void testMockedProperty() throws ValueFormatException, RepositoryException, URISyntaxException {
+    public void testMockedProperty() throws RepositoryException, URISyntaxException {
         uriProvider = new BinaryDownloadUriProvider(false) {
             @Override
-            protected Property getPrimaryProperty(Node node) throws RepositoryException {
+            protected @NotNull Property getPrimaryProperty(@NotNull Node node) {
                 return property;
             }
         };
@@ -99,7 +100,7 @@
     }
 
     @Test
-    public void testPropertyWithoutExternallyAccessibleBlobStore() throws URISyntaxException, RepositoryException, IOException {
+    public void testPropertyWithoutExternallyAccessibleBlobStore() {
          IllegalArgumentException e = assertThrows(IllegalArgumentException.class, ()-> uriProvider.toURI(fileResource, Scope.EXTERNAL, Operation.READ));
          assertEquals("Cannot provide url for downloading the binary property at '/test/jcr:content/jcr:data'", e.getMessage());
     }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java
index a1c4dc9..89ee80c 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceFactoryTest.java
@@ -23,8 +23,6 @@
 import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.internal.HelperData;
 
 import javax.jcr.GuestCredentials;
@@ -32,9 +30,8 @@
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.security.Privilege;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -54,18 +51,13 @@
     protected void setUp() throws Exception {
         super.setUp();
         final Session session = getSession();
-        node = JcrUtils.getOrCreateByPath(EXISTING_NODE_PATH, "nt:unstructured", session);
+        node = JcrUtils.getOrCreateByPath(EXISTING_NODE_PATH, NodeType.NT_UNSTRUCTURED, session);
         session.save();
 
         nonJackrabbitSession = (Session) Proxy.newProxyInstance(
                 getClass().getClassLoader(),
                 new Class<?>[]{Session.class},
-                new InvocationHandler() {
-            @Override
-            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                return method.invoke(session, args);
-            }
-        });
+                (proxy, method, args) -> method.invoke(session, args));
 
         AccessControlUtils.allow(node, EveryonePrincipal.NAME, Privilege.JCR_READ);
         session.save();
@@ -98,7 +90,7 @@
     }
 
     private void compareGetItemOrNull(String path, String expectedPath) throws RepositoryException {
-        HelperData helper = new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
+        HelperData helper = new HelperData(new AtomicReference<>(), new AtomicReference<>());
         Item item1 = new JcrItemResourceFactory(session, helper).getItemOrNull(path);
         Item item2 = new JcrItemResourceFactory(nonJackrabbitSession, helper).getItemOrNull(path);
         if (expectedPath == null) {
@@ -149,7 +141,7 @@
     }
  
     private void compareGetParentOrNull(Session s, String path, boolean nullExpected) throws RepositoryException {
-        HelperData helper = new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
+        HelperData helper = new HelperData(new AtomicReference<>(), new AtomicReference<>());
 
         String parentPath = PathUtils.getParentPath(path);
         Node parent = new JcrItemResourceFactory(s, helper).getParentOrNull(s.getItem(path), parentPath);
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java
index ba57e11..933cc9f 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java
@@ -26,10 +26,8 @@
 
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
-import org.junit.Ignore;
 
-@Ignore
-public class JcrItemResourceTestBase extends SlingRepositoryTestBase {
+public abstract class JcrItemResourceTestBase extends SlingRepositoryTestBase {
 
     protected static final long TEST_MODIFIED = System.currentTimeMillis();
 
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
index 56f30ca..245283d 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
@@ -20,6 +20,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
@@ -34,17 +35,20 @@
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.api.JcrResourceConstants;
 import org.apache.sling.jcr.resource.internal.HelperData;
 
+import static org.mockito.Mockito.mock;
+
 public class JcrNodeResourceTest extends JcrItemResourceTestBase {
 
-    private HelperData getHelperData() throws Exception {
-        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
+    private HelperData getHelperData() {
+        return new HelperData(new AtomicReference<>(), new AtomicReference<>());
     }
+    
+    private final ResourceResolver resourceResolver = mock(ResourceResolver.class);
 
     public void testLinkedFile() throws Exception {
         String fileName = "file";
@@ -61,7 +65,7 @@
         linkedFile.setProperty(JcrConstants.JCR_CONTENT, file);
         session.save();
 
-        JcrNodeResource linkedFileResource = new JcrNodeResource(null, linkedFile.getPath(), null, linkedFile, getHelperData());
+        JcrNodeResource linkedFileResource = new JcrNodeResource(resourceResolver, linkedFile.getPath(), null, linkedFile, getHelperData());
         assertEquals(TEST_DATA, linkedFileResource.adaptTo(InputStream.class));
 
     }
@@ -76,7 +80,7 @@
         getSession().save();
 
         file = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, file.getPath(), null, file, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, file.getPath(), null, file, getHelperData());
 
         assertEquals(file.getPath(), jnr.getPath());
 
@@ -94,7 +98,7 @@
         getSession().save();
 
         file = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, file.getPath(), null, file, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, file.getPath(), null, file, getHelperData());
 
         assertEquals(file.getPath(), jnr.getPath());
 
@@ -110,7 +114,7 @@
         getSession().save();
 
         res = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, res.getPath(), null, res, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, res.getPath(), null, res, getHelperData());
 
         assertEquals(res.getPath(), jnr.getPath());
 
@@ -126,7 +130,7 @@
         getSession().save();
 
         res = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, res.getPath(), null, res, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, res.getPath(), null, res, getHelperData());
 
         assertEquals(res.getPath(), jnr.getPath());
 
@@ -139,14 +143,14 @@
         Node node = rootNode.addNode(name, JcrConstants.NT_UNSTRUCTURED);
         getSession().save();
 
-        JcrNodeResource jnr = new JcrNodeResource(null, node.getPath(), null, node, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, node.getPath(), null, node, getHelperData());
         assertEquals(JcrConstants.NT_UNSTRUCTURED, jnr.getResourceType());
 
         String typeName = "some/resource/type";
         node.setProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, typeName);
         getSession().save();
 
-        jnr = new JcrNodeResource(null, node.getPath(), null, node, getHelperData());
+        jnr = new JcrNodeResource(resourceResolver, node.getPath(), null, node, getHelperData());
         assertEquals(typeName, jnr.getResourceType());
     }
 
@@ -158,7 +162,7 @@
         node.setProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, typeName);
         getSession().save();
 
-        Resource jnr = new JcrNodeResource(null, node.getPath(), null, node, getHelperData());
+        Resource jnr = new JcrNodeResource(resourceResolver, node.getPath(), null, node, getHelperData());
         assertEquals(typeName, jnr.getResourceType());
 
         // default super type is null
@@ -169,7 +173,7 @@
         typeNode.setProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY, superTypeName);
         getSession().save();
 
-        jnr = new JcrNodeResource(null, typeNode.getPath(), null, typeNode, getHelperData());
+        jnr = new JcrNodeResource(resourceResolver, typeNode.getPath(), null, typeNode, getHelperData());
         assertEquals(JcrConstants.NT_UNSTRUCTURED, jnr.getResourceType());
         assertEquals(superTypeName, jnr.getResourceSuperType());
 
@@ -178,7 +182,7 @@
         node.setProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY, otherSuperTypeName);
         getSession().save();
 
-        jnr = new JcrNodeResource(null, node.getPath(), null, node, getHelperData());
+        jnr = new JcrNodeResource(resourceResolver, node.getPath(), null, node, getHelperData());
         assertEquals(typeName, jnr.getResourceType());
         assertEquals(otherSuperTypeName, jnr.getResourceSuperType());
 
@@ -186,7 +190,7 @@
         node.getProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY).remove();
         getSession().save();
 
-        jnr = new JcrNodeResource(null, node.getPath(), null, node, getHelperData());
+        jnr = new JcrNodeResource(resourceResolver, node.getPath(), null, node, getHelperData());
         assertEquals(typeName, jnr.getResourceType());
         assertNull(jnr.getResourceSuperType());
     }
@@ -199,7 +203,7 @@
         getSession().save();
 
         res = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, res.getPath(), null, res, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, res.getPath(), null, res, getHelperData());
 
         final Map<?, ?> props = jnr.adaptTo(Map.class);
 
@@ -218,13 +222,13 @@
         assertEquals(JcrConstants.NT_UNSTRUCTURED, props.get(JcrConstants.JCR_PRIMARYTYPE));
 
         // assert we have nothing else left
-        final Set<String> existingKeys = new HashSet<String>();
+        final Set<String> existingKeys = new HashSet<>();
         existingKeys.add(JcrConstants.JCR_LASTMODIFIED);
         existingKeys.add(JcrConstants.JCR_MIMETYPE);
         existingKeys.add(JcrConstants.JCR_ENCODING);
         existingKeys.add(JcrConstants.JCR_DATA);
         existingKeys.add(JcrConstants.JCR_PRIMARYTYPE);
-        final Set<Object> crossCheck = new HashSet<Object>(props.keySet());
+        final Set<Object> crossCheck = new HashSet<>(props.keySet());
         crossCheck.removeAll(existingKeys);
         assertTrue(crossCheck.isEmpty());
 
@@ -246,13 +250,13 @@
         assertEquals(JcrConstants.NT_UNSTRUCTURED, propsSecond.get(JcrConstants.JCR_PRIMARYTYPE));
 
         // assert we have nothing else left
-        final Set<Object> crossCheck2 = new HashSet<Object>(propsSecond.keySet());
+        final Set<Object> crossCheck2 = new HashSet<>(propsSecond.keySet());
         crossCheck2.removeAll(existingKeys);
         assertTrue(crossCheck2.isEmpty());
     }
 
     public void testCorrectUTF8ByteLength() throws Exception {
-        byte[] utf8bytes = "Übersättigung".getBytes("UTF-8");
+        byte[] utf8bytes = "Übersättigung".getBytes(StandardCharsets.UTF_8);
         String name = "utf8file";
         Node file = rootNode.addNode(name, JcrConstants.NT_FILE);
         Node res = file.addNode(JcrConstants.JCR_CONTENT,
@@ -266,7 +270,7 @@
         getSession().save();
 
         file = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, file.getPath(), null, file, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, file.getPath(), null, file, getHelperData());
 
         assertEquals(utf8bytes, jnr.adaptTo(InputStream.class));
         assertEquals(utf8bytes.length, jnr.getResourceMetadata().getContentLength());
@@ -296,7 +300,7 @@
         getSession().save();
 
         res = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, res.getPath(), null, res, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, res.getPath(), null, res, getHelperData());
 
         final ValueMap props = jnr.adaptTo(ValueMap.class);
         assertFalse(props instanceof ModifiableValueMap);
@@ -338,7 +342,7 @@
         getSession().save();
 
         res = rootNode.getNode(name);
-        JcrNodeResource jnr = new JcrNodeResource(null, res.getPath(), null, res, getHelperData());
+        JcrNodeResource jnr = new JcrNodeResource(resourceResolver, res.getPath(), null, res, getHelperData());
 
         final ModifiableValueMap props = jnr.adaptTo(ModifiableValueMap.class);
         assertNotNull(props);
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
index 2615654..bc3d204 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
@@ -22,6 +22,7 @@
 
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map.Entry;
 
@@ -60,7 +61,7 @@
         final ResourceResolver resolver = this.context.mock(ResourceResolver.class);
         for (final Entry<Object, Integer> data : testData.entrySet()) {
             final String stringValue = data.getKey().toString();
-            final long stringByteLength =  stringValue.getBytes("UTF-8").length;
+            final long stringByteLength =  stringValue.getBytes(StandardCharsets.UTF_8).length;
             final Property property = this.context.mock(Property.class, stringValue);
             this.context.checking(new Expectations() {{
                 ignoring(resolver);
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java
index 5dbdf7c..e2ad5df 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java
@@ -37,12 +37,11 @@
 import java.util.Map;
 
 import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
 
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.jcr.api.SlingRepository;
@@ -60,17 +59,16 @@
 import org.mockito.Mockito;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
 
 @RunWith(Parameterized.class)
 public class JcrResourceProviderSessionHandlingTest {
 
-    private enum LoginStyle {USER, SESSION, SERVICE};
+    private enum LoginStyle {USER, SESSION, SERVICE}
 
-    private static final String AUTH_USER = "admin";
-    private static final char[] AUTH_PASSWORD = "admin".toCharArray();
-    private static final String SUDO_USER = "anonymous";
+    private static final String AUTH_USER = UserConstants.DEFAULT_ADMIN_ID;
+    private static final char[] AUTH_PASSWORD = AUTH_USER.toCharArray();
+    private static final String SUDO_USER = UserConstants.DEFAULT_ANONYMOUS_ID;
 
     @Parameters(name = "loginStyle= {0}, sudo = {1}, clone = {2}")
     public static List<Object[]> data() {
@@ -124,8 +122,7 @@
         
         @SuppressWarnings("deprecation")
         @Override
-        public Session loginService(String subServiceName, String workspace)
-                throws LoginException, RepositoryException {
+        public Session loginService(String subServiceName, String workspace) throws RepositoryException {
             // just fake service logins by doing administrative logins instead
             return wrapped.loginAdministrative(workspace);
         }
@@ -163,24 +160,22 @@
         }
 
         @Override
-        public Session login(Credentials credentials, String workspaceName)
-                throws LoginException, NoSuchWorkspaceException, RepositoryException {
+        public Session login(Credentials credentials, String workspaceName) throws RepositoryException {
             return wrapped.login(credentials, workspaceName);
         }
 
         @Override
-        public Session login(Credentials credentials) throws LoginException, RepositoryException {
+        public Session login(Credentials credentials) throws RepositoryException {
             return wrapped.login(credentials);
         }
 
         @Override
-        public Session login(String workspaceName)
-                throws LoginException, NoSuchWorkspaceException, RepositoryException {
+        public Session login(String workspaceName) throws RepositoryException {
             return wrapped.login(workspaceName);
         }
 
         @Override
-        public Session login() throws LoginException, RepositoryException {
+        public Session login() throws RepositoryException {
             return wrapped.login();
         }
 
@@ -191,7 +186,7 @@
 
         @SuppressWarnings("deprecation")
         @Override
-        public Session loginAdministrative(String workspace) throws LoginException, RepositoryException {
+        public Session loginAdministrative(String workspace) throws RepositoryException {
             return wrapped.loginAdministrative(workspace);
         }
         
@@ -217,7 +212,7 @@
             Bundle mockBundle = mock(Bundle.class);
             BundleContext mockBundleContext = mock(BundleContext.class);
             when(mockBundle.getBundleContext()).thenReturn(mockBundleContext);
-            when(mockBundleContext.getService(Matchers.<ServiceReference<Object>>any())).thenReturn(repo);
+            when(mockBundleContext.getService(Matchers.any())).thenReturn(repo);
             authInfo.put(ResourceResolverFactory.SUBSERVICE, "dummy-service");
             authInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, mockBundle);
             break;
@@ -232,7 +227,7 @@
         }
 
         ComponentContext ctx = mock(ComponentContext.class);
-        when(ctx.locateService(anyString(), Mockito.<ServiceReference<Object>>any())).thenReturn(repo);
+        when(ctx.locateService(anyString(), Mockito.any())).thenReturn(repo);
 
         jcrResourceProvider = new JcrResourceProvider();
         jcrResourceProvider.activate(ctx);
@@ -241,9 +236,9 @@
     }
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
 
-        // Some tests do a logout, so check for liveness before trying to log out.
+        // Some tests do a logout, so check for aliveness before trying to log out.
         if (jcrProviderState.getSession().isLive()) {
             jcrResourceProvider.logout(jcrProviderState);
         }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
index 1c97445..bac2e28 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
@@ -25,13 +25,10 @@
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
 
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.jcr.resource.internal.HelperData;
 import org.apache.sling.spi.resource.provider.ResolveContext;
 import org.apache.sling.spi.resource.provider.ResourceContext;
@@ -79,14 +76,14 @@
         return new JcrProviderState(session, new HelperData(new AtomicReference<>(), new AtomicReference<>()), false);
     }
     
-    private @NotNull ResolveContext mockResolveContext() {
-        ResolveContext ctx = mock(ResolveContext.class);
+    private @NotNull ResolveContext<JcrProviderState> mockResolveContext() {
+        ResolveContext<JcrProviderState> ctx = mock(ResolveContext.class);
         when(ctx.getProviderState()).thenReturn(createProviderState());
         return ctx;
     }
 
     public void testAdaptTo_Principal() {
-        ResolveContext ctx = mockResolveContext();
+        ResolveContext<JcrProviderState> ctx = mockResolveContext();
         Assert.assertNotNull(jcrResourceProvider.adaptTo(ctx, Principal.class));
     }
 
@@ -97,7 +94,7 @@
         parentNode.addNode("child3", NT_UNSTRUCTURED);
         session.save();
 
-        ResolveContext ctx = mockResolveContext();
+        ResolveContext<JcrProviderState> ctx = mockResolveContext();
         Resource parent = jcrResourceProvider.getResource(ctx, "/parent", ResourceContext.EMPTY_CONTEXT, null);
         Assert.assertNotNull(parent);
         // order with invalid names
@@ -130,7 +127,7 @@
         Node grandchild = child.addNode("grandchild", NT_UNSTRUCTURED);
         session.save();
 
-        ResolveContext ctx = mockResolveContext();
+        ResolveContext<JcrProviderState> ctx = mockResolveContext();
         Resource rootResource = jcrResourceProvider.getResource(ctx, PathUtils.ROOT_PATH, ResourceContext.EMPTY_CONTEXT, null);
         Resource parentResource = jcrResourceProvider.getResource(ctx, parentNode.getPath(), ResourceContext.EMPTY_CONTEXT, rootResource);
         Resource childResource = jcrResourceProvider.getResource(ctx, child.getPath(), ResourceContext.EMPTY_CONTEXT, parentResource);
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java
deleted file mode 100644
index 0f73916..0000000
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrTestNodeResource.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.sling.jcr.resource.internal.helper.jcr;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.external.URIProvider;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
-import org.apache.sling.jcr.resource.internal.HelperData;
-
-public class JcrTestNodeResource extends JcrNodeResource {
-
-    public JcrTestNodeResource(ResourceResolver resourceResolver, Node node,
-            ClassLoader dynamicClassLoader) throws RepositoryException {
-        super(resourceResolver, node.getPath(), null, node, new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>()));
-    }
-
-}
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryProvider.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryProvider.java
index 4dee137..a45d892 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryProvider.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryProvider.java
@@ -24,7 +24,6 @@
 import org.apache.sling.testing.mock.sling.oak.OakMockSlingRepository;
 import org.mockito.Mockito;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.component.ComponentContext;
 
 public class SlingRepositoryProvider {
     
@@ -44,17 +43,7 @@
             return INSTANCE;
         }
         
-
-        
-        public static void shutdown() throws Exception {
-            Method deactivateMethod = OakMockSlingRepository.class.getDeclaredMethod("deactivate",ComponentContext.class);
-            deactivateMethod.setAccessible(true);
-            deactivateMethod.invoke(getRepository(),(ComponentContext) null);
-        }
-        
-        
         private static BundleContext getFakeContext() {
-            BundleContext mockContext = Mockito.mock(BundleContext.class);
-            return mockContext;
+            return Mockito.mock(BundleContext.class);
         }
 }
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryTestBase.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryTestBase.java
index babdc20..d16ff5c 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryTestBase.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/SlingRepositoryTestBase.java
@@ -25,7 +25,7 @@
 
 import junit.framework.TestCase;
 
-public class SlingRepositoryTestBase extends TestCase {
+public abstract class SlingRepositoryTestBase extends TestCase {
     
     protected Node testRoot;
     protected Session session;
@@ -62,8 +62,4 @@
     protected SlingRepository getRepository() throws Exception {
         return SlingRepositoryProvider.getRepository();
     }
-
-    
-
-
 }