Index: dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java (working copy) @@ -100,14 +100,11 @@ */ public final String getUUID() throws RepositoryException { // Return "jcr:uuid" only if node is referenceable - Property mixinsProp = getProperty(JcrLexicon.MIXIN_TYPES); - if (mixinsProp != null) { - String referenceableMixinName = JcrMixLexicon.REFERENCEABLE.getString(namespaces()); - for (Value value : mixinsProp.getValues()) { - if (referenceableMixinName.equals(value.getString())) return nodeUuid.toString(); - } + String referenceableTypeName = JcrMixLexicon.REFERENCEABLE.getString(namespaces()); + if (!isNodeType(referenceableTypeName)) { + throw new UnsupportedRepositoryOperationException(); } - throw new UnsupportedRepositoryOperationException(); + return nodeUuid.toString(); } /** @@ -171,7 +168,7 @@ * @see javax.jcr.Node#getMixinNodeTypes() */ public NodeType[] getMixinNodeTypes() throws RepositoryException { - NodeTypeManager nodeTypeManager = session().getWorkspace().getNodeTypeManager(); + NodeTypeManager nodeTypeManager = session().nodeTypeManager(); Property mixinTypesProperty = getProperty(JcrLexicon.MIXIN_TYPES); if (mixinTypesProperty == null) return EMPTY_NODE_TYPES; List mixinNodeTypes = new LinkedList(); Index: dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java (working copy) @@ -57,6 +57,9 @@ protected static final boolean ORDERABLE_CHILD_NODES = true; protected static final boolean UNORDERABLE_CHILD_NODES = false; + /** Link to the repository node type manager to which the nodes defined in this source belong. */ + protected static final RepositoryNodeTypeManager NO_NODE_TYPE_MANAGER = null; + /** The predecessor node type source. */ private final JcrNodeTypeSource predecessor; Index: dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java (working copy) @@ -78,7 +78,7 @@ } JcrValue createValue( Object value ) throws RepositoryException { - return new JcrValue(context().getValueFactories(), propertyInfo().getPropertyType(), value); + return new JcrValue(context().getValueFactories(), this.cache, propertyInfo().getPropertyType(), value); } @Override Index: dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java (working copy) @@ -30,6 +30,7 @@ import javax.jcr.PropertyType; import javax.jcr.nodetype.NodeType; import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.JcrMixLexicon; /** @@ -43,7 +44,7 @@ /** The list of mixin node types. */ private final List mixinNodeTypes; - DnaBuiltinNodeTypeSource( JcrSession session, + DnaBuiltinNodeTypeSource( ExecutionContext context, JcrNodeTypeSource predecessor ) { super(predecessor); @@ -53,28 +54,29 @@ JcrNodeType base = findType(JcrNtLexicon.BASE); if (base == null) { - String baseTypeName = JcrNtLexicon.BASE.getString(session.getExecutionContext().getNamespaceRegistry()); - String namespaceTypeName = DnaLexicon.NAMESPACE.getString(session.getExecutionContext().getNamespaceRegistry()); + String baseTypeName = JcrNtLexicon.BASE.getString(context.getNamespaceRegistry()); + String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry()); throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName)); } JcrNodeType referenceable = findType(JcrMixLexicon.REFERENCEABLE); if (referenceable == null) { - String baseTypeName = JcrMixLexicon.REFERENCEABLE.getString(session.getExecutionContext().getNamespaceRegistry()); - String namespaceTypeName = DnaLexicon.SYSTEM.getString(session.getExecutionContext().getNamespaceRegistry()); + String baseTypeName = JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry()); + String namespaceTypeName = DnaLexicon.SYSTEM.getString(context.getNamespaceRegistry()); throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName)); } // Stubbing in child node and property definitions for now JcrNodeType namespace = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, DnaLexicon.NAMESPACE, Arrays.asList(new NodeType[] {base}), DnaLexicon.URI, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, DnaLexicon.URI, OnParentVersionBehavior.VERSION.getJcrValue(), @@ -88,12 +90,13 @@ NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType namespaces = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, DnaLexicon.NAMESPACES, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, null, OnParentVersionBehavior.VERSION.getJcrValue(), @@ -106,12 +109,13 @@ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType system = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, DnaLexicon.SYSTEM, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, DnaLexicon.NAMESPACES, OnParentVersionBehavior.VERSION.getJcrValue(), @@ -123,25 +127,18 @@ new NodeType[] {namespaces})}), NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES); - JcrNodeType root = new JcrNodeType(session, DnaLexicon.ROOT, Arrays.asList(new NodeType[] {base, referenceable}), - NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] { - new JcrNodeDefinition(session, null, JcrLexicon.SYSTEM, - OnParentVersionBehavior.IGNORE.getJcrValue(), true, true, - true, false, DnaLexicon.SYSTEM, new NodeType[] {system}), - new JcrNodeDefinition(session, null, ALL_NODES, - OnParentVersionBehavior.VERSION.getJcrValue(), false, false, - false, true, JcrNtLexicon.UNSTRUCTURED, - new NodeType[] {base}), + JcrNodeType root = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, DnaLexicon.ROOT, Arrays.asList(new NodeType[] {base, + referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] { + new JcrNodeDefinition(context, null, JcrLexicon.SYSTEM, OnParentVersionBehavior.IGNORE.getJcrValue(), true, true, + true, false, DnaLexicon.SYSTEM, new NodeType[] {system}), + new JcrNodeDefinition(context, null, ALL_NODES, OnParentVersionBehavior.VERSION.getJcrValue(), false, false, false, + true, JcrNtLexicon.UNSTRUCTURED, new NodeType[] {base}), - }), Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, ALL_NODES, - OnParentVersionBehavior.COPY.getJcrValue(), false, - false, false, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, - NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, ALL_NODES, - OnParentVersionBehavior.COPY.getJcrValue(), false, - false, false, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, - NO_CONSTRAINTS, true),}), NOT_MIXIN, + }), Arrays.asList(new JcrPropertyDefinition[] { + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, + NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, false), + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, + NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, true),}), NOT_MIXIN, ORDERABLE_CHILD_NODES); primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace,})); Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java (working copy) @@ -31,6 +31,7 @@ import javax.jcr.Value; import javax.jcr.nodetype.NodeType; import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; import org.jboss.dna.graph.property.basic.BasicName; @@ -45,27 +46,30 @@ /** The list of mixin node types. */ private final List mixinNodeTypes; - JcrBuiltinNodeTypeSource( JcrSession session ) { - this(session, null); + JcrBuiltinNodeTypeSource( ExecutionContext context ) { + this(context, null); } - JcrBuiltinNodeTypeSource( JcrSession session, + JcrBuiltinNodeTypeSource( ExecutionContext context, JcrNodeTypeSource predecessor ) { super(predecessor); primaryNodeTypes = new ArrayList(); - Value trueValue = new JcrValue(session.getExecutionContext().getValueFactories(), PropertyType.BOOLEAN, Boolean.TRUE); - Value ntBaseValue = new JcrValue(session.getExecutionContext().getValueFactories(), PropertyType.NAME, JcrNtLexicon.BASE); + /* + * These values get created without a session cache, as they aren't tied to any particular session. + */ + Value trueValue = new JcrValue(context.getValueFactories(), null, PropertyType.BOOLEAN, Boolean.TRUE); + Value ntBaseValue = new JcrValue(context.getValueFactories(), null, PropertyType.NAME, JcrNtLexicon.BASE); // Stubbing in child node and property definitions for now - JcrNodeType base = new JcrNodeType(session, JcrNtLexicon.BASE, NO_SUPERTYPES, NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, - Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.PRIMARY_TYPE, + JcrNodeType base = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.BASE, NO_SUPERTYPES, NO_PRIMARY_ITEM_NAME, + NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { + new JcrPropertyDefinition(context, null, JcrLexicon.PRIMARY_TYPE, OnParentVersionBehavior.COMPUTE.getJcrValue(), true, true, true, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.MIXIN_TYPES, + new JcrPropertyDefinition(context, null, JcrLexicon.MIXIN_TYPES, OnParentVersionBehavior.COMPUTE.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, true)}), NOT_MIXIN, @@ -73,13 +77,14 @@ // This needs to be declared early, as some of the primary types reference it JcrNodeType referenceable = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrMixLexicon.REFERENCEABLE, NO_SUPERTYPES, NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, JcrLexicon.UUID, OnParentVersionBehavior.INITIALIZE.getJcrValue(), @@ -93,14 +98,15 @@ IS_A_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType childNodeDefinition = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.CHILD_NODE_DEFINITION, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { new JcrPropertyDefinition( - session, + context, null, JcrLexicon.AUTO_CREATED, OnParentVersionBehavior.COPY.getJcrValue(), @@ -108,14 +114,14 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.DEFAULT_PRIMARY_TYPE, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.MANDATORY, OnParentVersionBehavior.COPY.getJcrValue(), @@ -123,14 +129,14 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.NAME, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.ON_PARENT_VERSION, OnParentVersionBehavior.COPY.getJcrValue(), @@ -138,7 +144,7 @@ PropertyType.STRING, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.PROTECTED, OnParentVersionBehavior.COPY.getJcrValue(), @@ -146,7 +152,7 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.REQUIRED_PRIMARY_TYPES, OnParentVersionBehavior.COPY.getJcrValue(), @@ -154,7 +160,7 @@ new Value[] {ntBaseValue}, PropertyType.NAME, NO_CONSTRAINTS, true), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.SAME_NAME_SIBLINGS, OnParentVersionBehavior.COPY.getJcrValue(), @@ -164,13 +170,14 @@ UNORDERABLE_CHILD_NODES); JcrNodeType hierarchyNode = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.HIERARCHY_NODE, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, JcrLexicon.CREATED, OnParentVersionBehavior.INITIALIZE.getJcrValue(), @@ -184,12 +191,13 @@ NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType file = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.FILE, Arrays.asList(new NodeType[] {hierarchyNode}), JcrLexicon.CONTENT, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, JcrLexicon.CONTENT, OnParentVersionBehavior.COPY.getJcrValue(), @@ -199,12 +207,13 @@ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType folder = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.FOLDER, Arrays.asList(new NodeType[] {hierarchyNode}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, null, OnParentVersionBehavior.VERSION.getJcrValue(), @@ -217,12 +226,13 @@ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType frozenNode = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.FROZEN_NODE, Arrays.asList(new NodeType[] {base, referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, ALL_NODES, OnParentVersionBehavior.ABORT.getJcrValue(), @@ -233,36 +243,37 @@ null, new NodeType[] {base})}), Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.FROZEN_MIXIN_TYPES, + new JcrPropertyDefinition(context, null, JcrLexicon.FROZEN_MIXIN_TYPES, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, true), - new JcrPropertyDefinition(session, null, JcrLexicon.FROZEN_PRIMARY_TYPE, + new JcrPropertyDefinition(context, null, JcrLexicon.FROZEN_PRIMARY_TYPE, OnParentVersionBehavior.ABORT.getJcrValue(), true, true, true, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.FROZEN_UUID, + new JcrPropertyDefinition(context, null, JcrLexicon.FROZEN_UUID, OnParentVersionBehavior.ABORT.getJcrValue(), true, true, true, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, ALL_NODES, + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, ALL_NODES, + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, true),}), NOT_MIXIN, ORDERABLE_CHILD_NODES); JcrNodeType linkedFile = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.LINKED_FILE, Arrays.asList(new NodeType[] {hierarchyNode}), JcrLexicon.CONTENT, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, JcrLexicon.CONTENT, OnParentVersionBehavior.COPY.getJcrValue(), @@ -277,14 +288,15 @@ // Had to be moved above nodeType due to dependency JcrNodeType propertyDefinition = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.PROPERTY_DEFINITION, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { new JcrPropertyDefinition( - session, + context, null, JcrLexicon.AUTO_CREATED, OnParentVersionBehavior.COPY.getJcrValue(), @@ -292,7 +304,7 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.DEFAULT_VALUES, OnParentVersionBehavior.COPY.getJcrValue(), @@ -300,7 +312,7 @@ PropertyType.UNDEFINED, NO_CONSTRAINTS, true), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.MANDATORY, OnParentVersionBehavior.COPY.getJcrValue(), @@ -308,7 +320,7 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.MULTIPLE, OnParentVersionBehavior.COPY.getJcrValue(), @@ -316,21 +328,21 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.NAME, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.ON_PARENT_VERSION, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.PROTECTED, OnParentVersionBehavior.COPY.getJcrValue(), @@ -338,14 +350,14 @@ PropertyType.BOOLEAN, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.REQUIRED_TYPE, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false), new JcrPropertyDefinition( - session, + context, null, JcrLexicon.VALUE_CONSTRAINTS, OnParentVersionBehavior.COPY.getJcrValue(), @@ -353,79 +365,82 @@ PropertyType.STRING, NO_CONSTRAINTS, true)}), NOT_MIXIN, UNORDERABLE_CHILD_NODES); - JcrNodeType nodeType = new JcrNodeType(session, JcrNtLexicon.NODE_TYPE, Arrays.asList(new NodeType[] {base}), - NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] { - new JcrNodeDefinition(session, null, JcrLexicon.CHILD_NODE_DEFINITION, + JcrNodeType nodeType = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.NODE_TYPE, + Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, + Arrays.asList(new JcrNodeDefinition[] { + new JcrNodeDefinition(context, null, JcrLexicon.CHILD_NODE_DEFINITION, OnParentVersionBehavior.VERSION.getJcrValue(), false, false, false, true, JcrNtLexicon.CHILD_NODE_DEFINITION, new NodeType[] {childNodeDefinition}), - new JcrNodeDefinition(session, null, JcrLexicon.PROPERTY_DEFINITION, + new JcrNodeDefinition(context, null, JcrLexicon.PROPERTY_DEFINITION, OnParentVersionBehavior.VERSION.getJcrValue(), false, false, false, true, JcrNtLexicon.PROPERTY_DEFINITION, new NodeType[] {propertyDefinition})}), Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.HAS_ORDERABLE_CHILD_NODES, + new JcrPropertyDefinition(context, null, JcrLexicon.HAS_ORDERABLE_CHILD_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.BOOLEAN, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.IS_MIXIN, + new JcrPropertyDefinition(context, null, JcrLexicon.IS_MIXIN, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.BOOLEAN, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.NODE_TYPE_NAME, + new JcrPropertyDefinition(context, null, JcrLexicon.NODE_TYPE_NAME, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.PRIMARY_ITEM_NAME, + new JcrPropertyDefinition(context, null, JcrLexicon.PRIMARY_ITEM_NAME, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.SUPERTYPES, + new JcrPropertyDefinition(context, null, JcrLexicon.SUPERTYPES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, NO_CONSTRAINTS, true),}), NOT_MIXIN, UNORDERABLE_CHILD_NODES); - JcrNodeType query = new JcrNodeType(session, JcrNtLexicon.QUERY, Arrays.asList(new NodeType[] {base}), - NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.LANGUAGE, + JcrNodeType query = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.QUERY, + Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, + Arrays.asList(new JcrPropertyDefinition[] { + new JcrPropertyDefinition(context, null, JcrLexicon.LANGUAGE, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.STATEMENT, + new JcrPropertyDefinition(context, null, JcrLexicon.STATEMENT, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false),}), NOT_MIXIN, UNORDERABLE_CHILD_NODES); - JcrNodeType resource = new JcrNodeType(session, JcrNtLexicon.RESOURCE, + JcrNodeType resource = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.RESOURCE, Arrays.asList(new NodeType[] {base, referenceable}), JcrLexicon.DATA, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.DATA, + new JcrPropertyDefinition(context, null, JcrLexicon.DATA, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.BINARY, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.ENCODING, + new JcrPropertyDefinition(context, null, JcrLexicon.ENCODING, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.LAST_MODIFIED, + new JcrPropertyDefinition(context, null, JcrLexicon.LAST_MODIFIED, OnParentVersionBehavior.IGNORE.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.DATE, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.MIMETYPE, + new JcrPropertyDefinition(context, null, JcrLexicon.MIMETYPE, OnParentVersionBehavior.COPY.getJcrValue(), false, true, false, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false),}), NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType unstructured = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.UNSTRUCTURED, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, ALL_NODES, OnParentVersionBehavior.VERSION.getJcrValue(), @@ -436,23 +451,24 @@ JcrNtLexicon.UNSTRUCTURED, new NodeType[] {base}),}), Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, ALL_NODES, + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, ALL_NODES, + new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, true),}), NOT_MIXIN, ORDERABLE_CHILD_NODES); JcrNodeType version = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.VERSION, Arrays.asList(new NodeType[] {base, referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition( - session, + context, null, JcrLexicon.FROZEN_NODE, OnParentVersionBehavior.ABORT.getJcrValue(), @@ -463,28 +479,29 @@ null, new NodeType[] {frozenNode}),}), Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.CREATED, + new JcrPropertyDefinition(context, null, JcrLexicon.CREATED, OnParentVersionBehavior.ABORT.getJcrValue(), true, true, true, NO_DEFAULT_VALUES, PropertyType.DATE, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.PREDECESSORS, + new JcrPropertyDefinition(context, null, JcrLexicon.PREDECESSORS, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, true), - new JcrPropertyDefinition(session, null, JcrLexicon.SUCCESSORS, + new JcrPropertyDefinition(context, null, JcrLexicon.SUCCESSORS, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, true),}), NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType versionLabels = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.VERSION_LABELS, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, ALL_NODES, OnParentVersionBehavior.ABORT.getJcrValue(), @@ -498,25 +515,26 @@ NOT_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType versionHistory = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.VERSION_HISTORY, Arrays.asList(new NodeType[] {base, referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] { - new JcrNodeDefinition(session, null, JcrLexicon.ROOT_VERSION, + new JcrNodeDefinition(context, null, JcrLexicon.ROOT_VERSION, OnParentVersionBehavior.ABORT.getJcrValue(), true, true, true, false, JcrNtLexicon.VERSION, new NodeType[] {version}), - new JcrNodeDefinition(session, null, JcrLexicon.VERSION_LABELS, + new JcrNodeDefinition(context, null, JcrLexicon.VERSION_LABELS, OnParentVersionBehavior.ABORT.getJcrValue(), true, true, true, false, JcrNtLexicon.VERSION_LABELS, new NodeType[] {versionLabels}), - new JcrNodeDefinition(session, null, ALL_NODES, + new JcrNodeDefinition(context, null, ALL_NODES, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, false, JcrNtLexicon.VERSION, new NodeType[] {version}),}), Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, JcrLexicon.VERSIONABLE_UUID, OnParentVersionBehavior.ABORT.getJcrValue(), @@ -531,13 +549,14 @@ Name CHILD_VERSION_HISTORY = new BasicName(JcrLexicon.Namespace.URI, "childVersionHistory"); JcrNodeType versionedChild = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrNtLexicon.VERSIONED_CHILD, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition( - session, + context, null, CHILD_VERSION_HISTORY, OnParentVersionBehavior.ABORT.getJcrValue(), @@ -556,42 +575,43 @@ mixinNodeTypes = new ArrayList(); - JcrNodeType lockable = new JcrNodeType(session, JcrMixLexicon.LOCKABLE, NO_SUPERTYPES, NO_PRIMARY_ITEM_NAME, - NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.LOCK_IS_DEEP, + JcrNodeType lockable = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrMixLexicon.LOCKABLE, NO_SUPERTYPES, + NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { + new JcrPropertyDefinition(context, null, JcrLexicon.LOCK_IS_DEEP, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.BOOLEAN, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.LOCK_OWNER, + new JcrPropertyDefinition(context, null, JcrLexicon.LOCK_OWNER, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.STRING, NO_CONSTRAINTS, false)}), IS_A_MIXIN, UNORDERABLE_CHILD_NODES); JcrNodeType versionable = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, JcrMixLexicon.VERSIONABLE, Arrays.asList(new NodeType[] {referenceable}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, JcrLexicon.BASE_VERSION, + new JcrPropertyDefinition(context, null, JcrLexicon.BASE_VERSION, OnParentVersionBehavior.IGNORE.getJcrValue(), false, true, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.IS_CHECKED_OUT, + new JcrPropertyDefinition(context, null, JcrLexicon.IS_CHECKED_OUT, OnParentVersionBehavior.IGNORE.getJcrValue(), true, true, true, new Value[] {trueValue}, PropertyType.BOOLEAN, NO_CONSTRAINTS, false), - new JcrPropertyDefinition(session, null, JcrLexicon.MERGE_FAILED, + new JcrPropertyDefinition(context, null, JcrLexicon.MERGE_FAILED, OnParentVersionBehavior.ABORT.getJcrValue(), false, false, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, true), - new JcrPropertyDefinition(session, null, JcrLexicon.PREDECESSORS, + new JcrPropertyDefinition(context, null, JcrLexicon.PREDECESSORS, OnParentVersionBehavior.COPY.getJcrValue(), false, true, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, true), - new JcrPropertyDefinition(session, null, JcrLexicon.VERSION_HISTORY, + new JcrPropertyDefinition(context, null, JcrLexicon.VERSION_HISTORY, OnParentVersionBehavior.COPY.getJcrValue(), false, true, true, NO_DEFAULT_VALUES, PropertyType.REFERENCE, NO_CONSTRAINTS, false),}), Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java (working copy) @@ -26,6 +26,7 @@ import javax.jcr.nodetype.ItemDefinition; import javax.jcr.nodetype.NodeType; import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; /** @@ -35,7 +36,7 @@ @Immutable class JcrItemDefinition implements ItemDefinition { - protected final JcrSession session; + protected final ExecutionContext context; protected final JcrNodeType declaringNodeType; protected final Name name; @@ -44,7 +45,7 @@ private final boolean mandatory; private final boolean protectedItem; - JcrItemDefinition( JcrSession session, + JcrItemDefinition( ExecutionContext context, JcrNodeType declaringNodeType, Name name, int onParentVersion, @@ -52,12 +53,9 @@ boolean mandatory, boolean protectedItem ) { super(); - this.session = session; + this.context = context; this.declaringNodeType = declaringNodeType; - this.name = name != null ? name : session.getExecutionContext() - .getValueFactories() - .getNameFactory() - .create(JcrNodeType.RESIDUAL_ITEM_NAME); + this.name = name != null ? name : context.getValueFactories().getNameFactory().create(JcrNodeType.RESIDUAL_ITEM_NAME) ; this.onParentVersion = onParentVersion; this.autoCreated = autoCreated; this.mandatory = mandatory; @@ -87,7 +85,7 @@ return JcrNodeType.RESIDUAL_ITEM_NAME; } - return name.getString(session.getExecutionContext().getNamespaceRegistry()); + return name.getString(context.getNamespaceRegistry()); } /** Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java (working copy) @@ -23,10 +23,10 @@ */ package org.jboss.dna.jcr; -import javax.jcr.RepositoryException; import javax.jcr.nodetype.NodeDefinition; import javax.jcr.nodetype.NodeType; import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; /** @@ -50,7 +50,10 @@ /** A durable identifier for this node definition. */ private NodeDefinitionId id; - JcrNodeDefinition( JcrSession session, + /** Link to the repository node type manager */ + private final RepositoryNodeTypeManager nodeTypeManager; + + JcrNodeDefinition( ExecutionContext context, JcrNodeType declaringNodeType, Name name, int onParentVersion, @@ -60,12 +63,31 @@ boolean allowsSameNameSiblings, Name defaultPrimaryTypeName, NodeType[] requiredPrimaryTypes ) { - super(session, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem); + super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem); + this.nodeTypeManager = null; this.allowsSameNameSiblings = allowsSameNameSiblings; this.defaultPrimaryTypeName = defaultPrimaryTypeName; this.requiredPrimaryTypes = requiredPrimaryTypes; } + JcrNodeDefinition( ExecutionContext context, + RepositoryNodeTypeManager nodeTypeManager, + JcrNodeType declaringNodeType, + Name name, + int onParentVersion, + boolean autoCreated, + boolean mandatory, + boolean protectedItem, + boolean allowsSameNameSiblings, + Name defaultPrimaryTypeName, + NodeType[] requiredPrimaryTypes ) { + super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem); + this.nodeTypeManager = nodeTypeManager; + this.allowsSameNameSiblings = allowsSameNameSiblings; + this.defaultPrimaryTypeName = defaultPrimaryTypeName; + this.requiredPrimaryTypes = requiredPrimaryTypes; + } + /** * Get the durable identifier for this node definition. * @@ -98,21 +120,7 @@ return null; } - /* - * Translate the name to a prefixed type based on the current transient (session) and persistent (workspace) - * prefix to URI mappings. - */ - String mappedTypeName = defaultPrimaryTypeName.getString(session.getExecutionContext().getNamespaceRegistry()); - - try { - return session.getWorkspace().getNodeTypeManager().getNodeType(mappedTypeName); - } catch (RepositoryException re) { - /* - * The spec doesn't allow us to throw a checked exception at this point, but a corrupted namespace mapping - * would be pretty severe. - */ - throw new IllegalStateException(JcrI18n.typeNotFound.text(mappedTypeName)); - } + return nodeTypeManager.getNodeType(defaultPrimaryTypeName); } /** @@ -133,7 +141,15 @@ * declaringNodeType. */ JcrNodeDefinition with( JcrNodeType declaringNodeType ) { - return new JcrNodeDefinition(session, declaringNodeType, name, getOnParentVersion(), isAutoCreated(), isMandatory(), - isProtected(), allowsSameNameSiblings(), defaultPrimaryTypeName, requiredPrimaryTypes); + return new JcrNodeDefinition(this.context, declaringNodeType.nodeTypeManager(), declaringNodeType, name, + getOnParentVersion(), isAutoCreated(), isMandatory(), isProtected(), + allowsSameNameSiblings(), defaultPrimaryTypeName, requiredPrimaryTypes); } + + JcrNodeDefinition with( ExecutionContext context ) { + return new JcrNodeDefinition(context, this.nodeTypeManager, this.declaringNodeType, name, getOnParentVersion(), + isAutoCreated(), isMandatory(), isProtected(), allowsSameNameSiblings(), + defaultPrimaryTypeName, requiredPrimaryTypes); + } + } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java (working copy) @@ -30,13 +30,13 @@ import java.util.Set; import java.util.Stack; import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; import javax.jcr.Value; import javax.jcr.nodetype.NodeDefinition; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.PropertyDefinition; import net.jcip.annotations.Immutable; import org.jboss.dna.common.util.CheckArg; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; /** @@ -65,12 +65,16 @@ private boolean orderableChildNodes; /** - * A reference to the session in which this node type exists, used to remap the internal names to their appropriate prefixed - * version (e.g., {http://www.jcp.org/jcr/nt/1.0}base to "nt:base".). + * A reference to the execution context in which this node type exists, used to remap the internal names to their appropriate + * prefixed version (e.g., {http://www.jcp.org/jcr/nt/1.0}base to "nt:base".). */ - private JcrSession session; + private ExecutionContext context; - JcrNodeType( JcrSession session, + /** Link to the repository node type manager for the repository to which this node type belongs. */ + private RepositoryNodeTypeManager nodeTypeManager; + + JcrNodeType( ExecutionContext context, + RepositoryNodeTypeManager nodeTypeManager, Name name, List declaredSupertypes, Name primaryItemName, @@ -78,7 +82,8 @@ Collection propertyDefinitions, boolean mixin, boolean orderableChildNodes ) { - this.session = session; + this.context = context; + this.nodeTypeManager = nodeTypeManager; this.name = name; this.primaryItemName = primaryItemName; this.declaredSupertypes = declaredSupertypes != null ? declaredSupertypes : Collections.emptyList(); @@ -224,35 +229,6 @@ * @return the {@link NodeDefinition} that best matches the child, or null if a child with the supplied name and primary type * are not allowed given this node type */ - @Deprecated - JcrNodeDefinition findBestNodeDefinitionForChild( String childName, - String primaryNodeTypeName ) { - // First, try to find a child node definition with the given name - JcrNodeDefinition childNode = getChildNodeDefinition(childName); - - // If there are no named definitions in the type hierarchy, try to find a residual node definition - if (childNode == null) { - childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME); - } - - // Check if the node can be added with the named child node definition - if (childNode != null && primaryNodeTypeName != null) { - NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName); - if (primaryNodeType == null) return null; - if (!checkTypeAgainstDefinition(primaryNodeType, childNode)) return null; - } - return childNode; - } - - /** - * Determine the best (most specific) {@link NodeDefinition} for a child with the supplied name and primary type. If the - * primary type is not supplied, then only the name is considered when finding a best match. - * - * @param childName the name of the child - * @param primaryNodeTypeName the name of the primary node type for the child - * @return the {@link NodeDefinition} that best matches the child, or null if a child with the supplied name and primary type - * are not allowed given this node type - */ JcrNodeDefinition findBestNodeDefinitionForChild( Name childName, Name primaryNodeTypeName ) { // First, try to find a child node definition with the given name @@ -314,17 +290,8 @@ return false; } - protected final NodeType getPrimaryNodeType( String primaryNodeTypeName ) { - try { - return session.getWorkspace().getNodeTypeManager().getNodeType(primaryNodeTypeName); - } catch (RepositoryException re) { - // If the node type doesn't exist, you can't add a child node with that type - return null; - } - } - protected final NodeType getPrimaryNodeType( Name primaryNodeTypeName ) { - return session.nodeTypeManager().getNodeType(primaryNodeTypeName); + return nodeTypeManager.getNodeType(primaryNodeTypeName); } /** @@ -338,7 +305,8 @@ CheckArg.isNotNull(childNodeName, "childNodeName"); CheckArg.isNotNull(primaryNodeTypeName, "primaryNodeTypeName"); - NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName); + Name nodeTypeName = context.getValueFactories().getNameFactory().create(primaryNodeTypeName); + NodeType primaryNodeType = getPrimaryNodeType(nodeTypeName); if (primaryNodeType == null) { // The node type doesn't exist, so you can't add a child node with that type return false; @@ -585,7 +553,7 @@ */ public String getName() { // Translate the name to the correct prefix. Need to check the session to support url-remapping. - return name.getString(session.getExecutionContext().getNamespaceRegistry()); + return name.getString(context.getNamespaceRegistry()); } /** @@ -609,7 +577,7 @@ } // Translate the name to the correct prefix. Need to check the session to support url-remapping. - return primaryItemName.getString(session.getExecutionContext().getNamespaceRegistry()); + return primaryItemName.getString(context.getNamespaceRegistry()); } /** @@ -695,4 +663,33 @@ public String toString() { return getName(); } + + /** + * Returns a {@link JcrNodeType} that is equivalent to this {@link JcrNodeType}, except with a different repository node type + * manager. This method should only be called during the initialization of the repository node type manager, unless some kind + * of cross-repository type shipping is implemented. + * + * @param nodeTypeManager the new repository node type manager + * @return a new {@link JcrNodeType} that has the same state as this node type, but with the given node type manager. + */ + final JcrNodeType with( RepositoryNodeTypeManager nodeTypeManager ) { + return new JcrNodeType(this.context, nodeTypeManager, this.name, this.declaredSupertypes, this.primaryItemName, + this.childNodeDefinitions, this.propertyDefinitions, this.mixin, this.orderableChildNodes); + } + + /** + * Returns a {@link JcrNodeType} that is equivalent to this {@link JcrNodeType}, except with a different execution context. + * + * @param context the new execution context + * @return a new {@link JcrNodeType} that has the same state as this node type, but with the given node type manager. + * @see JcrNodeTypeManager + */ + final JcrNodeType with( ExecutionContext context ) { + return new JcrNodeType(context, this.nodeTypeManager, this.name, this.declaredSupertypes, this.primaryItemName, + this.childNodeDefinitions, this.propertyDefinitions, this.mixin, this.orderableChildNodes); + } + + final RepositoryNodeTypeManager nodeTypeManager() { + return nodeTypeManager; + } } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java (working copy) @@ -25,44 +25,35 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.jcr.RepositoryException; import javax.jcr.nodetype.NoSuchNodeTypeException; import javax.jcr.nodetype.NodeDefinition; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.NodeTypeIterator; import javax.jcr.nodetype.NodeTypeManager; -import net.jcip.annotations.NotThreadSafe; +import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; /** - * Local implementation of @{link NodeTypeManager}. Initialized with {@link NodeType} source data when it is created (in the - * {@link JcrWorkspace} constructor. + * Local implementation of @{link NodeTypeManager}. This class handles translation between {@link Name}s and {@link String}s based + * on the namespace registry from the session's execution context in order to support transient namespace remappings. All + * {@link NodeType}s returned by this implementation are wrapped with the execution context of the session to allow proper ongoing + * handling of names. This implies that reference equality is not a safe test for node type equivalence. + * + * @see RepositoryNodeTypeManager */ -@NotThreadSafe +@Immutable class JcrNodeTypeManager implements NodeTypeManager { - private final Map primaryNodeTypes; - private final Map mixinNodeTypes; - private final JcrSession session; + private final ExecutionContext context; + private final RepositoryNodeTypeManager repositoryTypeManager; - JcrNodeTypeManager( JcrSession session, - JcrNodeTypeSource source ) { - this.session = session; - Collection primary = source.getPrimaryNodeTypes(); - Collection mixins = source.getMixinNodeTypes(); - - primaryNodeTypes = new HashMap(primary.size()); - for (JcrNodeType nodeType : primary) { - primaryNodeTypes.put(nodeType.getInternalName(), nodeType); - } - - mixinNodeTypes = new HashMap(mixins.size()); - for (JcrNodeType nodeType : mixins) { - mixinNodeTypes.put(nodeType.getInternalName(), nodeType); - } + JcrNodeTypeManager( ExecutionContext context, + RepositoryNodeTypeManager repositoryTypeManager ) { + this.context = context; + this.repositoryTypeManager = repositoryTypeManager; } /** @@ -72,6 +63,9 @@ */ public NodeTypeIterator getAllNodeTypes() { + Collection mixinNodeTypes = repositoryTypeManager.getMixinNodeTypes(); + Collection primaryNodeTypes = repositoryTypeManager.getPrimaryNodeTypes(); + // TODO: Can revisit this approach later if it becomes a performance issue /* * Note also that this creates a subtle difference in behavior for concurrent modification @@ -82,8 +76,16 @@ */ List allTypes = new ArrayList(primaryNodeTypes.size() + mixinNodeTypes.size()); - allTypes.addAll(primaryNodeTypes.values()); - allTypes.addAll(mixinNodeTypes.values()); + + // Need to return a version of the node type with the current context + for (JcrNodeType type : primaryNodeTypes) { + allTypes.add(type.with(context)); + } + + for (JcrNodeType type : mixinNodeTypes) { + allTypes.add(type.with(context)); + } + return new JcrNodeTypeIterator(allTypes); } @@ -93,16 +95,15 @@ * @see javax.jcr.nodetype.NodeTypeManager#getMixinNodeTypes() */ public NodeTypeIterator getMixinNodeTypes() { - return new JcrNodeTypeIterator(mixinNodeTypes.values()); - } + Collection rawTypes = repositoryTypeManager.getMixinNodeTypes(); + List types = new ArrayList(rawTypes.size()); - JcrNodeType getNodeType( Name nodeTypeName ) { + // Need to return a version of the node type with the current context + for (JcrNodeType type : rawTypes) { + types.add(type.with(context)); + } - JcrNodeType nodeType = primaryNodeTypes.get(nodeTypeName); - if (nodeType == null) { - nodeType = mixinNodeTypes.get(nodeTypeName); - } - return nodeType; + return new JcrNodeTypeIterator(types); } /** @@ -111,19 +112,47 @@ * @see javax.jcr.nodetype.NodeTypeManager#getNodeType(java.lang.String) */ public NodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException, RepositoryException { - Name ntName = session.getExecutionContext().getValueFactories().getNameFactory().create(nodeTypeName); - NodeType type = getNodeType(ntName); - if (type != null) return type; + Name ntName = context.getValueFactories().getNameFactory().create(nodeTypeName); + JcrNodeType type = repositoryTypeManager.getNodeType(ntName); + if (type != null) { + type = type.with(context); + return type; + } throw new NoSuchNodeTypeException(JcrI18n.typeNotFound.text(nodeTypeName)); } /** + * Returns the node type with the given name (if one exists) + * + * @param nodeTypeName the name of the node type to be returned + * @return the node type with the given name (if one exists) + * @see RepositoryNodeTypeManager#getNodeType(Name) + */ + JcrNodeType getNodeType( Name nodeTypeName ) { + JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName); + + if (nodeType != null) { + nodeType = nodeType.with(context); + } + + return nodeType; + } + + /** * {@inheritDoc} * * @see javax.jcr.nodetype.NodeTypeManager#getPrimaryNodeTypes() */ public NodeTypeIterator getPrimaryNodeTypes() { - return new JcrNodeTypeIterator(primaryNodeTypes.values()); + Collection rawTypes = repositoryTypeManager.getPrimaryNodeTypes(); + List types = new ArrayList(rawTypes.size()); + + // Need to return a version of the node type with the current context + for (JcrNodeType type : rawTypes) { + types.add(type.with(context)); + } + + return new JcrNodeTypeIterator(types); } /** @@ -134,7 +163,7 @@ * @throws NoSuchNodeTypeException */ JcrNodeDefinition getRootNodeDefinition() throws NoSuchNodeTypeException, RepositoryException { - for (NodeDefinition definition : getNodeType(DnaLexicon.ROOT).getChildNodeDefinitions()) { + for (NodeDefinition definition : repositoryTypeManager.getNodeType(DnaLexicon.ROOT).getChildNodeDefinitions()) { if (definition.getName().equals(JcrNodeType.RESIDUAL_ITEM_NAME)) return (JcrNodeDefinition)definition; } assert false; // should not get here @@ -150,7 +179,7 @@ JcrNodeDefinition getNodeDefinition( NodeDefinitionId definitionId ) { if (definitionId == null) return null; Name nodeTypeName = definitionId.getNodeTypeName(); - JcrNodeType nodeType = getNodeType(nodeTypeName); + JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName); return nodeType.getChildNodeDefinition(definitionId.getChildDefinitionName()); } @@ -165,7 +194,7 @@ boolean prefersMultiValued ) { if (definitionId == null) return null; Name nodeTypeName = definitionId.getNodeTypeName(); - JcrNodeType nodeType = getNodeType(nodeTypeName); + JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName); return nodeType.getPropertyDefinition(definitionId.getPropertyDefinitionName(), prefersMultiValued); } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java (working copy) @@ -23,6 +23,7 @@ */ package org.jboss.dna.jcr; +import java.util.UUID; import java.util.regex.Pattern; import javax.jcr.Node; import javax.jcr.PropertyType; @@ -41,6 +42,7 @@ import org.jboss.dna.graph.property.ValueFactory; import org.jboss.dna.graph.property.ValueFormatException; import org.jboss.dna.graph.property.basic.JodaDateTime; + /** * DNA implementation of the {@link PropertyDefinition} interface. This implementation is immutable and has all fields initialized * through its constructor. @@ -55,7 +57,7 @@ private PropertyDefinitionId id; private ConstraintChecker checker = null; - JcrPropertyDefinition( JcrSession session, + JcrPropertyDefinition( ExecutionContext context, JcrNodeType declaringNodeType, Name name, int onParentVersion, @@ -66,7 +68,7 @@ int requiredType, String[] valueConstraints, boolean multiple ) { - super(session, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem); + super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem); this.defaultValues = defaultValues; this.requiredType = requiredType; this.valueConstraints = valueConstraints; @@ -130,7 +132,7 @@ * declaringNodeType. */ JcrPropertyDefinition with( JcrNodeType declaringNodeType ) { - return new JcrPropertyDefinition(this.session, declaringNodeType, this.name, this.getOnParentVersion(), + return new JcrPropertyDefinition(this.context, declaringNodeType, this.name, this.getOnParentVersion(), this.isAutoCreated(), this.isMandatory(), this.isProtected(), this.getDefaultValues(), this.getRequiredType(), this.getValueConstraints(), this.isMultiple()); } @@ -152,7 +154,7 @@ ConstraintChecker checker = this.checker; if (checker == null || checker.getType() != type) { - checker = createChecker(session, type, valueConstraints); + checker = createChecker(context, type, valueConstraints); this.checker = checker; } @@ -167,21 +169,18 @@ /** * Returns a {@link ConstraintChecker} that will interpret the constraints described by valueConstraints using * the semantics defined in section 6.7.16 of the JCR 1.0 specification for the type indicated by type (where - * type is a value from {@link PropertyType}) for the given session. The session is required to - * handle the UUID lookups for reference constraints and provides the {@link ExecutionContext} that is used to provide - * namespace mappings and value factories for the other constraint checkers. + * type is a value from {@link PropertyType}) for the given context. The {@link ExecutionContext} is + * used to provide namespace mappings and value factories for the other constraint checkers. * - * @param session the current session + * @param context the execution context * @param type the type of constraint checker that should be created (based on values from {@link PropertyType}). * Type-specific semantics are defined in section 6.7.16 of the JCR 1.0 specification. * @param valueConstraints the constraints for the node as provided by {@link PropertyDefinition#getValueConstraints()}. * @return a constraint checker that matches the given parameters */ - private ConstraintChecker createChecker( JcrSession session, - int type, - String[] valueConstraints ) { - ExecutionContext context = session.getExecutionContext(); - + private ConstraintChecker createChecker( ExecutionContext context, + int type, + String[] valueConstraints ) { switch (type) { case PropertyType.BINARY: return new BinaryConstraintChecker(valueConstraints, context); @@ -196,7 +195,7 @@ case PropertyType.PATH: return new PathConstraintChecker(valueConstraints, context); case PropertyType.REFERENCE: - return new ReferenceConstraintChecker(valueConstraints, session); + return new ReferenceConstraintChecker(valueConstraints, context); case PropertyType.STRING: return new StringConstraintChecker(valueConstraints, context); default: @@ -333,7 +332,8 @@ @Override public boolean matches( Value value ) { Binary binary = valueFactories.getBinaryFactory().create(((JcrValue)value).value()); - return super.matches(new JcrValue(valueFactories, PropertyType.LONG, binary.getSize())); + Value sizeValue = ((JcrValue)value).sessionCache().session().getValueFactory().createValue(binary.getSize()); + return super.matches(sizeValue); } } @@ -408,15 +408,15 @@ @Immutable private static class ReferenceConstraintChecker implements ConstraintChecker { - private final JcrSession session; + // private final ExecutionContext context; private final Name[] constraints; protected ReferenceConstraintChecker( String[] valueConstraints, - JcrSession session ) { - this.session = session; + ExecutionContext context ) { + // this.context = context; - NameFactory factory = session.getExecutionContext().getValueFactories().getNameFactory(); + NameFactory factory = context.getValueFactories().getNameFactory(); constraints = new Name[valueConstraints.length]; @@ -430,18 +430,21 @@ } public boolean matches( Value value ) { - assert value != null; + assert value instanceof JcrValue; + JcrValue jcrValue = (JcrValue)value; + SessionCache cache = jcrValue.sessionCache(); + Node node = null; try { - node = session.getNodeByUUID(((JcrValue)value).value().toString()); + node = cache.findJcrNode((UUID)jcrValue.value()); } catch (RepositoryException re) { return false; } for (int i = 0; i < constraints.length; i++) { try { - if (node.isNodeType(constraints[i].getString(session.getExecutionContext().getNamespaceRegistry()))) { + if (node.isNodeType(constraints[i].getString(cache.session().namespaces()))) { return true; } } catch (RepositoryException re) { @@ -474,9 +477,11 @@ } public boolean matches( Value value ) { - assert value != null; + assert value instanceof JcrValue; - Name name = valueFactory.create(((JcrValue)value).value()); + JcrValue jcrValue = (JcrValue)value; + // Need to use the session execution context to handle the remaps + Name name = jcrValue.sessionCache().session().getExecutionContext().getValueFactories().getNameFactory().create(jcrValue.value()); for (int i = 0; i < constraints.length; i++) { if (constraints[i].equals(name)) { @@ -561,5 +566,4 @@ return false; } } - } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java (working copy) @@ -75,6 +75,7 @@ private final Map descriptors; private final ExecutionContext executionContext; private final RepositoryConnectionFactory connectionFactory; + private final RepositoryNodeTypeManager repositoryTypeManager; /** * Creates a JCR repository that uses the supplied {@link RepositoryConnectionFactory repository connection factory} to @@ -145,9 +146,22 @@ modifiableDescriptors.put(Repository.SPEC_NAME_DESC, JcrI18n.SPEC_NAME_DESC.text()); modifiableDescriptors.put(Repository.SPEC_VERSION_DESC, "1.0"); this.descriptors = Collections.unmodifiableMap(modifiableDescriptors); + + JcrNodeTypeSource source = null; + source = new JcrBuiltinNodeTypeSource(this.executionContext); + source = new DnaBuiltinNodeTypeSource(this.executionContext, source); + this.repositoryTypeManager = new RepositoryNodeTypeManager(this.executionContext, source); } /** + * Returns the repository-level node type manager + * @return the repository-level node type manager + */ + RepositoryNodeTypeManager getRepositoryTypeManager() { + return repositoryTypeManager; + } + + /** * Get the name of the repository source that this repository is using. * * @return the name of the RepositorySource Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java (working copy) @@ -146,6 +146,11 @@ assert this.graph != null; } + // Added to facilitate mock testing of items without necessarily requiring an entire repository structure to be built + final SessionCache cache() { + return this.cache; + } + ExecutionContext getExecutionContext() { return this.executionContext; } @@ -439,39 +444,41 @@ */ public ValueFactory getValueFactory() { final ValueFactories valueFactories = executionContext.getValueFactories(); + final SessionCache sessionCache = this.cache; + return new ValueFactory() { public Value createValue( String value, int propertyType ) { - return new JcrValue(valueFactories, propertyType, value); + return new JcrValue(valueFactories, sessionCache, propertyType, value); } public Value createValue( Node value ) throws RepositoryException { - return new JcrValue(valueFactories, PropertyType.REFERENCE, UUID.fromString(value.getUUID())); + return new JcrValue(valueFactories, sessionCache, PropertyType.REFERENCE, UUID.fromString(value.getUUID())); } public Value createValue( InputStream value ) { - return new JcrValue(valueFactories, PropertyType.BINARY, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.BINARY, value); } public Value createValue( Calendar value ) { - return new JcrValue(valueFactories, PropertyType.DATE, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.DATE, value); } public Value createValue( boolean value ) { - return new JcrValue(valueFactories, PropertyType.BOOLEAN, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.BOOLEAN, value); } public Value createValue( double value ) { - return new JcrValue(valueFactories, PropertyType.DOUBLE, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.DOUBLE, value); } public Value createValue( long value ) { - return new JcrValue(valueFactories, PropertyType.LONG, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.LONG, value); } public Value createValue( String value ) { - return new JcrValue(valueFactories, PropertyType.STRING, value); + return new JcrValue(valueFactories, sessionCache, PropertyType.STRING, value); } }; } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java (working copy) @@ -43,19 +43,27 @@ @NotThreadSafe final class JcrValue implements Value { + private final SessionCache sessionCache; private final ValueFactories valueFactories; private final int type; private final Object value; JcrValue( ValueFactories valueFactories, + SessionCache sessionCache, int type, Object value ) { assert valueFactories != null; assert type == PropertyType.BINARY || type == PropertyType.BOOLEAN || type == PropertyType.DATE || type == PropertyType.DOUBLE || type == PropertyType.LONG || type == PropertyType.NAME || type == PropertyType.PATH || type == PropertyType.REFERENCE || type == PropertyType.STRING; + + // Leaving this assertion out for now so that values can be created in node type sources, which are created outside + // the context of any particular session. + // assert sessionCache != null; assert value != null; + this.valueFactories = valueFactories; + this.sessionCache = sessionCache; this.type = type; this.value = value; } @@ -81,6 +89,14 @@ } /** + * Returns the session cache for the session that created this value. + * @return the session cache for the session that created this value. + */ + final SessionCache sessionCache() { + return sessionCache; + } + + /** * {@inheritDoc} * * @see javax.jcr.Value#getBoolean() @@ -195,6 +211,11 @@ return type; } + private JcrValue withTypeAndValue( int type, + Object value ) { + return new JcrValue(this.valueFactories, this.sessionCache, type, value); + } + /** * Returns a copy of the current {@link JcrValue} cast to the JCR type specified by the type argument. If the * value cannot be converted base don the JCR type conversion rules, a {@link ValueFormatException} will be thrown. @@ -207,14 +228,14 @@ JcrValue asType( int type ) throws ValueFormatException { if (type == this.type) { - return new JcrValue(this.valueFactories, this.type, this.value); + return this.withTypeAndValue(this.type, this.value); } switch (type) { case PropertyType.BOOLEAN: try { if (this.type == PropertyType.STRING || this.type == PropertyType.BINARY) { - return new JcrValue(this.valueFactories, type, valueFactories.getBooleanFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getBooleanFactory().create(value)); } } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { throw createValueFormatException(vfe); @@ -225,7 +246,7 @@ try { if (this.type == PropertyType.DOUBLE || this.type == PropertyType.LONG || this.type == PropertyType.STRING || this.type == PropertyType.BINARY) { - return new JcrValue(this.valueFactories, type, valueFactories.getDateFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getDateFactory().create(value)); } } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { throw createValueFormatException(vfe); @@ -236,12 +257,12 @@ case PropertyType.NAME: try { if (this.type == PropertyType.STRING) { - return new JcrValue(this.valueFactories, type, this.valueFactories.getNameFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getNameFactory().create(value)); } String valueAsString = this.valueFactories.getStringFactory().create(value); if (this.type == PropertyType.BINARY) { - return new JcrValue(this.valueFactories, type, this.valueFactories.getNameFactory().create(valueAsString)); + return this.withTypeAndValue(type, valueFactories.getNameFactory().create(valueAsString)); } @@ -250,9 +271,7 @@ Segment[] segments = path.getSegmentsArray(); if (!path.isAbsolute() && segments.length == 1 && !segments[0].hasIndex()) { - return new JcrValue(this.valueFactories, type, - this.valueFactories.getNameFactory().create(valueAsString)); - + return this.withTypeAndValue(type, valueFactories.getNameFactory().create(valueAsString)); } } } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { @@ -264,7 +283,8 @@ case PropertyType.PATH: try { if (this.type == PropertyType.STRING) { - return new JcrValue(this.valueFactories, type, this.valueFactories.getPathFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getPathFactory().create(value)); + } } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { throw createValueFormatException(vfe); @@ -282,18 +302,21 @@ // Anything can be converted to these types case PropertyType.BINARY: try { - return new JcrValue(this.valueFactories, type, valueFactories.getBinaryFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getBinaryFactory().create(value)); + } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { throw createValueFormatException(vfe); } case PropertyType.STRING: try { - return new JcrValue(this.valueFactories, type, valueFactories.getStringFactory().create(value)); + return this.withTypeAndValue(type, valueFactories.getStringFactory().create(value)); + } catch (org.jboss.dna.graph.property.ValueFormatException vfe) { throw createValueFormatException(vfe); } case PropertyType.UNDEFINED: - return new JcrValue(this.valueFactories, this.type, this.value); + return this.withTypeAndValue(this.type, this.value); + default: assert false : "Unexpected JCR property type " + type; // This should still throw an exception even if assertions are turned off Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java (working copy) @@ -148,10 +148,7 @@ this.session = new JcrSession(this.repository, this, this.context, sessionAttributes); // This must be initialized after the session - JcrNodeTypeSource source = null; - source = new JcrBuiltinNodeTypeSource(this.session); - source = new DnaBuiltinNodeTypeSource(this.session, source); - this.nodeTypeManager = new JcrNodeTypeManager(this.session, source); + this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repository.getRepositoryTypeManager()); } final String getSourceName() { Index: dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java (revision 0) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java (revision 0) @@ -0,0 +1,81 @@ +/* + * JBoss DNA (http://www.jboss.org/dna) + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. Some portions may be licensed + * to Red Hat, Inc. under one or more contributor license agreements. + * See the AUTHORS.txt file in the distribution for a full listing of + * individual contributors. + * + * Unless otherwise indicated, all code in JBoss DNA is licensed + * to you under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * JBoss DNA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.dna.jcr; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import net.jcip.annotations.Immutable; +import org.jboss.dna.graph.ExecutionContext; +import org.jboss.dna.graph.property.Name; + +/** + * The {@link RepositoryNodeTypeManager} is the maintainer of node type information for the entire repository at run-time. The + * repository manager maintains a list of all node types and the ability to retrieve node types by {@link Name}.

The JCR 1.0 + * and 2.0 specifications both require that node type information be shared across all sessions within a repository and that the + * {@link javax.jcr.nodetype.NodeTypeManager} perform operations based on the string versions of {@link Name}s based on the permanent + * (workspace-scoped) and transient (session-scoped) namespace mappings. DNA achieves this by maintaining a single master + * repository of all node type information (the {@link RepositoryNodeTypeManager}) and per-session wrappers ( + * {@link JcrNodeTypeManager}) for this master repository that perform {@link String} to {@link Name} translation based on the + * {@link javax.jcr.Session}'s transient mappings and then delegating node type lookups to the repository manager. + */ +@Immutable +class RepositoryNodeTypeManager { + + private final Map primaryNodeTypes; + private final Map mixinNodeTypes; + + RepositoryNodeTypeManager( ExecutionContext context, + JcrNodeTypeSource source ) { + Collection primary = source.getPrimaryNodeTypes(); + Collection mixins = source.getMixinNodeTypes(); + + primaryNodeTypes = new HashMap(primary.size()); + for (JcrNodeType nodeType : primary) { + primaryNodeTypes.put(nodeType.getInternalName(), nodeType.with(this)); + } + + mixinNodeTypes = new HashMap(mixins.size()); + for (JcrNodeType nodeType : mixins) { + mixinNodeTypes.put(nodeType.getInternalName(), nodeType.with(this)); + } + } + + public Collection getMixinNodeTypes() { + return mixinNodeTypes.values(); + } + + public Collection getPrimaryNodeTypes() { + return primaryNodeTypes.values(); + } + + JcrNodeType getNodeType( Name nodeTypeName ) { + + JcrNodeType nodeType = primaryNodeTypes.get(nodeTypeName); + if (nodeType == null) { + nodeType = mixinNodeTypes.get(nodeTypeName); + } + return nodeType; + } +} Index: dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java (revision 783) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java (working copy) @@ -970,7 +970,7 @@ * @param primaryTypeOfChild the name of the child's primary type * @return the node definition for this child, as best as can be determined, or null if the node definition could not be * determined - * @throws RepositoryException if the parent's pimary node type cannot be found in the {@link NodeTypeManager} + * @throws RepositoryException if the parent's primary node type cannot be found in the {@link NodeTypeManager} */ protected JcrNodeDefinition findNodeDefinitionForChild( NodeInfo parentInfo, Name childName, Index: dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java (working copy) @@ -147,7 +147,7 @@ } protected Value stringValueFor( Object value ) { - return new JcrValue(context.getValueFactories(), PropertyType.STRING, value); + return new JcrValue(context.getValueFactories(), cache, PropertyType.STRING, value); } protected void addChild( Name childName, @@ -459,37 +459,7 @@ assertThat((JcrSession)node.getSession(), is(session)); } - @Test - public void shouldProvideUuidIfReferenceable() throws Exception { - // Create the property ... - PropertyId propertyId = new PropertyId(uuid, name("jcr:mixinTypes")); - AbstractJcrProperty property = mock(AbstractJcrProperty.class); - stub(cache.findJcrProperty(propertyId)).toReturn(property); - stub(property.getValues()).toReturn(new Value[] {stringValueFor("acme:someMixin"), stringValueFor("mix:referenceable")}); - // Call the method ... - assertThat(node.getUUID(), is(uuid.toString())); - } - @Test( expected = UnsupportedRepositoryOperationException.class ) - public void shouldNotProvideUuidIfNotReferenceable() throws Exception { - // Create the property ... - PropertyId propertyId = new PropertyId(uuid, name("jcr:mixinTypes")); - AbstractJcrProperty property = mock(AbstractJcrProperty.class); - stub(cache.findJcrProperty(propertyId)).toReturn(property); - stub(property.getValues()).toReturn(new Value[] {stringValueFor("acme:someMixin"), stringValueFor("mix:notReferenceable")}); - // Call the method ... - node.getUUID(); - } - - @Test( expected = UnsupportedRepositoryOperationException.class ) - public void shouldNotProvideUuidIfNoMixinTypes() throws Exception { - PropertyId propertyId = new PropertyId(uuid, name("jcr:mixinTypes")); - stub(cache.findJcrProperty(propertyId)).toReturn(null); - // Call the method ... - node.getUUID(); - } - - @Test( expected = UnsupportedRepositoryOperationException.class ) public void shouldNotAllowGetVersionHistory() throws Exception { node.getVersionHistory(); } Index: dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java (working copy) @@ -30,8 +30,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.UUID; -import javax.jcr.Node; import javax.jcr.PropertyType; import javax.jcr.Value; import javax.jcr.nodetype.NodeType; @@ -52,21 +50,22 @@ import org.mockito.MockitoAnnotations.Mock; /** - * Indirectly tests the JcrConstaintCheckerFactory through {@link JcrPropertyDefinition#satisfiesConstraints(Value)}, - * which provides the wrapper around the factory that the rest of the API is expected to utilize. - * + * Indirectly tests the JcrConstaintCheckerFactory through {@link JcrPropertyDefinition#satisfiesConstraints(Value)}, which + * provides the wrapper around the factory that the rest of the API is expected to utilize. */ public class JcrPropertyDefinitionTest { - private final String[] EXPECTED_BINARY_CONSTRAINTS = new String[] { "[,5)", "[10, 20)", "(30,40]", "[50,]" }; - private final String[] EXPECTED_DATE_CONSTRAINTS = new String[] { "[,+1945-08-01T01:30:00.000Z]", "[+1975-08-01T01:30:00.000Z,)"}; - private final String[] EXPECTED_DOUBLE_CONSTRAINTS = new String[] { "[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]" }; - private final String[] EXPECTED_LONG_CONSTRAINTS = new String[] { "[,5)", "[10, 20)", "(30,40]", "[50,]" }; - private final String[] EXPECTED_NAME_CONSTRAINTS = new String[] { "jcr:system", "dnatest:constrainedType" }; - //private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/" + JcrLexicon.Namespace.URI + ":system/*", "b", "/a/b/c" }; - private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/jcr:system/*", "b", "/a/b/c" }; - private final String[] EXPECTED_REFERENCE_CONSTRAINTS = new String[] { "dna:root" }; - private final String[] EXPECTED_STRING_CONSTRAINTS = new String[] { "foo", "bar*", ".*baz" }; + private final String[] EXPECTED_BINARY_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}; + private final String[] EXPECTED_DATE_CONSTRAINTS = new String[] {"[,+1945-08-01T01:30:00.000Z]", + "[+1975-08-01T01:30:00.000Z,)"}; + private final String[] EXPECTED_DOUBLE_CONSTRAINTS = new String[] {"[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]"}; + private final String[] EXPECTED_LONG_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}; + private final String[] EXPECTED_NAME_CONSTRAINTS = new String[] {"jcr:system", "dnatest:constrainedType"}; + // private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/" + JcrLexicon.Namespace.URI + ":system/*", "b", + // "/a/b/c" }; + private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/jcr:system/*", "b", "/a/b/c"}; + private final String[] EXPECTED_REFERENCE_CONSTRAINTS = new String[] {"dna:root"}; + private final String[] EXPECTED_STRING_CONSTRAINTS = new String[] {"foo", "bar*", ".*baz"}; private String workspaceName; private ExecutionContext context; @@ -75,6 +74,7 @@ private JcrSession session; private Graph graph; private RepositoryConnectionFactory connectionFactory; + private RepositoryNodeTypeManager repoTypeManager; private NodeTypeManager nodeTypeManager; private Map sessionAttributes; @Mock @@ -82,6 +82,8 @@ @Before public void beforeEach() throws Exception { + MockitoAnnotations.initMocks(this); + workspaceName = "workspace1"; final String repositorySourceName = "repository"; @@ -97,7 +99,7 @@ // Set up the initial content ... graph = Graph.create(source, context); - + // Make sure the path to the namespaces exists ... graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces"); graph.create("/a").and().create("/a/b").and().create("/a/b/c"); @@ -118,7 +120,12 @@ }; // Stub out the repository, since we only need a few methods ... - MockitoAnnotations.initMocks(this); + JcrNodeTypeSource source = null; + source = new JcrBuiltinNodeTypeSource(this.context, source); + source = new DnaBuiltinNodeTypeSource(this.context, source); + source = new TestNodeTypeSource(this.context, source); + repoTypeManager = new RepositoryNodeTypeManager(context, source); + stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager); stub(repository.getRepositorySourceName()).toReturn(repositorySourceName); stub(repository.getConnectionFactory()).toReturn(connectionFactory); @@ -132,39 +139,37 @@ // Create the session and log in ... session = (JcrSession)workspace.getSession(); - nodeTypeManager = new JcrNodeTypeManager(this.session, - new TestNodeTypeSource(this.session, - new DnaBuiltinNodeTypeSource(this.session, - new JcrBuiltinNodeTypeSource(this.session)))); - stub(workspace.getNodeTypeManager()).toReturn(nodeTypeManager); - + nodeTypeManager = workspace.getNodeTypeManager(); } @After public void after() throws Exception { - if (session.isLive()) { + if (session != null && session.isLive()) { session.logout(); } } - private JcrPropertyDefinition propertyDefinitionFor(NodeType nodeType, Name propertyName) { + private JcrPropertyDefinition propertyDefinitionFor( NodeType nodeType, + Name propertyName ) { PropertyDefinition propertyDefs[] = nodeType.getPropertyDefinitions(); String property = propertyName.getString(context.getNamespaceRegistry()); - + for (int i = 0; i < propertyDefs.length; i++) { if (propertyDefs[i].getName().equals(property)) { - return (JcrPropertyDefinition) propertyDefs[i]; + return (JcrPropertyDefinition)propertyDefs[i]; } } - throw new IllegalStateException("Could not find property definition name " + property + " for type " - + nodeType.getName() + ". Test setup is invalid."); + throw new IllegalStateException("Could not find property definition name " + property + " for type " + nodeType.getName() + + ". Test setup is invalid."); } - private void checkConstraints(NodeType nodeType, Name propertyName, String[] expectedConstraints) { + private void checkConstraints( NodeType nodeType, + Name propertyName, + String[] expectedConstraints ) { PropertyDefinition propertyDefs[] = nodeType.getPropertyDefinitions(); String property = propertyName.getString(context.getNamespaceRegistry()); String[] constraints = null; - + for (int i = 0; i < propertyDefs.length; i++) { if (propertyDefs[i].getName().equals(property)) { constraints = propertyDefs[i].getValueConstraints(); @@ -176,10 +181,10 @@ throw new IllegalStateException("Unexpected constraints for property: " + property); } } - + private NodeType validateTypeDefinition() throws Exception { NamespaceRegistry nsr = context.getNamespaceRegistry(); - + NodeType constrainedType = nodeTypeManager.getNodeType(TestLexicon.CONSTRAINED_TYPE.getString(nsr)); assertThat(constrainedType, notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY), notNullValue()); @@ -190,7 +195,7 @@ assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING), notNullValue()); - + checkConstraints(constrainedType, TestLexicon.CONSTRAINED_BINARY, EXPECTED_BINARY_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_DATE, EXPECTED_DATE_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_DOUBLE, EXPECTED_DOUBLE_CONSTRAINTS); @@ -199,24 +204,26 @@ checkConstraints(constrainedType, TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_REFERENCE, EXPECTED_REFERENCE_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS); - + return constrainedType; } - - private Value valueFor(Object value, int jcrType) { - return new JcrValue(context.getValueFactories(), jcrType, value); + + private Value valueFor( Object value, + int jcrType ) { + return new JcrValue(context.getValueFactories(), session.cache(), jcrType, value); } - - private String stringOfLength(int length) { + + private String stringOfLength( int length ) { StringBuffer buff = new StringBuffer(length); for (int i = 0; i < length; i++) { buff.append(i % 10); } - + return buff.toString(); } - private boolean satisfiesConstraints(JcrPropertyDefinition property, Value[] values) { + private boolean satisfiesConstraints( JcrPropertyDefinition property, + Value[] values ) { for (int i = 0; i < values.length; i++) { if (!property.satisfiesConstraints(values[i])) { return false; @@ -224,8 +231,8 @@ } return true; } - - @Test( expected = AssertionError.class ) + + @Test( expected = AssertionError.class ) public void shouldNotAllowNullValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); @@ -585,45 +592,41 @@ public void shouldAllowValidReferenceValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); - - UUID uuid = ((AbstractJcrNode) session.getRootNode()).nodeUuid; - assertThat(prop.satisfiesConstraints(valueFor(uuid, PropertyType.REFERENCE)), is(true)); + Value value = session.getValueFactory().createValue(session.getRootNode()); + + assertThat(prop.satisfiesConstraints(value), is(true)); } @Test public void shouldAllowValidReferenceValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); - - UUID uuid = ((AbstractJcrNode) session.getRootNode()).nodeUuid; - assertThat(satisfiesConstraints(prop, new Value[] { }), is(true)); - assertThat(satisfiesConstraints(prop, new Value[] { valueFor(uuid, PropertyType.REFERENCE) }), is(true)); + Value value = session.getValueFactory().createValue(session.getRootNode()); + + assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); + assertThat(satisfiesConstraints(prop, new Value[] {value}), is(true)); } - @Test public void shouldNotAllowInvalidReferenceValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); - Node aNode = session.getRootNode().getNode("a"); - UUID uuid = ((JcrNode) aNode).nodeUuid; + Value value = session.getValueFactory().createValue(session.getRootNode().getNode("a")); - - assertThat(prop.satisfiesConstraints(valueFor(uuid, PropertyType.REFERENCE)), is(false)); + assertThat(prop.satisfiesConstraints(value), is(false)); } @Test public void shouldNotAllowInvalidReferenceValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); - - Node aNode = session.getRootNode().getNode("a"); - UUID uuid = ((JcrNode) aNode).nodeUuid; - - assertThat(satisfiesConstraints(prop, new Value[] { valueFor(uuid, PropertyType.REFERENCE) }), is(false)); + + Value value = session.getValueFactory().createValue(session.getRootNode().getNode("a")); + + assertThat(satisfiesConstraints(prop, new Value[] {value}), is(false)); } } Index: dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java (working copy) @@ -50,7 +50,9 @@ import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; import javax.jcr.ValueFactory; +import javax.jcr.nodetype.NodeType; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import org.jboss.dna.graph.ExecutionContext; @@ -81,6 +83,7 @@ private JcrSession session; private Graph graph; private RepositoryConnectionFactory connectionFactory; + private RepositoryNodeTypeManager repoTypeManager; private Map sessionAttributes; @Mock private JcrRepository repository; @@ -103,6 +106,7 @@ graph.create("/a").and().create("/a/b").and().create("/a/b/c"); graph.set("booleanProperty").on("/a/b").to(true); graph.set("stringProperty").on("/a/b/c").to("value"); + graph.set("jcr:mixinTypes").on("/a").to("mix:lockable"); graph.set("jcr:mixinTypes").on("/a/b").to("mix:referenceable"); graph.set("multiLineProperty").on("/a/b/c").to(MULTI_LINE_VALUE); @@ -122,11 +126,18 @@ } }; + // Set up the repo type manager + JcrNodeTypeSource nodeTypes = null; + nodeTypes = new JcrBuiltinNodeTypeSource(context, nodeTypes); + nodeTypes = new DnaBuiltinNodeTypeSource(context, nodeTypes); + repoTypeManager = new RepositoryNodeTypeManager(context, nodeTypes); + // Stub out the repository, since we only need a few methods ... MockitoAnnotations.initMocks(this); stub(repository.getRepositorySourceName()).toReturn(repositorySourceName); stub(repository.getConnectionFactory()).toReturn(connectionFactory); - + stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager); + // Set up the session attributes ... sessionAttributes = new HashMap(); sessionAttributes.put("attribute1", "value1"); @@ -404,7 +415,10 @@ public void rootNodeShouldHaveProperType() throws Exception { Node rootNode = session.getRootNode(); - assertTrue(rootNode.getPrimaryNodeType().equals(session.nodeTypeManager().getNodeType(DnaLexicon.ROOT))); + NodeType rootNodePrimaryType = rootNode.getPrimaryNodeType(); + NodeType dnaRootType = session.nodeTypeManager().getNodeType(DnaLexicon.ROOT); + + assertThat(rootNodePrimaryType.getName(), is(dnaRootType.getName())); } @@ -447,4 +461,34 @@ } + /* + * Moved these three tests over from AbstractJcrNode as they require more extensive scaffolding that is already implemented in + * this test. + */ + + @Test + public void shouldProvideUuidIfReferenceable() throws Exception { + // The root node is referenceable in DNA + Node rootNode = session.getRootNode(); + + UUID uuid = ((AbstractJcrNode)rootNode).internalUuid(); + assertThat(rootNode.getUUID(), is(uuid.toString())); + } + + @Test( expected = UnsupportedRepositoryOperationException.class ) + public void shouldNotProvideUuidIfNotReferenceable() throws Exception { + // The b node was not set up to be referenceable in this test, but does have a mixin type + Node node = session.getRootNode().getNode("a"); + + node.getUUID(); + } + + @Test( expected = UnsupportedRepositoryOperationException.class ) + public void shouldNotProvideUuidIfNoMixinTypes() throws Exception { + // The c node was not set up to be referenceable in this test and has no mixin types + Node node = session.getRootNode().getNode("a").getNode("b").getNode("c"); + + node.getUUID(); + } + } Index: dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java (working copy) @@ -38,6 +38,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.MockitoAnnotations.Mock; /** * @author jverhaeg @@ -46,11 +48,15 @@ private ValueFactories factories; private JcrValue value; + @Mock + private SessionCache cache; @Before public void before() { + MockitoAnnotations.initMocks(this); + factories = new StandardValueFactories(Mockito.mock(NamespaceRegistry.class)); - value = new JcrValue(factories, PropertyType.BOOLEAN, true); + value = new JcrValue(factories, cache, PropertyType.BOOLEAN, true); } @Test @@ -102,30 +108,30 @@ @Test( expected = ValueFormatException.class ) public void shouldNotProvideBooleanForDate() throws Exception { - new JcrValue(factories, PropertyType.DATE, new Date()).getBoolean(); + new JcrValue(factories, cache, PropertyType.DATE, new Date()).getBoolean(); } @Test public void shouldProvideDateForDate() throws Exception { Date date = new Date(); - assertThat(new JcrValue(factories, PropertyType.DATE, date).getDate().getTime(), is(date)); + assertThat(new JcrValue(factories, cache, PropertyType.DATE, date).getDate().getTime(), is(date)); } @Test public void shouldProvideDoubleForDate() throws Exception { Date date = new Date(); - assertThat(new JcrValue(factories, PropertyType.DATE, date).getDouble(), is((double)date.getTime())); + assertThat(new JcrValue(factories, cache, PropertyType.DATE, date).getDouble(), is((double)date.getTime())); } @Test public void shouldProvideLongForDate() throws Exception { Date date = new Date(); - assertThat(new JcrValue(factories, PropertyType.DATE, date).getLong(), is(date.getTime())); + assertThat(new JcrValue(factories, cache, PropertyType.DATE, date).getLong(), is(date.getTime())); } @Test public void shouldProvideStreamForDate() throws Exception { - testProvidesStream(new JcrValue(factories, PropertyType.DATE, new Date())); + testProvidesStream(new JcrValue(factories, cache, PropertyType.DATE, new Date())); } @Test @@ -134,158 +140,160 @@ date.set(2008, 7, 18, 12, 0, 0); date.set(Calendar.MILLISECOND, 0); String expectedValue = "2008-08-18T12:00:00.000"; - assertThat(new JcrValue(factories, PropertyType.DATE, date).getString().substring(0, expectedValue.length()), + assertThat(new JcrValue(factories, cache, PropertyType.DATE, date).getString().substring(0, expectedValue.length()), is(expectedValue)); - assertThat(new JcrValue(factories, PropertyType.DATE, date.getTime()).getString().substring(0, expectedValue.length()), + assertThat(new JcrValue(factories, cache, PropertyType.DATE, date.getTime()).getString().substring(0, + expectedValue.length()), is(expectedValue)); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideBooleanForDouble() throws Exception { - new JcrValue(factories, PropertyType.DOUBLE, 0.0).getBoolean(); + new JcrValue(factories, cache, PropertyType.DOUBLE, 0.0).getBoolean(); } @Test public void shouldProvideDateForDouble() throws Exception { Calendar expectedValue = Calendar.getInstance(); expectedValue.setTime(new Date(0L)); - assertThat(new JcrValue(factories, PropertyType.DOUBLE, 0.0).getDate(), is(expectedValue)); + assertThat(new JcrValue(factories, cache, PropertyType.DOUBLE, 0.0).getDate(), is(expectedValue)); } @Test public void shouldProvideDoubleForDouble() throws Exception { - assertThat(new JcrValue(factories, PropertyType.DOUBLE, 1.2).getDouble(), is(1.2)); + assertThat(new JcrValue(factories, cache, PropertyType.DOUBLE, 1.2).getDouble(), is(1.2)); } @Test public void shouldProvideLongForDouble() throws Exception { - assertThat(new JcrValue(factories, PropertyType.DOUBLE, 1.0).getLong(), is(1L)); - assertThat(new JcrValue(factories, PropertyType.DOUBLE, Double.MAX_VALUE).getLong(), is(Long.MAX_VALUE)); + assertThat(new JcrValue(factories, cache, PropertyType.DOUBLE, 1.0).getLong(), is(1L)); + assertThat(new JcrValue(factories, cache, PropertyType.DOUBLE, Double.MAX_VALUE).getLong(), is(Long.MAX_VALUE)); } @Test public void shouldProvideStreamForDouble() throws Exception { - testProvidesStream(new JcrValue(factories, PropertyType.DOUBLE, 1.0)); + testProvidesStream(new JcrValue(factories, cache, PropertyType.DOUBLE, 1.0)); } @Test public void shouldProvideStringForDouble() throws Exception { - assertThat(new JcrValue(factories, PropertyType.DOUBLE, 1.0).getString(), is("1.0")); + assertThat(new JcrValue(factories, cache, PropertyType.DOUBLE, 1.0).getString(), is("1.0")); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideBooleanForLong() throws Exception { - new JcrValue(factories, PropertyType.LONG, 0L).getBoolean(); + new JcrValue(factories, cache, PropertyType.LONG, 0L).getBoolean(); } @Test public void shouldProvideDateForLong() throws Exception { Calendar expectedValue = Calendar.getInstance(); expectedValue.setTime(new Date(0L)); - assertThat(new JcrValue(factories, PropertyType.LONG, 0L).getDate(), is(expectedValue)); + assertThat(new JcrValue(factories, cache, PropertyType.LONG, 0L).getDate(), is(expectedValue)); } @Test public void shouldProvideDoubleForLong() throws Exception { - assertThat(new JcrValue(factories, PropertyType.LONG, 1L).getDouble(), is(1.0)); + assertThat(new JcrValue(factories, cache, PropertyType.LONG, 1L).getDouble(), is(1.0)); } @Test public void shouldProvideLongForLong() throws Exception { - assertThat(new JcrValue(factories, PropertyType.LONG, 1L).getLong(), is(1L)); + assertThat(new JcrValue(factories, cache, PropertyType.LONG, 1L).getLong(), is(1L)); } @Test public void shouldProvideStreamForLong() throws Exception { - testProvidesStream(new JcrValue(factories, PropertyType.LONG, 1L)); + testProvidesStream(new JcrValue(factories, cache, PropertyType.LONG, 1L)); } @Test public void shouldProvideStringForLong() throws Exception { - assertThat(new JcrValue(factories, PropertyType.LONG, 1L).getString(), is("1")); + assertThat(new JcrValue(factories, cache, PropertyType.LONG, 1L).getString(), is("1")); } @Test public void shouldProvideBooleanForString() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "true").getBoolean(), is(true)); - assertThat(new JcrValue(factories, PropertyType.STRING, "yes").getBoolean(), is(false)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "true").getBoolean(), is(true)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "yes").getBoolean(), is(false)); } @Test public void shouldProvideDateForString() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "2008").getDate(), notNullValue()); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "2008").getDate(), notNullValue()); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideDateForInvalidString() throws Exception { - new JcrValue(factories, PropertyType.STRING, "true").getDate(); + new JcrValue(factories, cache, PropertyType.STRING, "true").getDate(); } @Test public void shouldProvideDoubleForString() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "1").getDouble(), is(1.0)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "1").getDouble(), is(1.0)); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideDoubleForInvalidString() throws Exception { - new JcrValue(factories, PropertyType.STRING, "true").getDouble(); + new JcrValue(factories, cache, PropertyType.STRING, "true").getDouble(); } @Test public void shouldProvideLongForString() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "1").getLong(), is(1L)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "1").getLong(), is(1L)); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideLongForInvalidString() throws Exception { - new JcrValue(factories, PropertyType.STRING, "true").getLong(); + new JcrValue(factories, cache, PropertyType.STRING, "true").getLong(); } @Test public void shouldProvideStreamForString() throws Exception { - testProvidesStream(new JcrValue(factories, PropertyType.STRING, "true")); + testProvidesStream(new JcrValue(factories, cache, PropertyType.STRING, "true")); } @Test public void shouldProvideStringForString() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "true").getString(), is("true")); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "true").getString(), is("true")); } @Test public void shouldProvideBooleanForUuid() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, UUID.randomUUID()).getBoolean(), is(false)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, UUID.randomUUID()).getBoolean(), is(false)); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideDateForUuid() throws Exception { - new JcrValue(factories, PropertyType.STRING, UUID.randomUUID()).getDate(); + new JcrValue(factories, cache, PropertyType.STRING, UUID.randomUUID()).getDate(); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideDoubleForUuid() throws Exception { - new JcrValue(factories, PropertyType.STRING, UUID.randomUUID()).getDouble(); + new JcrValue(factories, cache, PropertyType.STRING, UUID.randomUUID()).getDouble(); } @Test( expected = ValueFormatException.class ) public void shouldNotProvideLongForUuid() throws Exception { - new JcrValue(factories, PropertyType.STRING, UUID.randomUUID()).getLong(); + new JcrValue(factories, cache, PropertyType.STRING, UUID.randomUUID()).getLong(); } @Test public void shouldProvideStreamForUuid() throws Exception { - testProvidesStream(new JcrValue(factories, PropertyType.STRING, UUID.randomUUID())); + testProvidesStream(new JcrValue(factories, cache, PropertyType.STRING, UUID.randomUUID())); } @Test public void shouldProvideStringForUuid() throws Exception { String expectedValue = "40d373f7-75ad-4d84-900e-c72ebd98abb9"; - assertThat(new JcrValue(factories, PropertyType.STRING, UUID.fromString(expectedValue)).getString(), is(expectedValue)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, UUID.fromString(expectedValue)).getString(), + is(expectedValue)); } @Test public void shouldProvideLength() throws Exception { - assertThat(new JcrValue(factories, PropertyType.STRING, "test").getLength(), is(4L)); - assertThat(new JcrValue(factories, PropertyType.BINARY, "test").getLength(), is(4L)); + assertThat(new JcrValue(factories, cache, PropertyType.STRING, "test").getLength(), is(4L)); + assertThat(new JcrValue(factories, cache, PropertyType.BINARY, "test").getLength(), is(4L)); } private void testProvidesStream( JcrValue value ) throws Exception { Index: dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java (working copy) @@ -31,14 +31,20 @@ import static org.mockito.Mockito.stub; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; import javax.jcr.nodetype.NodeType; import org.jboss.dna.common.statistic.Stopwatch; import org.jboss.dna.common.util.StringUtil; @@ -49,6 +55,7 @@ import org.jboss.dna.graph.property.Name; import org.jboss.dna.graph.property.Path; import org.jboss.dna.graph.property.Property; +import org.jboss.dna.graph.property.ValueFactories; import org.jboss.dna.jcr.cache.Children; import org.jboss.dna.jcr.cache.NodeInfo; import org.jboss.dna.jcr.cache.PropertyInfo; @@ -65,6 +72,7 @@ private String workspaceName; private ExecutionContext context; + private RepositoryNodeTypeManager repoTypes; private JcrNodeTypeManager nodeTypes; private Stopwatch sw; private Graph store; @@ -87,27 +95,74 @@ workspaceName = "theWorkspace"; + InMemoryRepositorySource source = new InMemoryRepositorySource(); + source.setName("store"); + source.setDefaultWorkspaceName(workspaceName); + store = Graph.create(source, context); + + cache = new SessionCache(session, workspaceName, context, nodeTypes, store); + stub(session.getExecutionContext()).toReturn(context); stub(session.namespaces()).toReturn(context.getNamespaceRegistry()); + stub(session.getValueFactory()).toReturn(valueFactoryForContextAndCache(context, cache)); // Load up all the node types ... - JcrNodeTypeSource nodeTypeSource = new JcrBuiltinNodeTypeSource(session); - nodeTypeSource = new DnaBuiltinNodeTypeSource(session, nodeTypeSource); - nodeTypeSource = new VehixNodeTypeSource(session, nodeTypeSource); - nodeTypes = new JcrNodeTypeManager(session, nodeTypeSource); + JcrNodeTypeSource nodeTypeSource = null; + nodeTypeSource = new JcrBuiltinNodeTypeSource(this.context, nodeTypeSource); + nodeTypeSource = new DnaBuiltinNodeTypeSource(this.context, nodeTypeSource); + nodeTypeSource = new VehixNodeTypeSource(context, nodeTypeSource); + repoTypes = new RepositoryNodeTypeManager(context, nodeTypeSource); + nodeTypes = new JcrNodeTypeManager(this.context, repoTypes); stub(session.nodeTypeManager()).toReturn(nodeTypes); - InMemoryRepositorySource source = new InMemoryRepositorySource(); - source.setName("store"); - source.setDefaultWorkspaceName(workspaceName); - store = Graph.create(source, context); - // Import the "cars.xml" file into the repository store.importXmlFrom(new File("src/test/resources/vehicles.xml")).into("/"); - cache = new SessionCache(session, workspaceName, context, nodeTypes, store); } + private ValueFactory valueFactoryForContextAndCache( ExecutionContext context, + SessionCache cache ) { + final ValueFactories valueFactories = context.getValueFactories(); + final SessionCache sessionCache = cache; + + return new ValueFactory() { + + public Value createValue( String value, + int propertyType ) { + return new JcrValue(valueFactories, sessionCache, propertyType, value); + } + + public Value createValue( javax.jcr.Node value ) throws RepositoryException { + return new JcrValue(valueFactories, sessionCache, PropertyType.REFERENCE, UUID.fromString(value.getUUID())); + } + + public Value createValue( InputStream value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.BINARY, value); + } + + public Value createValue( Calendar value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.DATE, value); + } + + public Value createValue( boolean value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.BOOLEAN, value); + } + + public Value createValue( double value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.DOUBLE, value); + } + + public Value createValue( long value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.LONG, value); + } + + public Value createValue( String value ) { + return new JcrValue(valueFactories, sessionCache, PropertyType.STRING, value); + } + }; + + } + /** * Define the node types for the "vehix" namespace. */ @@ -115,24 +170,24 @@ private final List primaryNodeTypes; private final List mixinNodeTypes; - public VehixNodeTypeSource( JcrSession session, + public VehixNodeTypeSource( ExecutionContext context, JcrNodeTypeSource predecessor ) { super(predecessor); this.primaryNodeTypes = new ArrayList(); this.mixinNodeTypes = new ArrayList(); - Name carName = session.getExecutionContext().getValueFactories().getNameFactory().create("vehix:car"); - Name aircraftName = session.getExecutionContext().getValueFactories().getNameFactory().create("vehix:aircraft"); + Name carName = context.getValueFactories().getNameFactory().create("vehix:car"); + Name aircraftName = context.getValueFactories().getNameFactory().create("vehix:aircraft"); JcrNodeType unstructured = findType(JcrNtLexicon.UNSTRUCTURED); // Add in the "vehix:car" node type (which extends "nt:unstructured") ... - JcrNodeType car = new JcrNodeType(session, carName, Arrays.asList(new NodeType[] {unstructured}), - NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, - ORDERABLE_CHILD_NODES); + JcrNodeType car = new JcrNodeType(context, (RepositoryNodeTypeManager)null, carName, + Arrays.asList(new NodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, + NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES); // Add in the "vehix:aircraft" node type (which extends "nt:unstructured") ... - JcrNodeType aircraft = new JcrNodeType(session, aircraftName, Arrays.asList(new NodeType[] {unstructured}), - NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, - ORDERABLE_CHILD_NODES); + JcrNodeType aircraft = new JcrNodeType(context, (RepositoryNodeTypeManager)null, aircraftName, + Arrays.asList(new NodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME, + NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES); primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,})); } Index: dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java (revision 783) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java (working copy) @@ -29,6 +29,7 @@ import java.util.List; import javax.jcr.PropertyType; import javax.jcr.nodetype.NodeType; +import org.jboss.dna.graph.ExecutionContext; /** * Node type source with additional node types that can be used for testing. This class defines its own namespace for its types. @@ -40,7 +41,7 @@ /** The list of mixin node types. */ private final List mixinNodeTypes; - TestNodeTypeSource( JcrSession session, + TestNodeTypeSource( ExecutionContext context, JcrNodeTypeSource predecessor ) { super(predecessor); @@ -50,32 +51,35 @@ JcrNodeType base = findType(JcrNtLexicon.BASE); if (base == null) { - String baseTypeName = JcrNtLexicon.BASE.getString(session.getExecutionContext().getNamespaceRegistry()); - String namespaceTypeName = DnaLexicon.NAMESPACE.getString(session.getExecutionContext().getNamespaceRegistry()); + String baseTypeName = JcrNtLexicon.BASE.getString(context.getNamespaceRegistry()); + String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry()); throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName)); } + + // Stubbing in child node and property definitions for now JcrNodeType constrainedType = new JcrNodeType( - session, + context, + NO_NODE_TYPE_MANAGER, TestLexicon.CONSTRAINED_TYPE, Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] { - new JcrPropertyDefinition(session, null, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_BINARY, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.BINARY, new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}, false), - new JcrPropertyDefinition(session, null, TestLexicon.CONSTRAINED_DATE, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_DATE, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.DATE, new String[] { "[,+1945-08-01T01:30:00.000Z]", "[+1975-08-01T01:30:00.000Z,)"}, false), - new JcrPropertyDefinition(session, null, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_DOUBLE, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, @@ -83,33 +87,33 @@ new String[] {"[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]"}, false), - new JcrPropertyDefinition(session, null, TestLexicon.CONSTRAINED_LONG, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_LONG, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.LONG, new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}, false), - new JcrPropertyDefinition(session, null, TestLexicon.CONSTRAINED_NAME, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_NAME, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.NAME, new String[] { "jcr:system", "dnatest:constrainedType"}, false), - new JcrPropertyDefinition(session, null, TestLexicon.CONSTRAINED_PATH, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_PATH, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.PATH, new String[] { // "/" + JcrLexicon.Namespace.URI + ":system/*", "b", "/a/b/c"}, false), "/jcr:system/*", "b", "/a/b/c"}, false), - new JcrPropertyDefinition(session, null, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_REFERENCE, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES, PropertyType.REFERENCE, new String[] {"dna:root",}, false), - new JcrPropertyDefinition(session, null, + new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_STRING, OnParentVersionBehavior.IGNORE.getJcrValue(), false, false, false, NO_DEFAULT_VALUES,