/** * Determine if any of the test type names are equal to or have been derived from the primary type * or any of the mixins. * * @param testTypeNames the names of the types or mixins being tested against (never <code>null * </code>) * @param primaryTypeName the primary type name (never <code>null</code>) * @param mixinNames the mixin names (may be <code>null</code>) * @return <code>true</code> if at least one test type name is equal to or derived from the * primary type or one of the mixins * @throws RepositoryException if there is an exception obtaining node types * @throws IllegalArgumentException if <code>testTypeNames</code> is <code>null</code> or empty or * if <code>primaryTypeName</code> is <code>null</code> or zero length */ public boolean isDerivedFrom(String[] testTypeNames, String primaryTypeName, String[] mixinNames) throws RepositoryException { CheckArg.isNotEmpty(testTypeNames, "testTypeNames"); CheckArg.isNotEmpty(primaryTypeName, "primaryTypeName"); NameFactory nameFactory = context().getValueFactories().getNameFactory(); Name[] typeNames = nameFactory.create(testTypeNames); // first check primary type for (Name typeName : typeNames) { JcrNodeType nodeType = getNodeType(typeName); if ((nodeType != null) && nodeType.isNodeType(primaryTypeName)) { return true; } } // now check mixins if (mixinNames != null) { for (String mixin : mixinNames) { for (Name typeName : typeNames) { JcrNodeType nodeType = getNodeType(typeName); if ((nodeType != null) && nodeType.isNodeType(mixin)) { return true; } } } } return false; }
/** * 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 NodeTypes#getNodeType(Name) */ JcrNodeType getNodeType(Name nodeTypeName) { JcrNodeType nodeType = nodeTypes().getNodeType(nodeTypeName); if (nodeType != null) { nodeType = nodeType.with(context(), session); } return nodeType; }
@Override public JcrNodeType getNodeType(String nodeTypeName) throws NoSuchNodeTypeException, RepositoryException { session.checkLive(); Name ntName = context().getValueFactories().getNameFactory().create(nodeTypeName); JcrNodeType type = nodeTypes().getNodeType(ntName); if (type != null) { type = type.with(context(), session); return type; } throw new NoSuchNodeTypeException(JcrI18n.typeNotFound.text(nodeTypeName)); }
@Override public NodeTypeIterator getPrimaryNodeTypes() throws RepositoryException { session.checkLive(); Collection<JcrNodeType> rawTypes = nodeTypes().getPrimaryNodeTypes(); List<JcrNodeType> types = new ArrayList<JcrNodeType>(rawTypes.size()); // Need to return a version of the node type with the current context for (JcrNodeType type : rawTypes) { types.add(type.with(context(), session)); } return new JcrNodeTypeIterator(types); }
@Test public void shouldAllowDefinitionWithExistingSupertypes() throws Exception { Name testTypeName = nameFactory.create(TEST_TYPE_NAME); ntTemplate.setName(TEST_TYPE_NAME); ntTemplate.setDeclaredSuperTypeNames(new String[] {"nt:base", "mix:referenceable"}); JcrNodeType testNodeType = repoTypeManager.registerNodeType(ntTemplate); assertThat(testNodeType.getName(), is(TEST_TYPE_NAME)); JcrNodeType nodeTypeFromRepo = nodeTypes().getNodeType(testTypeName); assertThat(nodeTypeFromRepo, is(notNullValue())); assertThat(nodeTypeFromRepo.getName(), is(TEST_TYPE_NAME)); }
@Test(expected = NodeTypeExistsException.class) public void shouldNotAllowRedefinitionOfNewTypeIfAllowUpdatesIsFalse() throws Exception { Name testTypeName = nameFactory.create(TEST_TYPE_NAME); ntTemplate.setName(TEST_TYPE_NAME); ntTemplate.setDeclaredSuperTypeNames(new String[] {"nt:base"}); JcrNodeType testNodeType = repoTypeManager.registerNodeType(ntTemplate); assertThat(testNodeType.getName(), is(TEST_TYPE_NAME)); JcrNodeType nodeTypeFromRepo = nodeTypes().getNodeType(testTypeName); assertThat(nodeTypeFromRepo, is(notNullValue())); assertThat(nodeTypeFromRepo.getName(), is(TEST_TYPE_NAME)); testNodeType = repoTypeManager.registerNodeType(ntTemplate); }
private void compareTemplateToNodeType(JcrNodeTypeTemplate template, JcrNodeType nodeType) { Name nodeTypeName = nameFactory.create(template.getName()); if (nodeType == null) { nodeType = nodeTypes().getNodeType(nodeTypeName); assertThat(nodeType.nodeTypeManager(), is(notNullValue())); } NodeTypeAssertion.compareTemplateToNodeType(template, nodeType); }
private void validateTypes(List<JcrNodeType> typesPendingRegistration) throws RepositoryException { NodeTypes nodeTypes = this.nodeTypesCache; for (JcrNodeType nodeType : typesPendingRegistration) { for (JcrNodeDefinition nodeDef : nodeType.getDeclaredChildNodeDefinitions()) { Name[] requiredPrimaryTypeNames = nodeDef.requiredPrimaryTypeNames(); for (Name primaryTypeName : requiredPrimaryTypeNames) { JcrNodeType requiredPrimaryType = nodeTypes.findTypeInMapOrList(primaryTypeName, typesPendingRegistration); if (requiredPrimaryType == null) { String msg = JcrI18n.invalidPrimaryTypeName.text(primaryTypeName, nodeType.getName()); throw new RepositoryException(msg); } } } if (nodeType.isMixin()) { for (NodeType superType : nodeType.getSupertypes()) { if (!superType.isMixin()) { String msg = JcrI18n.invalidMixinSupertype.text(nodeType.getName(), superType.getName()); throw new RepositoryException(msg); } } } } }
protected Indexes( ExecutionContext context, Collection<IndexDefinition> defns, NodeTypes nodeTypes) { // Identify the subtypes for each node type, and do this before we build any views ... if (!defns.isEmpty()) { Map<Name, Collection<String>> subtypesByName = new HashMap<>(); for (JcrNodeType nodeType : nodeTypes.getAllNodeTypes()) { // For each of the supertypes ... for (JcrNodeType supertype : nodeType.getTypeAndSupertypes()) { Collection<String> types = subtypesByName.get(supertype.getInternalName()); if (types == null) { types = new LinkedList<>(); subtypesByName.put(supertype.getInternalName(), types); } types.add(nodeType.getName()); } } // Now process all of the indexes ... NameFactory names = context.getValueFactories().getNameFactory(); Set<Name> nodeTypeNames = new HashSet<>(); for (IndexDefinition defn : defns) { // Determine all of the node types that are subtypes of any columns nodeTypeNames.clear(); Name nodeTypeName = names.create(defn.getNodeTypeName()); if (!subtypesByName.containsKey(nodeTypeName)) { Logger.getLogger(getClass()) .warn( JcrI18n.errorIndexing, "not creating index " + defn.getName() + " because of unknown nodeType " + nodeTypeName.getString()); continue; } indexByName.put(defn.getName(), defn); // Now find out all of the node types that are or subtype the named node types ... for (String typeAndSubtype : subtypesByName.get(nodeTypeName)) { Map<String, Collection<IndexDefinition>> byProvider = indexesByProviderByNodeTypeName.get(typeAndSubtype); if (byProvider == null) { byProvider = new HashMap<>(); indexesByProviderByNodeTypeName.put(typeAndSubtype, byProvider); } Collection<IndexDefinition> indexes = byProvider.get(defn.getProviderName()); if (indexes == null) { indexes = new LinkedList<>(); byProvider.put(typeAndSubtype, indexes); } indexes.add(defn); } } } }
List<JcrNodeType> registerNodeTypes( Iterable<NodeTypeDefinition> nodeTypeDefns, boolean failIfNodeTypeDefinitionsExist, boolean skipIfNodeTypeDefinitionExists, boolean persist) throws InvalidNodeTypeDefinitionException, NodeTypeExistsException, RepositoryException { if (nodeTypeDefns == null) { return Collections.emptyList(); } List<JcrNodeType> typesPendingRegistration = new ArrayList<JcrNodeType>(); try { nodeTypesLock.writeLock().lock(); final NodeTypes nodeTypes = this.nodeTypesCache; for (NodeTypeDefinition nodeTypeDefn : nodeTypeDefns) { if (nodeTypeDefn instanceof JcrNodeTypeTemplate) { // Switch to use this context, so names are properly prefixed ... nodeTypeDefn = ((JcrNodeTypeTemplate) nodeTypeDefn).with(context); } Name internalName = nodeTypes.nameFactory().create(nodeTypeDefn.getName()); if (internalName == null || internalName.getLocalName().length() == 0) { throw new InvalidNodeTypeDefinitionException(JcrI18n.invalidNodeTypeName.text()); } boolean found = nodeTypes.hasNodeType(internalName); if (found && failIfNodeTypeDefinitionsExist) { String name = nodeTypeDefn.getName(); throw new NodeTypeExistsException(internalName, JcrI18n.nodeTypeAlreadyExists.text(name)); } if (found && skipIfNodeTypeDefinitionExists) continue; List<JcrNodeType> supertypes = nodeTypes.supertypesFor(nodeTypeDefn, typesPendingRegistration); JcrNodeType nodeType = nodeTypeFrom(nodeTypeDefn, supertypes); typesPendingRegistration.add(nodeType); } if (!typesPendingRegistration.isEmpty()) { // Make sure the nodes have primary types that are either already registered, or pending // registration ... validateTypes(typesPendingRegistration); // Validate each of types that should be registered for (JcrNodeType typePendingRegistration : typesPendingRegistration) { nodeTypes.validate( typePendingRegistration, Arrays.asList(typePendingRegistration.getDeclaredSupertypes()), typesPendingRegistration); } SystemContent system = null; if (persist) { SessionCache systemCache = repository.createSystemSession(context, false); system = new SystemContent(systemCache); } for (JcrNodeType nodeType : typesPendingRegistration) { if (system != null) system.store(nodeType, true); } // Create the new cache ... NodeTypes newNodeTypes = nodeTypes.with(typesPendingRegistration); // Save the changes ... if (system != null) system.save(); // And finally update the capabilities cache ... this.nodeTypesCache = newNodeTypes; this.schemata = null; } } finally { nodeTypesLock.writeLock().unlock(); } return typesPendingRegistration; }
/** * Allows the collection of node types to be unregistered if they are not referenced by other node * types as supertypes, default primary types of child nodes, or required primary types of child * nodes. * * @param nodeTypeNames the names of the node types to be unregistered * @param failIfNodeTypesAreUsed true if this method should fail to unregister the named node * types if any of the node types are still in use by nodes, or false if this method should * not perform such a check * @throws NoSuchNodeTypeException if any of the node type names do not correspond to a registered * node type * @throws InvalidNodeTypeDefinitionException if any of the node types with the given names cannot * be unregistered because they are the supertype, one of the required primary types, or a * default primary type of a node type that is not being unregistered. * @throws RepositoryException if any other error occurs */ void unregisterNodeType(Collection<Name> nodeTypeNames, boolean failIfNodeTypesAreUsed) throws NoSuchNodeTypeException, InvalidNodeTypeDefinitionException, RepositoryException { CheckArg.isNotNull(nodeTypeNames, "nodeTypeNames"); if (nodeTypeNames.isEmpty()) return; if (failIfNodeTypesAreUsed) { long start = System.nanoTime(); // Search the content graph to make sure that this type isn't being used for (Name nodeTypeName : nodeTypeNames) { if (isNodeTypeInUse(nodeTypeName)) { String name = nodeTypeName.getString(context.getNamespaceRegistry()); throw new InvalidNodeTypeDefinitionException( JcrI18n.cannotUnregisterInUseType.text(name)); } } long time = TimeUnit.MILLISECONDS.convert(Math.abs(System.nanoTime() - start), TimeUnit.NANOSECONDS); logger.debug( "{0} milliseconds to check if any of these node types are unused before unregistering them: {1}", time, nodeTypeNames); } try { /* * Grab an exclusive lock on this data to keep other nodes from being added/saved while the unregistration checks are occurring */ List<JcrNodeType> removedNodeTypes = new ArrayList<JcrNodeType>(nodeTypeNames.size()); nodeTypesLock.writeLock().lock(); final NodeTypes nodeTypes = this.nodeTypesCache; for (Name nodeTypeName : nodeTypeNames) { /* * Check that the type names are valid */ if (nodeTypeName == null) { throw new NoSuchNodeTypeException(JcrI18n.invalidNodeTypeName.text()); } String name = nodeTypeName.getString(context.getNamespaceRegistry()); JcrNodeType foundNodeType = nodeTypes.getNodeType(nodeTypeName); if (foundNodeType == null) { throw new NoSuchNodeTypeException(JcrI18n.noSuchNodeType.text(name)); } removedNodeTypes.add(foundNodeType); /* * Check that no other node definitions have dependencies on any of the named types */ for (JcrNodeType nodeType : nodeTypes.getAllNodeTypes()) { // If this node is also being unregistered, don't run checks against it if (nodeTypeNames.contains(nodeType.getInternalName())) { continue; } for (JcrNodeType supertype : nodeType.supertypes()) { if (nodeTypeName.equals(supertype.getInternalName())) { throw new InvalidNodeTypeDefinitionException( JcrI18n.cannotUnregisterSupertype.text(name, supertype.getName())); } } for (JcrNodeDefinition childNode : nodeType.childNodeDefinitions()) { NodeType defaultPrimaryType = childNode.getDefaultPrimaryType(); if (defaultPrimaryType != null && name.equals(defaultPrimaryType.getName())) { throw new InvalidNodeTypeDefinitionException( JcrI18n.cannotUnregisterDefaultPrimaryType.text( name, nodeType.getName(), childNode.getName())); } if (childNode.requiredPrimaryTypeNameSet().contains(nodeTypeName)) { throw new InvalidNodeTypeDefinitionException( JcrI18n.cannotUnregisterRequiredPrimaryType.text( name, nodeType.getName(), childNode.getName())); } } } } // Create the new cache ... NodeTypes newNodeTypes = nodeTypes.without(removedNodeTypes); // Remove the node types from persistent storage ... SessionCache system = repository.createSystemSession(context, false); SystemContent systemContent = new SystemContent(system); systemContent.unregisterNodeTypes( removedNodeTypes.toArray(new JcrNodeType[removedNodeTypes.size()])); systemContent.save(); // Now change the cache ... this.nodeTypesCache = newNodeTypes; this.schemata = null; } finally { nodeTypesLock.writeLock().unlock(); } }