You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2016/02/15 11:49:30 UTC

svn commit: r1730493 - in /sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource: ./ internal/ internal/helper/ internal/helper/jcr/

Author: cziegeler
Date: Mon Feb 15 10:49:29 2016
New Revision: 1730493

URL: http://svn.apache.org/viewvc?rev=1730493&view=rev
Log:
SLING-5513 : Deprecate JcrResourceUtil - add deprecation warnings

Added:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java   (with props)
Modified:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java Mon Feb 15 10:49:29 2016
@@ -31,6 +31,7 @@ import org.apache.sling.api.resource.Per
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.jcr.resource.internal.NodeUtil;
 import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry;
+import org.slf4j.LoggerFactory;
 
 /**
  * This implementation of the value map allows to change
@@ -44,6 +45,8 @@ public final class JcrModifiableProperty
     extends JcrPropertyMap
     implements PersistableValueMap {
 
+    private static volatile boolean LOG_DEPRECATED = true;
+
     /** Set of removed and changed properties. */
     private Set<String> changedProperties;
 
@@ -53,6 +56,10 @@ public final class JcrModifiableProperty
      */
     public JcrModifiablePropertyMap(final Node node) {
         super(node);
+        if ( LOG_DEPRECATED ) {
+            LOG_DEPRECATED = false;
+            LoggerFactory.getLogger(this.getClass()).warn("DEPRECATION WARNING: JcrModifiablePropertyMap is deprecated. Please switch to resource API.");
+        }
     }
 
     /**
@@ -63,6 +70,10 @@ public final class JcrModifiableProperty
      */
     public JcrModifiablePropertyMap(final Node node, final ClassLoader dynamicCL) {
         super(node, dynamicCL);
+        if ( LOG_DEPRECATED ) {
+            LOG_DEPRECATED = false;
+            LoggerFactory.getLogger(this.getClass()).warn("DEPRECATION WARNING: JcrModifiablePropertyMap is deprecated. Please switch to resource API.");
+        }
     }
 
     // ---------- Map

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java Mon Feb 15 10:49:29 2016
@@ -37,6 +37,7 @@ import org.apache.jackrabbit.util.ISO907
 import org.apache.jackrabbit.util.Text;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry;
+import org.slf4j.LoggerFactory;
 
 /**
  * An implementation of the value map based on a JCR node.
@@ -48,6 +49,8 @@ import org.apache.sling.jcr.resource.int
 public class JcrPropertyMap
     implements ValueMap {
 
+    private static volatile boolean LOG_DEPRECATED = true;
+
     /** The underlying node. */
     private final Node node;
 
@@ -85,6 +88,10 @@ public class JcrPropertyMap
         this.valueCache = new LinkedHashMap<String, Object>();
         this.fullyRead = false;
         this.dynamicClassLoader = dynamicCL;
