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 23:34:28 UTC
svn commit: r1542109 - 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-core/src/main/java/org/apache/jackrabbit/oak/util/
oak-jcr/src/main/java/org/apache/jackra...
Author: tripod
Date: Thu Nov 14 22:34:27 2013
New Revision: 1542109
URL: http://svn.apache.org/r1542109
Log:
OAK-1126: Same node and property name support
This reverts commit f3f78810e7eda7fe127a3f7f711b8fa28f88c5fd.
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/util/GenericDescriptors.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=1542109&r1=1542108&r2=1542109&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 22:34:27 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=1542109&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 22:34:27 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=1542109&r1=1542108&r2=1542109&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 22:34:27 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;
@@ -34,6 +43,60 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.authentication.LoginContext;
import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.util.GenericDescriptors;
+
+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
@@ -47,6 +110,8 @@ public class ContentRepositoryImpl imple
private final SecurityProvider securityProvider;
private final QueryIndexProvider indexProvider;
+ private GenericDescriptors descriptors;
+
/**
* Creates an content repository instance based on the given, already
* initialized components.
@@ -94,4 +159,125 @@ public class ContentRepositoryImpl imple
return nodeStore;
}
+ @Nonnull
+ @Override
+ public Descriptors getDescriptors() {
+ if (descriptors == null) {
+ descriptors = createDescriptors();
+ }
+ return descriptors;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Nonnull
+ protected GenericDescriptors createDescriptors() {
+ final ValueFactory valueFactory = new SimpleValueFactory();
+ final Value trueValue = valueFactory.createValue(true);
+ final Value falseValue = valueFactory.createValue(false);
+ return new GenericDescriptors()
+ .put(IDENTIFIER_STABILITY, valueFactory.createValue(Repository.IDENTIFIER_STABILITY_METHOD_DURATION), true, true)
+ .put(LEVEL_1_SUPPORTED, trueValue, true, true)
+ .put(LEVEL_2_SUPPORTED, trueValue, true, true)
+ .put(OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_AUTOCREATED_DEFINITIONS_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_INHERITANCE, valueFactory.createValue(NODE_TYPE_MANAGEMENT_INHERITANCE_SINGLE), true, true)
+ .put(NODE_TYPE_MANAGEMENT_MULTIPLE_BINARY_PROPERTIES_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_MULTIVALUED_PROPERTIES_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_ORDERABLE_CHILD_NODES_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_OVERRIDES_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_PRIMARY_ITEM_NAME_SUPPORTED, trueValue, true, true)
+ .put(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)
+ .put(NODE_TYPE_MANAGEMENT_RESIDUAL_DEFINITIONS_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_VALUE_CONSTRAINTS_SUPPORTED, trueValue, true, true)
+ .put(NODE_TYPE_MANAGEMENT_UPDATE_IN_USE_SUPORTED, falseValue, true, true)
+ .put(OPTION_ACCESS_CONTROL_SUPPORTED, trueValue, true, true)
+ .put(OPTION_JOURNALED_OBSERVATION_SUPPORTED, falseValue, true, true)
+ .put(OPTION_LIFECYCLE_SUPPORTED, falseValue, true, true)
+ // locking support added via JCR layer
+ .put(OPTION_LOCKING_SUPPORTED, falseValue, true, true)
+ .put(OPTION_OBSERVATION_SUPPORTED, trueValue, true, true)
+ .put(OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED,
+ supportsSameNameNodeAndProperties() ? trueValue : falseValue, true, true)
+ .put(OPTION_QUERY_SQL_SUPPORTED, falseValue, true, true)
+ .put(OPTION_RETENTION_SUPPORTED, falseValue, true, true)
+ .put(OPTION_SHAREABLE_NODES_SUPPORTED, falseValue, true, true)
+ // todo: let plugin set the descriptor
+ .put(OPTION_SIMPLE_VERSIONING_SUPPORTED, falseValue, true, true)
+ .put(OPTION_TRANSACTIONS_SUPPORTED, falseValue, true, true)
+ .put(OPTION_UNFILED_CONTENT_SUPPORTED, falseValue, true, true)
+ .put(OPTION_UPDATE_MIXIN_NODE_TYPES_SUPPORTED, trueValue, true, true)
+ .put(OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED, trueValue, true, true)
+ .put(OPTION_VERSIONING_SUPPORTED, trueValue, true, true)
+ .put(OPTION_WORKSPACE_MANAGEMENT_SUPPORTED, trueValue, true, true)
+ // xml export support added via JCR layer
+ .put(OPTION_XML_EXPORT_SUPPORTED, falseValue, true, true)
+ // xml import support added via JCR layer
+ .put(OPTION_XML_IMPORT_SUPPORTED, falseValue, true, true)
+ .put(OPTION_ACTIVITIES_SUPPORTED, falseValue, true, true)
+ .put(OPTION_BASELINES_SUPPORTED, falseValue, true, true)
+ .put(QUERY_FULL_TEXT_SEARCH_SUPPORTED, falseValue, true, true)
+ .put(QUERY_JOINS, valueFactory.createValue(QUERY_JOINS_NONE), true, true)
+ .put(QUERY_LANGUAGES, new Value[0], false, true)
+ .put(QUERY_STORED_QUERIES_SUPPORTED, falseValue, true, true)
+ .put(QUERY_XPATH_DOC_ORDER, falseValue, true, true)
+ .put(QUERY_XPATH_POS_INDEX, falseValue, true, true)
+ .put(REP_NAME_DESC, valueFactory.createValue("Apache Jackrabbit Oak"), true, true)
+ .put(REP_VERSION_DESC, valueFactory.createValue(getVersion()), true, true)
+ .put(REP_VENDOR_DESC, valueFactory.createValue("The Apache Software Foundation"), true, true)
+ .put(REP_VENDOR_URL_DESC, valueFactory.createValue("http://www.apache.org/"), true, true)
+ .put(SPEC_NAME_DESC, valueFactory.createValue("Content Repository for Java Technology API"), true, true)
+ .put(SPEC_VERSION_DESC, valueFactory.createValue("2.0"), true, true)
+ .put(WRITE_SUPPORTED, trueValue, true, true);
+ }
+
+ /**
+ * 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/util/GenericDescriptors.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/GenericDescriptors.java?rev=1542109&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/GenericDescriptors.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/GenericDescriptors.java Thu Nov 14 22:34:27 2013
@@ -0,0 +1,173 @@
+/*
+ * 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.util;
+
+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 GenericDescriptors 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 GenericDescriptors() {
+ base = null;
+ }
+
+ /**
+ * Constructs a descriptors set that uses the given {@code base} descriptors as base.
+ * @param base the base descriptors or {@code null}
+ */
+ public GenericDescriptors(@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 name descriptor name
+ * @param values array of descriptor values
+ * @param singleValued flag indicating if this is single valued descriptor. see {@link Descriptors#isSingleValueDescriptor(String)}
+ * @param standard flag indicating if this is a standard descriptor. see {@link Descriptors#isStandardDescriptor(String)}
+ * @return {@code this} suitable for chaining.
+ */
+ public GenericDescriptors put(@Nonnull String name, @Nonnull Value[] values, boolean singleValued, boolean standard) {
+ descriptors.put(name, new Descriptor(name, values, singleValued, standard));
+ return this;
+ }
+
+ /**
+ * Adds a new descriptor to this set of descriptors which overlay the ones from the base set.
+ *
+ * @param name descriptor name
+ * @param value descriptor value
+ * @param singleValued flag indicating if this is single valued descriptor. see {@link Descriptors#isSingleValueDescriptor(String)}
+ * @param standard flag indicating if this is a standard descriptor. see {@link Descriptors#isStandardDescriptor(String)}
+ * @return {@code this} suitable for chaining.
+ */
+ public GenericDescriptors put(@Nonnull String name, @Nonnull Value value, boolean singleValued, boolean standard) {
+ descriptors.put(name, new Descriptor(name, new Value[]{value}, singleValued, standard));
+ return this;
+ }
+
+ /**
+ * Internal Descriptor class
+ */
+ private 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;
+ }
+ }
+
+}
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=1542109&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 22:34:27 2013
@@ -0,0 +1,44 @@
+/*
+ * 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.util.GenericDescriptors;
+
+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 org.apache.jackrabbit.oak.util.GenericDescriptors} by automatically marking some of the JCR
+ * features as supported.
+ */
+public class JcrDescriptorsImpl extends GenericDescriptors {
+
+ 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);
+ put(OPTION_LOCKING_SUPPORTED, trueValue, true, true);
+ put(OPTION_XML_EXPORT_SUPPORTED, trueValue, true, true);
+ put(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=1542109&r1=1542108&r2=1542109&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 22:34:27 2013
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.oak.jcr.repository;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import java.util.Collections;
import java.util.Map;
@@ -37,18 +35,21 @@ 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.jcr.delegate.SessionDelegate;
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;
import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.ThreadSynchronising;
import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.Timed;
import org.apache.jackrabbit.oak.jcr.session.SessionContext;
-import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.util.GenericDescriptors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* TODO document
*/
@@ -67,7 +68,7 @@ public class RepositoryImpl implements J
*/
public static final String REFRESH_INTERVAL = "oak.refresh-interval";
- private final Descriptors descriptors;
+ private final GenericDescriptors descriptors;
private final ContentRepository contentRepository;
protected final Whiteboard whiteboard;
private final SecurityProvider securityProvider;
@@ -239,15 +240,15 @@ 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 GenericDescriptors determineDescriptors() {
+ return new JcrDescriptorsImpl(contentRepository.getDescriptors(), new SimpleValueFactory());
}
/**
* Returns the descriptors associated with the repository
* @return repository descriptor
*/
- protected Descriptors getDescriptors() {
+ protected GenericDescriptors getDescriptors() {
return descriptors;
}
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=1542109&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 22:34:27 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