You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2013/11/14 02:56:42 UTC

svn commit: r1541782 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/ oak-jcr/src/test/java/org/apac...

Author: tripod
Date: Thu Nov 14 01:56:41 2013
New Revision: 1541782

URL: http://svn.apache.org/r1541782
Log:
OAK-1126 Same node and property name support

- added org.apache.jackrabbit.oak.api.Descriptors and expose them already on the ContentRepository
- simply set the SNNP descriptor based on the NodeStore implementation
- adding simple SNNP tests

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Descriptors.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/DescriptorsImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/JcrDescriptorsImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/SameNamePropertyNodeTest.java
Removed:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/Descriptors.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentRepository.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentRepository.java?rev=1541782&r1=1541781&r2=1541782&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentRepository.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentRepository.java Thu Nov 14 01:56:41 2013
@@ -83,4 +83,12 @@ public interface ContentRepository {
     ContentSession login(@Nullable Credentials credentials, @Nullable String workspaceName)
             throws LoginException, NoSuchWorkspaceException;
 
+    /**
+     * Returns the repository descriptors which contain all or a subset of the descriptors defined in
+     * {@link javax.jcr.Repository}.
+     *
+     * @return the repository descriptors
+     */
+    @Nonnull
+    Descriptors getDescriptors();
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Descriptors.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Descriptors.java?rev=1541782&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Descriptors.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Descriptors.java Thu Nov 14 01:56:41 2013
@@ -0,0 +1,86 @@
+/*
+ * 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.jackrabbit.oak.api;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.Value;
+
+/**
+ * Repository descriptors interface that is used to support providing the repository descriptors of
+ * {@link javax.jcr.Repository}
+ */
+public interface Descriptors {
+
+    /**
+     * Returns a string array holding all descriptor keys available for this
+     * implementation, both the standard descriptors defined by the string
+     * constants in this interface and any implementation-specific descriptors.
+     * Used in conjunction with {@link #getValue(String key)} and
+     * {@link #getValues(String key)} to query information about this
+     * repository implementation.
+     *
+     * @return a string array holding all descriptor keys.
+     */
+    @Nonnull
+    String[] getKeys();
+
+    /**
+     * Returns {@code true} if {@code key} is a standard descriptor
+     * defined by the string constants in this interface and {@code false}
+     * if it is either a valid implementation-specific key or not a valid key.
+     *
+     * @param key a descriptor key.
+     * @return whether <code>key</code> is a standard descriptor.
+     */
+    boolean isStandardDescriptor(@Nonnull String key);
+
+    /**
+     * Returns {@code true} if {@code key} is a valid single-value
+     * descriptor; otherwise returns {@code false}
+     *
+     * @param key a descriptor key.
+     * @return whether the specified descriptor is multi-valued.
+     * @since JCR 2.0
+     */
+    boolean isSingleValueDescriptor(@Nonnull String key);
+
+    /**
+     * The value of a single-value descriptor is found by passing the key for
+     * that descriptor to this method. If {@code key} is the key of a
+     * multi-value descriptor or not a valid key this method returns
+     * {@code null}.
+     *
+     * @param key a descriptor key.
+     * @return The value of the indicated descriptor
+     */
+    @CheckForNull
+    Value getValue(@Nonnull String key);
+
+    /**
+     * The value array of a multi-value descriptor is found by passing the key
+     * for that descriptor to this method. If {@code key} is the key of a
+     * single-value descriptor then this method returns that value as an array
+     * of size one. If {@code key} is not a valid key this method returns
+     * {@code null}.
+     *
+     * @param key a descriptor key.
+     * @return the value array for the indicated descriptor
+     */
+    @CheckForNull
+    Value[] getValues(@Nonnull String key);
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java?rev=1541782&r1=1541781&r2=1541782&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java Thu Nov 14 01:56:41 2013
@@ -16,16 +16,25 @@
  */
 package org.apache.jackrabbit.oak.core;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.jcr.Credentials;
 import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.PropertyType;
+import javax.jcr.Repository;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
 import javax.security.auth.login.LoginException;
 
+import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Descriptors;
+import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider;
 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
@@ -35,6 +44,59 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static javax.jcr.Repository.IDENTIFIER_STABILITY;
+import static javax.jcr.Repository.LEVEL_1_SUPPORTED;
+import static javax.jcr.Repository.LEVEL_2_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_AUTOCREATED_DEFINITIONS_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_INHERITANCE;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_INHERITANCE_SINGLE;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_MULTIPLE_BINARY_PROPERTIES_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_MULTIVALUED_PROPERTIES_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_ORDERABLE_CHILD_NODES_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_OVERRIDES_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_PRIMARY_ITEM_NAME_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_PROPERTY_TYPES;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_RESIDUAL_DEFINITIONS_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_UPDATE_IN_USE_SUPORTED;
+import static javax.jcr.Repository.NODE_TYPE_MANAGEMENT_VALUE_CONSTRAINTS_SUPPORTED;
+import static javax.jcr.Repository.OPTION_ACCESS_CONTROL_SUPPORTED;
+import static javax.jcr.Repository.OPTION_ACTIVITIES_SUPPORTED;
+import static javax.jcr.Repository.OPTION_BASELINES_SUPPORTED;
+import static javax.jcr.Repository.OPTION_JOURNALED_OBSERVATION_SUPPORTED;
+import static javax.jcr.Repository.OPTION_LIFECYCLE_SUPPORTED;
+import static javax.jcr.Repository.OPTION_LOCKING_SUPPORTED;
+import static javax.jcr.Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED;
+import static javax.jcr.Repository.OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED;
+import static javax.jcr.Repository.OPTION_OBSERVATION_SUPPORTED;
+import static javax.jcr.Repository.OPTION_QUERY_SQL_SUPPORTED;
+import static javax.jcr.Repository.OPTION_RETENTION_SUPPORTED;
+import static javax.jcr.Repository.OPTION_SHAREABLE_NODES_SUPPORTED;
+import static javax.jcr.Repository.OPTION_SIMPLE_VERSIONING_SUPPORTED;
+import static javax.jcr.Repository.OPTION_TRANSACTIONS_SUPPORTED;
+import static javax.jcr.Repository.OPTION_UNFILED_CONTENT_SUPPORTED;
+import static javax.jcr.Repository.OPTION_UPDATE_MIXIN_NODE_TYPES_SUPPORTED;
+import static javax.jcr.Repository.OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED;
+import static javax.jcr.Repository.OPTION_VERSIONING_SUPPORTED;
+import static javax.jcr.Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED;
+import static javax.jcr.Repository.OPTION_XML_EXPORT_SUPPORTED;
+import static javax.jcr.Repository.OPTION_XML_IMPORT_SUPPORTED;
+import static javax.jcr.Repository.QUERY_FULL_TEXT_SEARCH_SUPPORTED;
+import static javax.jcr.Repository.QUERY_JOINS;
+import static javax.jcr.Repository.QUERY_JOINS_NONE;
+import static javax.jcr.Repository.QUERY_LANGUAGES;
+import static javax.jcr.Repository.QUERY_STORED_QUERIES_SUPPORTED;
+import static javax.jcr.Repository.QUERY_XPATH_DOC_ORDER;
+import static javax.jcr.Repository.QUERY_XPATH_POS_INDEX;
+import static javax.jcr.Repository.REP_NAME_DESC;
+import static javax.jcr.Repository.REP_VENDOR_DESC;
+import static javax.jcr.Repository.REP_VENDOR_URL_DESC;
+import static javax.jcr.Repository.REP_VERSION_DESC;
+import static javax.jcr.Repository.SPEC_NAME_DESC;
+import static javax.jcr.Repository.SPEC_VERSION_DESC;
+import static javax.jcr.Repository.WRITE_SUPPORTED;
+
 /**
  * {@code MicroKernel}-based implementation of
  * the {@link ContentRepository} interface.
@@ -47,6 +109,8 @@ public class ContentRepositoryImpl imple
     private final SecurityProvider securityProvider;
     private final QueryIndexProvider indexProvider;
 
+    private DescriptorsImpl descriptors;
+    
     /**
      * Creates an content repository instance based on the given, already
      * initialized components.
@@ -94,4 +158,222 @@ public class ContentRepositoryImpl imple
         return nodeStore;
     }
 
+    @Nonnull
+    @Override
+    public Descriptors getDescriptors() {
+        if (descriptors == null) {
+            descriptors = createDescriptors();
+        }
+        return descriptors;
+    }
+    
+    @SuppressWarnings("deprecation")
+    @Nonnull
+    protected DescriptorsImpl createDescriptors() {
+        final ValueFactory valueFactory = new SimpleValueFactory();
+        final Value trueValue = valueFactory.createValue(true);
+        final Value falseValue = valueFactory.createValue(false);
+        DescriptorsImpl d = new DescriptorsImpl();
+        d.put(new DescriptorsImpl.Descriptor(
+                IDENTIFIER_STABILITY,
+                valueFactory.createValue(Repository.IDENTIFIER_STABILITY_METHOD_DURATION), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                LEVEL_1_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                LEVEL_2_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_AUTOCREATED_DEFINITIONS_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_INHERITANCE,
+                valueFactory.createValue(NODE_TYPE_MANAGEMENT_INHERITANCE_SINGLE), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_MULTIPLE_BINARY_PROPERTIES_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_MULTIVALUED_PROPERTIES_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_ORDERABLE_CHILD_NODES_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_OVERRIDES_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_PRIMARY_ITEM_NAME_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_PROPERTY_TYPES,
+                new Value[] {
+                        valueFactory.createValue(PropertyType.TYPENAME_STRING),
+                        valueFactory.createValue(PropertyType.TYPENAME_BINARY),
+                        valueFactory.createValue(PropertyType.TYPENAME_LONG),
+                        valueFactory.createValue(PropertyType.TYPENAME_LONG),
+                        valueFactory.createValue(PropertyType.TYPENAME_DOUBLE),
+                        valueFactory.createValue(PropertyType.TYPENAME_DECIMAL),
+                        valueFactory.createValue(PropertyType.TYPENAME_DATE),
+                        valueFactory.createValue(PropertyType.TYPENAME_BOOLEAN),
+                        valueFactory.createValue(PropertyType.TYPENAME_NAME),
+                        valueFactory.createValue(PropertyType.TYPENAME_PATH),
+                        valueFactory.createValue(PropertyType.TYPENAME_REFERENCE),
+                        valueFactory.createValue(PropertyType.TYPENAME_WEAKREFERENCE),
+                        valueFactory.createValue(PropertyType.TYPENAME_URI),
+                        valueFactory.createValue(PropertyType.TYPENAME_UNDEFINED)
+                }, false, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_RESIDUAL_DEFINITIONS_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_VALUE_CONSTRAINTS_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                NODE_TYPE_MANAGEMENT_UPDATE_IN_USE_SUPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_ACCESS_CONTROL_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_JOURNALED_OBSERVATION_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_LIFECYCLE_SUPPORTED,
+                falseValue, true, true));
+        // locking support added via JCR layer
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_LOCKING_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_OBSERVATION_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED,
+                supportsSameNameNodeAndProperties() ? trueValue : falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_QUERY_SQL_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_RETENTION_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_SHAREABLE_NODES_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_SIMPLE_VERSIONING_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_TRANSACTIONS_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_UNFILED_CONTENT_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_UPDATE_MIXIN_NODE_TYPES_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_VERSIONING_SUPPORTED,
+                trueValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_WORKSPACE_MANAGEMENT_SUPPORTED,
+                trueValue, true, true));
+        // xml export support added via JCR layer
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_XML_EXPORT_SUPPORTED,
+                falseValue, true, true));
+        // xml import support added via JCR layer
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_XML_IMPORT_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_ACTIVITIES_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                OPTION_BASELINES_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_FULL_TEXT_SEARCH_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_JOINS,
+                valueFactory.createValue(QUERY_JOINS_NONE), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_LANGUAGES,
+                new Value[0], false, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_STORED_QUERIES_SUPPORTED,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_XPATH_DOC_ORDER,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                QUERY_XPATH_POS_INDEX,
+                falseValue, true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                REP_NAME_DESC,
+                valueFactory.createValue("Apache Jackrabbit Oak"), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                REP_VERSION_DESC,
+                valueFactory.createValue(getVersion()), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                REP_VENDOR_DESC,
+                valueFactory.createValue("The Apache Software Foundation"), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                REP_VENDOR_URL_DESC,
+                valueFactory.createValue("http://www.apache.org/"), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                SPEC_NAME_DESC,
+                valueFactory.createValue("Content Repository for Java Technology API"), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                SPEC_VERSION_DESC,
+                valueFactory.createValue("2.0"), true, true));
+        d.put(new DescriptorsImpl.Descriptor(
+                WRITE_SUPPORTED,
+                trueValue, true, true));
+
+        return d;
+    }
+
+    /**
+     * Checks if this repository supports same name node and properties. currently this is tied to the underlying
+     * node store implementation class.
+     *
+     * @return {@code true} if this repository supports SNNP.
+     */
+    private boolean supportsSameNameNodeAndProperties() {
+        return !(nodeStore instanceof KernelNodeStore);
+    }
+
+    /**
+     * Returns the version of this repository implementation.
+     * @return the version
+     */
+    @Nonnull
+    private static String getVersion() {
+        InputStream stream = ContentRepositoryImpl.class.getResourceAsStream(
+                "/META-INF/maven/org.apache.jackrabbit/oak-core/pom.properties");
+        if (stream != null) {
+            try {
+                try {
+                    Properties properties = new Properties();
+                    properties.load(stream);
+                    return properties.getProperty("version");
+                } finally {
+                    stream.close();
+                }
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+        return "SNAPSHOT";
+    }
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/DescriptorsImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/DescriptorsImpl.java?rev=1541782&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/DescriptorsImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/DescriptorsImpl.java Thu Nov 14 01:56:41 2013
@@ -0,0 +1,156 @@
+/*
+ * 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.jackrabbit.oak.core;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.oak.api.Descriptors;
+
+/**
+ * Default implementation of the {@link Descriptors} interface. Supports overlying of given default descriptors.
+ */
+public class DescriptorsImpl implements org.apache.jackrabbit.oak.api.Descriptors {
+
+    private final Descriptors base;
+
+    private final Map<String, Descriptor> descriptors = new ConcurrentHashMap<String, Descriptor>();
+
+    /**
+     * Constructs an empty descriptors set.
+     */
+    public DescriptorsImpl() {
+        base = null;
+    }
+
+    /**
+     * Constructs a descriptors set that uses the given {@code base} descriptors as base.
+     * @param base the base descriptors or {@code null}
+     */
+    public DescriptorsImpl(@Nullable Descriptors base) {
+        this.base = base;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Note: If this descriptors are based on default descriptors, the returns string array is a merge of this and the
+     * base's keys.
+     */
+    @Nonnull
+    @Override
+    public String[] getKeys() {
+        Set<String> keys = new HashSet<String>(descriptors.keySet());
+        if (base != null) {
+            Collections.addAll(keys, base.getKeys());
+        }
+        return keys.toArray(new String[keys.size()]);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Note: If the descriptor with {@code key} does not exist in this set, the call is delegated to the base descriptors.
+     */
+    @Override
+    public boolean isStandardDescriptor(@Nonnull String key) {
+        return descriptors.containsKey(key) && descriptors.get(key).standard
+                || base != null && base.isStandardDescriptor(key);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Note: If the descriptor with {@code key} does not exist in this set, the call is delegated to the base descriptors.
+     */
+    @Override
+    public boolean isSingleValueDescriptor(@Nonnull String key) {
+        return descriptors.containsKey(key) && descriptors.get(key).singleValued
+                || base != null && base.isSingleValueDescriptor(key);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Note: If the descriptor with {@code key} does not exist in this set, the call is delegated to the base descriptors.
+     */
+    @CheckForNull
+    @Override
+    public Value getValue(@Nonnull String key) {
+        Descriptor d = descriptors.get(key);
+        if (d == null) {
+            return base == null ? null : base.getValue(key);
+        }
+        return !d.singleValued ? null : d.values[0];
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Note: If the descriptor with {@code key} does not exist in this set, the call is delegated to the base descriptors.
+     */
+    @CheckForNull
+    @Override
+    public Value[] getValues(@Nonnull String key) {
+        Descriptor d = descriptors.get(key);
+        if (d == null) {
+            return base == null ? null : base.getValues(key);
+        }
+        return d.values;
+    }
+
+    /**
+     * Adds a new descriptor to this set of descriptors which overlay the ones from the base set.
+     * @param descriptor the descriptor to add.
+     */
+    public void put(@Nonnull Descriptor descriptor) {
+        descriptors.put(descriptor.name, descriptor);
+    }
+
+    /**
+     * Internal Descriptor class
+     */
+    public static final class Descriptor {
+        final String name;
+        final Value[] values;
+        final boolean singleValued;
+        final boolean standard;
+
+        public Descriptor(String name, Value[] values, boolean singleValued, boolean standard) {
+            this.name = name;
+            this.values = values;
+            this.singleValued = singleValued;
+            this.standard = standard;
+        }
+
+        public Descriptor(String name, Value value, boolean singleValued, boolean standard) {
+            this(name, new Value[]{ value }, singleValued, standard);
+        }
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/JcrDescriptorsImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/JcrDescriptorsImpl.java?rev=1541782&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/JcrDescriptorsImpl.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/JcrDescriptorsImpl.java Thu Nov 14 01:56:41 2013
@@ -0,0 +1,51 @@
+/*
+ * 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.jackrabbit.oak.jcr.repository;
+
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.oak.api.Descriptors;
+import org.apache.jackrabbit.oak.core.DescriptorsImpl;
+
+import static javax.jcr.Repository.OPTION_LOCKING_SUPPORTED;
+import static javax.jcr.Repository.OPTION_XML_EXPORT_SUPPORTED;
+import static javax.jcr.Repository.OPTION_XML_IMPORT_SUPPORTED;
+
+/**
+ * The {@code JcrDescriptorsImpl} extend the {@link DescriptorsImpl} by automatically marking some of the JCR
+ * features as supported.
+ */
+public class JcrDescriptorsImpl extends DescriptorsImpl {
+
+    public JcrDescriptorsImpl(Descriptors base, ValueFactory valueFactory) {
+        super(base);
+
+        // add the descriptors of the features that are provided by the JCR layer
+        final Value trueValue = valueFactory.createValue(true);
+        final Value falseValue = valueFactory.createValue(false);
+        put(new DescriptorsImpl.Descriptor(
+                OPTION_LOCKING_SUPPORTED,
+                trueValue, true, true));
+        put(new DescriptorsImpl.Descriptor(
+                OPTION_XML_EXPORT_SUPPORTED,
+                trueValue, true, true));
+        put(new DescriptorsImpl.Descriptor(
+                OPTION_XML_IMPORT_SUPPORTED,
+                trueValue, true, true));
+   }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java?rev=1541782&r1=1541781&r2=1541782&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java Thu Nov 14 01:56:41 2013
@@ -37,6 +37,8 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Descriptors;
+import org.apache.jackrabbit.oak.core.DescriptorsImpl;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.LogOnce;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.Once;
@@ -67,7 +69,7 @@ public class RepositoryImpl implements J
      */
     public static final String REFRESH_INTERVAL = "oak.refresh-interval";
 
-    private final Descriptors descriptors;
+    private final DescriptorsImpl descriptors;
     private final ContentRepository contentRepository;
     protected final Whiteboard whiteboard;
     private final SecurityProvider securityProvider;
@@ -239,8 +241,8 @@ public class RepositoryImpl implements J
      * by the subclasses to add more values to the descriptor
      * @return  repository descriptor
      */
-    protected Descriptors determineDescriptors() {
-        return new Descriptors(new SimpleValueFactory());
+    protected DescriptorsImpl determineDescriptors() {
+        return new JcrDescriptorsImpl(contentRepository.getDescriptors(), new SimpleValueFactory());
     }
 
     /**

Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/SameNamePropertyNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/SameNamePropertyNodeTest.java?rev=1541782&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/SameNamePropertyNodeTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/SameNamePropertyNodeTest.java Thu Nov 14 01:56:41 2013
@@ -0,0 +1,142 @@
+/*
+ * 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.jackrabbit.oak.jcr;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.junit.Test;
+
+public class SameNamePropertyNodeTest extends AbstractJCRTest {
+
+    private String sameName = "sameName";
+    private Node n;
+    private Property p;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        if (!getHelper().getRepository().getDescriptorValue(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED).getBoolean()) {
+            throw new NotExecutableException("node and property with same name is not supported");
+        }
+
+        n = testRootNode.addNode(sameName);
+        p = testRootNode.setProperty(sameName, "value");
+        superuser.save();
+    }
+
+    @Test
+    public void testIsSame() throws Exception {
+        assertFalse(n.isSame(p));
+        assertFalse(p.isSame(n));
+    }
+
+    @Test
+    public void testNodeExists() throws Exception {
+        assertTrue(superuser.nodeExists(n.getPath()));
+    }
+
+    @Test
+    public void testSessionGetNode() throws Exception {
+        Node nn = superuser.getNode(n.getPath());
+        assertTrue(n.isSame(nn));
+    }
+
+    @Test
+    public void testHasNode() throws Exception {
+        assertTrue(testRootNode.hasNode(sameName));
+    }
+
+    @Test
+    public void testGetNode() throws Exception {
+        assertTrue(n.isSame(testRootNode.getNode(sameName)));
+        assertFalse(n.isSame(p));
+    }
+
+    @Test
+    public void testPropertyExists() throws Exception {
+        assertTrue(superuser.propertyExists(p.getPath()));
+    }
+
+    @Test
+    public void testSessionGetProperty() throws Exception {
+        Property pp = superuser.getProperty(p.getPath());
+        assertTrue(p.isSame(pp));
+    }
+
+    @Test
+    public void testHasProperty() throws Exception {
+        assertTrue(testRootNode.hasProperty(sameName));
+    }
+
+    @Test
+    public void testGetProperty() throws Exception {
+        assertTrue(p.isSame(testRootNode.getProperty(sameName)));
+        assertFalse(p.isSame(n));
+    }
+
+    @Test
+    public void testItemExists() throws Exception {
+        assertTrue(superuser.itemExists(n.getPath()));
+    }
+
+    @Test
+    public void testGetItem() throws Exception {
+        Item item = superuser.getItem(n.getPath());
+        if (item.isNode()) {
+            assertTrue(n.isSame(item));
+        } else {
+            assertTrue(p.isSame(item));
+        }
+    }
+
+    /**
+     * Tests if a microkernel fixture sets the SNNP repository descriptor to false.
+     */
+    @Test
+    public void testMicroKernelSupport() throws Exception {
+        NodeStore nodeStore = NodeStoreFixture.MK_IMPL.createNodeStore();
+        JackrabbitRepository repository  = (JackrabbitRepository) new Jcr(nodeStore).createRepository();
+        try {
+            assertFalse(repository.getDescriptorValue(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED).getBoolean());
+        } finally {
+            repository.shutdown();
+        }
+    }
+
+    /**
+     * Tests if a nodestore fixture sets the SNNP repository descriptor to true.
+     */
+    @Test
+    public void testNodeStoreSupport() throws Exception {
+        NodeStore nodeStore = NodeStoreFixture.SEGMENT_MK.createNodeStore();
+        JackrabbitRepository repository  = (JackrabbitRepository) new Jcr(nodeStore).createRepository();
+        try {
+            assertTrue(repository.getDescriptorValue(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED).getBoolean());
+        } finally {
+            repository.shutdown();
+        }
+
+    }
+}
\ No newline at end of file