+        if ( LOG_DEPRECATED ) {
+            LOG_DEPRECATED = false;
+            LoggerFactory.getLogger(this.getClass()).warn("DEPRECATION WARNING: JcrPropertyMap is deprecated. Please switch to resource API.");
+        }
     }
 
     protected ClassLoader getDynamicClassLoader() {

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java Mon Feb 15 10:49:29 2016
@@ -39,6 +39,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.jcr.resource.internal.helper.LazyInputStream;
+import org.slf4j.LoggerFactory;
 
 /**
  * The <code>JcrResourceUtil</code> class provides helper methods used
@@ -49,6 +50,17 @@ import org.apache.sling.jcr.resource.int
 @Deprecated
 public class JcrResourceUtil {
 
+    private static volatile boolean LOG_DEPRECATED_QUERY = true;
+    private static volatile boolean LOG_DEPRECATED_TO_JAVA_OBJECT_1 = true;
+    private static volatile boolean LOG_DEPRECATED_TO_JAVA_OBJECT_2 = true;
+    private static volatile boolean LOG_DEPRECATED_CREATE_VALUE = true;
+    private static volatile boolean LOG_DEPRECATED_SET_PROPERTY = true;
+    private static volatile boolean LOG_DEPRECATED_CREATE_PATH_1 = true;
+    private static volatile boolean LOG_DEPRECATED_CREATE_PATH_2 = true;
+    private static volatile boolean LOG_DEPRECATED_GET_RST_1 = true;
+    private static volatile boolean LOG_DEPRECATED_GET_RST_2 = true;
+    private static volatile boolean LOG_DEPRECATED_RT_TO_PATH = true;
+
     /**
      * Helper method to execute a JCR query.
      *
@@ -60,6 +72,10 @@ public class JcrResourceUtil {
      */
     public static QueryResult query(Session session, String query,
             String language) throws RepositoryException {
+        if ( LOG_DEPRECATED_QUERY ) {
+            LOG_DEPRECATED_QUERY = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.query is deprecated. Please use the resource resolver.");
+        }
         QueryManager qManager = session.getWorkspace().getQueryManager();
         Query q = qManager.createQuery(query, language);
         return q.execute();
@@ -73,6 +89,10 @@ public class JcrResourceUtil {
      * @throws RepositoryException if the value cannot be converted
      */
     public static Object toJavaObject(Value value) throws RepositoryException {
+        if ( LOG_DEPRECATED_TO_JAVA_OBJECT_1 ) {
+            LOG_DEPRECATED_TO_JAVA_OBJECT_1 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.toJavaObject(Value) is deprecated. Please use the resource resolver API.");
+        }
         switch (value.getType()) {
             case PropertyType.DECIMAL:
                 return value.getDecimal();
@@ -107,6 +127,10 @@ public class JcrResourceUtil {
      */
     public static Object toJavaObject(Property property)
             throws RepositoryException {
+        if ( LOG_DEPRECATED_TO_JAVA_OBJECT_2 ) {
+            LOG_DEPRECATED_TO_JAVA_OBJECT_2 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.toJavaObject(Property) is deprecated. Please use the resource resolver API.");
+        }
         // multi-value property: return an array of values
         if (property.isMultiple()) {
             Value[] values = property.getValues();
@@ -153,6 +177,10 @@ public class JcrResourceUtil {
      */
     public static Value createValue(final Object value, final Session session)
     throws RepositoryException {
+        if ( LOG_DEPRECATED_CREATE_VALUE ) {
+            LOG_DEPRECATED_CREATE_VALUE = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createValue is deprecated. Please use the resource resolver API.");
+        }
         Value val;
         ValueFactory fac = session.getValueFactory();
         if(value instanceof Calendar) {
@@ -194,6 +222,10 @@ public class JcrResourceUtil {
                                    final String propertyName,
                                    final Object propertyValue)
     throws RepositoryException {
+        if ( LOG_DEPRECATED_SET_PROPERTY ) {
+            LOG_DEPRECATED_SET_PROPERTY = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.setProperty is deprecated. Please use the resource resolver API.");
+        }
         if ( propertyValue == null ) {
             node.setProperty(propertyName, (String)null);
         } else if ( propertyValue.getClass().isArray() ) {
@@ -220,6 +252,10 @@ public class JcrResourceUtil {
      */
     @Deprecated
     public static String resourceTypeToPath(String type) {
+        if ( LOG_DEPRECATED_RT_TO_PATH ) {
+            LOG_DEPRECATED_RT_TO_PATH = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.resourceTypeToPath is deprecated. Please use the resource resolver API.");
+        }
         return type.replaceAll("\\:", "/");
     }
 
@@ -249,6 +285,10 @@ public class JcrResourceUtil {
     @Deprecated
     public static String getResourceSuperType(
             ResourceResolver resourceResolver, String resourceType) {
+        if ( LOG_DEPRECATED_GET_RST_1) {
+            LOG_DEPRECATED_GET_RST_1 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.getResourceSuperType(String) is deprecated. Please use the resource resolver API.");
+        }
         return ResourceUtil.getResourceSuperType(resourceResolver, resourceType);
     }
 
@@ -273,6 +313,10 @@ public class JcrResourceUtil {
     @SuppressWarnings("deprecation")
     @Deprecated
     public static String getResourceSuperType(Resource resource) {
+        if ( LOG_DEPRECATED_GET_RST_2) {
+            LOG_DEPRECATED_GET_RST_2 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.getResourceSuperType(Resource) is deprecated. Please use the resource resolver API.");
+        }
         String resourceSuperType = resource.getResourceSuperType();
         if ( resourceSuperType == null ) {
             final ResourceResolver resolver = resource.getResourceResolver();
@@ -305,6 +349,10 @@ public class JcrResourceUtil {
                                   Session session,
                                   boolean autoSave)
             throws RepositoryException {
+        if ( LOG_DEPRECATED_CREATE_PATH_1 ) {
+            LOG_DEPRECATED_CREATE_PATH_1 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createPath(String, ...) is deprecated. Please use the resource resolver API.");
+        }
         if (path == null || path.length() == 0 || "/".equals(path)) {
             return session.getRootNode();
         }
@@ -357,6 +405,10 @@ public class JcrResourceUtil {
                                   String nodeType,
                                   boolean autoSave)
     throws RepositoryException {
+        if ( LOG_DEPRECATED_CREATE_PATH_2 ) {
+            LOG_DEPRECATED_CREATE_PATH_2 = false;
+            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createPath(Node,...) is deprecated. Please use the resource resolver API.");
+        }
         if (relativePath == null || relativePath.length() == 0 || "/".equals(relativePath)) {
             return parentNode;
         }

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java Mon Feb 15 10:49:29 2016
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import javax.jcr.Session;
 
+import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
@@ -37,6 +38,7 @@ import org.apache.sling.commons.classloa
 import org.apache.sling.jcr.resource.JcrResourceConstants;
 import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
 import org.osgi.framework.Constants;
+import org.slf4j.LoggerFactory;
 
 /**
  * The <code>JcrResourceResolverFactoryImpl</code> is the
@@ -63,6 +65,11 @@ public class JcrResourceResolverFactoryI
     @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
     private volatile DynamicClassLoaderManager dynamicClassLoaderManager;
 
+    @Activate
+    protected void activate() {
+        LoggerFactory.getLogger(this.getClass()).warn("DEPRECATION WARNING: JcrResourceResolverFactory is deprecated. Please use ResourceResolverFactory instead.");
+    }
+
     /**
      * Get the dynamic class loader if available.
      *
@@ -79,6 +86,7 @@ public class JcrResourceResolverFactoryI
     /**
      * @see org.apache.sling.jcr.resource.JcrResourceResolverFactory#getResourceResolver(javax.jcr.Session)
      */
+    @Override
     public ResourceResolver getResourceResolver(final Session session) {
         final Map<String, Object> authInfo = new HashMap<String, Object>(1);
         authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
@@ -94,6 +102,7 @@ public class JcrResourceResolverFactoryI
     /**
      * @see org.apache.sling.api.resource.ResourceResolverFactory#getServiceResourceResolver(Map)
      */
+    @Override
     public ResourceResolver getServiceResourceResolver(Map<String, Object> authenticationInfo) throws LoginException {
         return delegatee.getServiceResourceResolver(authenticationInfo);
     }
@@ -101,6 +110,7 @@ public class JcrResourceResolverFactoryI
     /**
      * @see org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)
      */
+    @Override
     public ResourceResolver getAdministrativeResourceResolver(
             final Map<String, Object> authenticationInfo) throws LoginException {
         return delegatee.getAdministrativeResourceResolver(authenticationInfo);
@@ -109,6 +119,7 @@ public class JcrResourceResolverFactoryI
     /**
      * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)
      */
+    @Override
     public ResourceResolver getResourceResolver(final Map<String, Object> arg0)
             throws LoginException {
         return delegatee.getResourceResolver(arg0);
@@ -117,6 +128,7 @@ public class JcrResourceResolverFactoryI
     /**
      * @see org.apache.sling.api.resource.ResourceResolverFactory#getThreadResourceResolver()
      */
+    @Override
     public ResourceResolver getThreadResourceResolver() {
         return delegatee.getThreadResourceResolver();
     }

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrValueMap.java Mon Feb 15 10:49:29 2016
@@ -18,28 +18,459 @@
  */
 package org.apache.sling.jcr.resource.internal;
 
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
 import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
 
-import org.apache.sling.jcr.resource.JcrPropertyMap;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry;
 
-@SuppressWarnings("deprecation")
-public class JcrValueMap extends JcrPropertyMap {
+public class JcrValueMap implements ValueMap {
 
     private final HelperData helper;
 
+    /** The underlying node. */
+    private final Node node;
+
+    /** A cache for the properties. */
+    final Map<String, JcrPropertyMapCacheEntry> cache;
+
+    /** A cache for the values. */
+    final Map<String, Object> valueCache;
+
+    /** Has the node been read completely? */
+    boolean fullyRead;
+
+    /**
+     * Create a new JCR property map based on a node.
+     * @param node The underlying node.
+     */
     public JcrValueMap(final Node node, final HelperData helper) {
-        super(node, null);
+        this.node = node;
+        this.cache = new LinkedHashMap<String, JcrPropertyMapCacheEntry>();
+        this.valueCache = new LinkedHashMap<String, Object>();
+        this.fullyRead = false;
         this.helper = helper;
     }
 
+    /**
+     * Get the node.
+     *
+     * @return the node
+     */
+    protected Node getNode() {
+        return node;
+    }
+
+    // ---------- ValueMap
+
+    String checkKey(final String key) {
+        if ( key == null ) {
+            throw new NullPointerException("Key must not be null.");
+        }
+        if ( key.startsWith("./") ) {
+            return key.substring(2);
+        }
+        return key;
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ValueMap#get(java.lang.String, java.lang.Class)
+     */
     @Override
-    protected String[] getNamespacePrefixes() throws RepositoryException {
-        return this.helper.getNamespacePrefixes(this.getNode().getSession());
+    @SuppressWarnings("unchecked")
+    public <T> T get(final String aKey, 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 ) {
+            return null;
+        }
+        return entry.convertToType(type, this.node, this.getDynamicClassLoader());
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ValueMap#get(java.lang.String, java.lang.Object)
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T get(final String aKey,final T defaultValue) {
+        final String key = checkKey(aKey);
+        if (defaultValue == null) {
+            return (T) get(key);
+        }
+
+        // special handling in case the default value implements one
+        // of the interface types supported by the convertToType method
+        Class<T> type = (Class<T>) normalizeClass(defaultValue.getClass());
+
+        T value = get(key, type);
+        if (value == null) {
+            value = defaultValue;
+        }
+
+        return value;
+    }
+
+    // ---------- Map
+
+    /**
+     * @see java.util.Map#get(java.lang.Object)
+     */
+    @Override
+    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;
+    }
+
+    /**
+     * @see java.util.Map#containsKey(java.lang.Object)
+     */
+    @Override
+    public boolean containsKey(final Object key) {
+        return get(key) != null;
+    }
+
+    /**
+     * @see java.util.Map#containsValue(java.lang.Object)
+     */
+    @Override
+    public boolean containsValue(final Object value) {
+        readFully();
+        return valueCache.containsValue(value);
+    }
+
+    /**
+     * @see java.util.Map#isEmpty()
+     */
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    /**
+     * @see java.util.Map#size()
+     */
+    @Override
+    public int size() {
+        readFully();
+        return cache.size();
+    }
+
+    /**
+     * @see java.util.Map#entrySet()
+     */
+    @Override
+    public Set<java.util.Map.Entry<String, Object>> entrySet() {
+        readFully();
+        final Map<String, Object> sourceMap;
+        if (cache.size() == valueCache.size()) {
+            sourceMap = valueCache;
+        } else {
+            sourceMap = transformEntries(cache);
+        }
+        return Collections.unmodifiableSet(sourceMap.entrySet());
+    }
+
+    /**
+     * @see java.util.Map#keySet()
+     */
+    @Override
+    public Set<String> keySet() {
+        readFully();
+        return cache.keySet();
+    }
+
+    /**
+     * @see java.util.Map#values()
+     */
+    @Override
+    public Collection<Object> values() {
+        readFully();
+        final Map<String, Object> sourceMap;
+        if (cache.size() == valueCache.size()) {
+            sourceMap = valueCache;
+        } else {
+            sourceMap = transformEntries(cache);
+        }
+        return Collections.unmodifiableCollection(sourceMap.values());
     }
 
+    /**
+     * Return the path of the current node.
+     *
+     * @return the path
+     * @throws IllegalStateException If a repository exception occurs
+     * @deprecated
+     */
+    @Deprecated
+    public String getPath() {
+        try {
+            return node.getPath();
+        } catch (final RepositoryException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    // ---------- Helpers to access the node's property ------------------------
+
+    /**
+     * Put a single property into the cache
+     * @param prop
+     * @return the cached property
+     * @throws IllegalArgumentException if a repository exception occurs
+     */
+    private JcrPropertyMapCacheEntry cacheProperty(final Property prop) {
+        try {
+            // calculate the key
+            final String name = prop.getName();
+            String key = null;
+            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) ) {
+                    key = null;
+                }
+            }
+            if ( key == null ) {
+                key = Text.unescapeIllegalJcrChars(name);
+            }
+            JcrPropertyMapCacheEntry entry = cache.get(key);
+            if ( entry == null ) {
+                entry = new JcrPropertyMapCacheEntry(prop);
+                cache.put(key, entry);
+
+                final Object defaultValue = entry.getPropertyValue();
+                if (defaultValue != null) {
+                    valueCache.put(key, entry.getPropertyValue());
+                }
+            }
+            return entry;
+        } catch (final RepositoryException re) {
+            throw new IllegalArgumentException(re);
+        }
+    }
+
+    /**
+     * Read a single property.
+     * @throws IllegalArgumentException if a repository exception occurs
+     */
+    JcrPropertyMapCacheEntry read(final String name) {
+        // check for empty key
+        if ( name.length() == 0 ) {
+            return null;
+        }
+        // if the name is a path, we should handle this differently
+        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) ) {
+                    return new JcrPropertyMapCacheEntry(node.getProperty(path));
+                }
+            } catch (final RepositoryException re) {
+                throw new IllegalArgumentException(re);
+            }
+            // now we do a proper segment by segment encoding
+            final StringBuilder sb = new StringBuilder();
+            int pos = 0;
+            int lastPos = -1;
+            while ( pos < name.length() ) {
+                if ( name.charAt(pos) == '/' ) {
+                    if ( lastPos + 1 < pos ) {
+                        sb.append(Text.escapeIllegalJcrChars(name.substring(lastPos + 1, pos)));
+                    }
+                    sb.append('/');
+                    lastPos = pos;
+                }
+                pos++;
+            }
+            if ( lastPos + 1 < pos ) {
+                sb.append(Text.escapeIllegalJcrChars(name.substring(lastPos + 1)));
+            }
+            final String newPath = sb.toString();
+            try {
+                if ( node.hasProperty(newPath) ) {
+                    return new JcrPropertyMapCacheEntry(node.getProperty(newPath));
+                }
+            } catch (final RepositoryException re) {
+                throw new IllegalArgumentException(re);
+            }
+
+            return null;
+        }
+
+        // check cache
+        JcrPropertyMapCacheEntry cachedValued = cache.get(name);
+        if ( fullyRead || cachedValued != null ) {
+            return cachedValued;
+        }
+
+        final String key;
+        try {
+            key = escapeKeyName(name);
+            if (node.hasProperty(key)) {
+                final Property prop = node.getProperty(key);
+                return cacheProperty(prop);
+            }
+        } catch (final RepositoryException re) {
+            throw new IllegalArgumentException(re);
+        }
+
+        try {
+            // for compatibility with older versions we use the (wrong) ISO9075 path
+            // encoding
+            final String oldKey = ISO9075.encodePath(name);
+            if (!oldKey.equals(key) && node.hasProperty(oldKey)) {
+                final Property prop = node.getProperty(oldKey);
+                return cacheProperty(prop);
+            }
+        } catch (final RepositoryException re) {
+            // we ignore this
+        }
+
+        // property not found
+        return null;
+    }
+
+    /**
+     * Handles key name escaping by taking into consideration if it contains a
+     * registered prefix
+     *
+     * @param key the key to escape
+     * @return escaped key name
+     * @throws RepositoryException if the repository's namespaced prefixes cannot be retrieved
+     */
+    protected String escapeKeyName(final String key) throws RepositoryException {
+        final int indexOfPrefix = key.indexOf(':');
+        // check if colon is neither the first nor the last character
+        if (indexOfPrefix > 0 && key.length() > indexOfPrefix + 1) {
+            final String prefix = key.substring(0, indexOfPrefix);
+            for (final String existingPrefix : getNamespacePrefixes()) {
+                if (existingPrefix.equals(prefix)) {
+                    return prefix
+                            + ":"
+                            + Text.escapeIllegalJcrChars(key
+                                    .substring(indexOfPrefix + 1));
+                }
+            }
+        }
+        return Text.escapeIllegalJcrChars(key);
+    }
+
+    /**
+     * Read all properties.
+     * @throws IllegalArgumentException if a repository exception occurs
+     */
+    void readFully() {
+        if (!fullyRead) {
+            try {
+                final PropertyIterator pi = node.getProperties();
+                while (pi.hasNext()) {
+                    final Property prop = pi.nextProperty();
+                    this.cacheProperty(prop);
+                }
+                fullyRead = true;
+            } catch (final RepositoryException re) {
+                throw new IllegalArgumentException(re);
+            }
+        }
+    }
+
+    // ---------- Unsupported Modification methods
+
     @Override
-    protected ClassLoader getDynamicClassLoader() {
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putAll(Map<? extends String, ? extends Object> t) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    // ---------- Implementation helper
+
+    private Class<?> normalizeClass(Class<?> type) {
+        if (Calendar.class.isAssignableFrom(type)) {
+            type = Calendar.class;
+        } else if (Date.class.isAssignableFrom(type)) {
+            type = Date.class;
+        } else if (Value.class.isAssignableFrom(type)) {
+            type = Value.class;
+        } else if (Property.class.isAssignableFrom(type)) {
+            type = Property.class;
+        }
+        return type;
+    }
+
+    private Map<String, Object> transformEntries( Map<String, JcrPropertyMapCacheEntry> map) {
+
+        Map<String, Object> transformedEntries = new LinkedHashMap<String, Object>(map.size());
+        for ( Map.Entry<String, JcrPropertyMapCacheEntry> entry : map.entrySet() )
+            transformedEntries.put(entry.getKey(), entry.getValue().getPropertyValueOrNull());
+
+        return transformedEntries;
+    }
+
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("JcrPropertyMap [node=");
+        sb.append(this.node);
+        sb.append(", values={");
+        final Iterator<Map.Entry<String, Object>> iter = this.entrySet().iterator();
+        boolean first = true;
+        while ( iter.hasNext() ) {
+            if ( first ) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            final Map.Entry<String, Object> e = iter.next();
+            sb.append(e.getKey());
+            sb.append("=");
+            sb.append(e.getValue());
+        }
+        sb.append("}]");
+        return sb.toString();
+    }
+
+    private String[] getNamespacePrefixes() throws RepositoryException {
+        return this.helper.getNamespacePrefixes(this.getNode().getSession());
+    }
+
+    private ClassLoader getDynamicClassLoader() {
         return helper.getDynamicClassLoader();
     }
 }

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java Mon Feb 15 10:49:29 2016
@@ -40,15 +40,13 @@ import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
 
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.sling.jcr.resource.JcrPropertyMap;
-import org.apache.sling.jcr.resource.JcrResourceUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class JcrPropertyMapCacheEntry {
 
     /** Global logger */
-    private static Logger LOGGER = LoggerFactory.getLogger(JcrPropertyMap.class);
+    private static Logger LOGGER = LoggerFactory.getLogger(JcrPropertyMapCacheEntry.class);
 
     /** The JCR property - only set for existing values. */
     private final Property property;

Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java?rev=1730493&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java (added)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java Mon Feb 15 10:49:29 2016
@@ -0,0 +1,174 @@
+/*
+ * 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;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+
+/**
+ * The <code>JcrResourceUtil</code> class provides helper methods used
+ * throughout this bundle.
+ *
+ */
+public class JcrResourceUtil {
+
+    /**
+     * Helper method to execute a JCR query.
+     *
+     * @param session the session
+     * @param query the query
+     * @param language the language
+     * @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 {
+        QueryManager qManager = session.getWorkspace().getQueryManager();
+        Query q = qManager.createQuery(query, language);
+        return q.execute();
+    }
+
+    /**
+     * Converts a JCR Value to a corresponding Java Object
+     *
+     * @param value the JCR Value to convert
+     * @return the Java Object
+     * @throws RepositoryException if the value cannot be converted
+     */
+    public static Object toJavaObject(Value value) throws RepositoryException {
+        switch (value.getType()) {
+            case PropertyType.DECIMAL:
+                return value.getDecimal();
+            case PropertyType.BINARY:
+                return new LazyInputStream(value);
+            case PropertyType.BOOLEAN:
+                return value.getBoolean();
+            case PropertyType.DATE:
+                return value.getDate();
+            case PropertyType.DOUBLE:
+                return value.getDouble();
+            case PropertyType.LONG:
+                return value.getLong();
+            case PropertyType.NAME: // fall through
+            case PropertyType.PATH: // fall through
+            case PropertyType.REFERENCE: // fall through
+            case PropertyType.STRING: // fall through
+            case PropertyType.UNDEFINED: // not actually expected
+            default: // not actually expected
+                return value.getString();
+        }
+    }
+
+    /**
+     * Converts the value(s) of a JCR Property to a corresponding Java Object.
+     * If the property has multiple values the result is an array of Java
+     * Objects representing the converted values of the property.
+     *
+     * @param property the property to be converted to the corresponding Java Object
+     * @throws RepositoryException if the conversion cannot take place
+     * @return the Object resulting from the conversion
+     */
+    public static Object toJavaObject(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 ) {
+                result = new Boolean[values.length];
+            } else if ( firstValue instanceof Calendar ) {
+                result = new Calendar[values.length];
+            } else if ( firstValue instanceof Double ) {
+                result = new Double[values.length];
+            } else if ( firstValue instanceof Long ) {
+                result = new Long[values.length];
+            } else if ( firstValue instanceof BigDecimal) {
+                result = new BigDecimal[values.length];
+            } else if ( firstValue instanceof InputStream) {
+                result = new Object[values.length];
+            } else {
+                result = new String[values.length];
+            }
+            for (int i = 0; i < values.length; i++) {
+                Value value = values[i];
+                if (value != null) {
+                    result[i] = toJavaObject(value);
+                }
+            }
+            return result;
+        }
+
+        // single value property
+        return toJavaObject(property.getValue());
+    }
+
+    /**
+     * Creates a {@link javax.jcr.Value JCR Value} for the given object with
+     * the given Session.
+     * Selects the the {@link javax.jcr.PropertyType PropertyType} according
+     * the instance of the object's Class
+     *
+     * @param value object
+     * @param session to create value for
+     * @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 {
+        Value val;
+        ValueFactory fac = session.getValueFactory();
+        if(value instanceof Calendar) {
+            val = fac.createValue((Calendar)value);
+        } else if (value instanceof InputStream) {
+            val = fac.createValue(fac.createBinary((InputStream)value));
+        } else if (value instanceof Node) {
+            val = fac.createValue((Node)value);
+        } else if (value instanceof BigDecimal) {
+            val = fac.createValue((BigDecimal)value);
+        } else if (value instanceof Long) {
+            val = fac.createValue((Long)value);
+        } else if (value instanceof Short) {
+            val = fac.createValue((Short)value);
+        } else if (value instanceof Integer) {
+            val = fac.createValue((Integer)value);
+        } else if (value instanceof Number) {
+            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 {
+            val = null;
+        }
+        return val;
+    }
+}

Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrResourceUtil.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/BasicQueryLanguageProvider.java Mon Feb 15 10:49:29 2016
@@ -36,7 +36,7 @@ import org.apache.sling.api.resource.Que
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.apache.sling.jcr.resource.internal.helper.JcrResourceUtil;
 import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
 import org.apache.sling.spi.resource.provider.ProviderContext;
 import org.apache.sling.spi.resource.provider.ResolveContext;

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=1730493&r1=1730492&r2=1730493&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Mon Feb 15 10:49:29 2016
@@ -56,6 +56,8 @@ import org.slf4j.LoggerFactory;
 })
 class JcrNodeResource extends JcrItemResource<Node> { // this should be package private, see SLING-1414
 
+    private static volatile boolean LOG_DEPRECATED_MAP = true;
+
     /** marker value for the resourceSupertType before trying to evaluate */
     private static final String UNSET_RESOURCE_SUPER_TYPE = "<unset>";
 
@@ -133,6 +135,10 @@ class JcrNodeResource extends JcrItemRes
         } else if (type == Map.class || type == ValueMap.class) {
             return (Type) new JcrValueMap(getNode(), this.helper); // unchecked cast
         } else if (type == PersistableValueMap.class ) {
+            if ( LOG_DEPRECATED_MAP ) {
+                LOG_DEPRECATED_MAP = false;
+                LOGGER.warn("DEPRECATION WARNING: PersistableValueMap is deprecated, a JcrResource should not be adapted to this anymore. Please switch to ModifiableValueMap.");
+            }
             // check write
             try {
                 getNode().getSession().checkPermission(getPath(),