@SuppressWarnings("unchecked") @Test public void shouldAllowUnregisteringUnusedTypesWithMutualDependencies() throws Exception { ntTemplate.setName(TEST_TYPE_NAME); JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context); childNode.setDefaultPrimaryTypeName(TEST_TYPE_NAME2); ntTemplate.getNodeDefinitionTemplates().add(childNode); NodeTypeTemplate ntTemplate2 = new JcrNodeTypeTemplate(this.context); ntTemplate2.setName(TEST_TYPE_NAME2); JcrNodeDefinitionTemplate childNode2 = new JcrNodeDefinitionTemplate(this.context); childNode2.setDefaultPrimaryTypeName(TEST_TYPE_NAME); ntTemplate2.getNodeDefinitionTemplates().add(childNode2); try { repoTypeManager.registerNodeTypes( Arrays.asList(new NodeTypeDefinition[] {ntTemplate, ntTemplate2})); } catch (Exception ex) { fail(ex.getMessage()); } Name typeNameAsName = nameFactory.create(TEST_TYPE_NAME); Name type2NameAsName = nameFactory.create(TEST_TYPE_NAME2); int nodeTypeCount = nodeTypes().getAllNodeTypes().size(); repoTypeManager.unregisterNodeType( Arrays.asList(new Name[] {typeNameAsName, type2NameAsName}), true); assertThat(nodeTypes().getAllNodeTypes().size(), is(nodeTypeCount - 2)); assertThat(nodeTypes().getNodeType(typeNameAsName), is(nullValue())); assertThat(nodeTypes().getNodeType(type2NameAsName), is(nullValue())); }
@Test(expected = InvalidNodeTypeDefinitionException.class) public void shouldNotAllowUnregisteringRequiredPrimaryType() throws Exception { repoTypeManager.unregisterNodeType( Arrays.asList( new Name[] { JcrNtLexicon.FROZEN_NODE, }), true); }
@Test(expected = InvalidNodeTypeDefinitionException.class) public void shouldNotAllowUnregisteringSupertype() throws Exception { repoTypeManager.unregisterNodeType( Arrays.asList( new Name[] { JcrNtLexicon.HIERARCHY_NODE, }), true); }
@Test public void shouldAllowUnregisteringUnusedType() throws Exception { ntTemplate.setName(TEST_TYPE_NAME); JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context); childNode.setDefaultPrimaryTypeName(JcrNtLexicon.FILE.getString(this.registry)); ntTemplate.getNodeDefinitionTemplates().add(childNode); try { repoTypeManager.registerNodeType(ntTemplate); } catch (Exception ex) { fail(ex.getMessage()); } Name typeNameAsName = nameFactory.create(TEST_TYPE_NAME); int nodeTypeCount = nodeTypes().getAllNodeTypes().size(); repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {typeNameAsName}), true); assertThat(nodeTypes().getAllNodeTypes().size(), is(nodeTypeCount - 1)); assertThat(nodeTypes().getNodeType(typeNameAsName), is(nullValue())); }
/** * 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 * @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 AccessDeniedException if the current session does not have the {@link * ModeShapePermissions#REGISTER_TYPE register type permission}. * @throws RepositoryException if any other error occurs */ public void unregisterNodeTypes(Collection<String> nodeTypeNames) throws NoSuchNodeTypeException, InvalidNodeTypeDefinitionException, RepositoryException { NameFactory nameFactory = context().getValueFactories().getNameFactory(); try { session.checkPermission((Path) null, ModeShapePermissions.REGISTER_TYPE); } catch (AccessControlException ace) { throw new AccessDeniedException(ace); } Collection<Name> names = new ArrayList<Name>(nodeTypeNames.size()); for (String name : nodeTypeNames) { names.add(nameFactory.create(name)); } // Unregister the node types, but perform a check to see if any of the node types are currently // being used. // Unregistering a node type that is being used will likely cause the system to become unstable. boolean failIfNodeTypesAreUsed = true; repositoryTypeManager.unregisterNodeType(names, failIfNodeTypesAreUsed); }
@Test(expected = InvalidNodeTypeDefinitionException.class) public void shouldNotAllowUnregisteringDefaultPrimaryType() throws Exception { ntTemplate.setName(TEST_TYPE_NAME); JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context); childNode.setDefaultPrimaryTypeName(JcrNtLexicon.FILE.getString(this.registry)); ntTemplate.getNodeDefinitionTemplates().add(childNode); try { repoTypeManager.registerNodeType(ntTemplate); } catch (Exception ex) { fail(ex.getMessage()); } repoTypeManager.unregisterNodeType( Arrays.asList( new Name[] { JcrNtLexicon.FILE, }), true); }
@Test(expected = NoSuchNodeTypeException.class) public void shouldNotAllowUnregisteringInvalidTypeNames() throws Exception { repoTypeManager.unregisterNodeType( Arrays.asList(new Name[] {JcrNtLexicon.FILE, JcrLexicon.DATA}), true); }
@Test(expected = IllegalArgumentException.class) public void shouldNotAllowUnregisteringNullCollection() throws Exception { repoTypeManager.unregisterNodeType(null, true); }
@Override public void notify(ChangeSet changeSet) { if (!systemWorkspaceName.equals(changeSet.getWorkspaceName())) { // The change does not affect the 'system' workspace, so skip it ... return; } if (context.getProcessId().equals(changeSet.getProcessKey())) { // We generated these changes, so skip them ... return; } // Now process the changes ... Set<Name> nodeTypesToRefresh = new HashSet<Name>(); Set<Name> nodeTypesToDelete = new HashSet<Name>(); for (Change change : changeSet) { if (change instanceof NodeAdded) { NodeAdded added = (NodeAdded) change; Path addedPath = added.getPath(); if (nodeTypesPath.isAncestorOf(addedPath)) { // Get the name of the node type ... Name nodeTypeName = addedPath.getSegment(2).getName(); nodeTypesToRefresh.add(nodeTypeName); } } else if (change instanceof NodeRemoved) { NodeRemoved removed = (NodeRemoved) change; Path removedPath = removed.getPath(); if (nodeTypesPath.isAncestorOf(removedPath)) { // Get the name of the node type ... Name nodeTypeName = removedPath.getSegment(2).getName(); if (removedPath.size() == 3) { nodeTypesToDelete.add(nodeTypeName); } else { // It's a child defn or property defn ... if (!nodeTypesToDelete.contains(nodeTypeName)) { // The child defn or property defn is being removed but the node type is not ... nodeTypesToRefresh.add(nodeTypeName); } } } } else if (change instanceof PropertyChanged) { PropertyChanged propChanged = (PropertyChanged) change; Path changedPath = propChanged.getPathToNode(); if (nodeTypesPath.isAncestorOf(changedPath)) { // Get the name of the node type ... Name nodeTypeName = changedPath.getSegment(2).getName(); nodeTypesToRefresh.add(nodeTypeName); } } // we don't care about node moves (don't happen) or property added/removed (handled by node // add/remove) } if (nodeTypesToRefresh.isEmpty() && nodeTypesToDelete.isEmpty()) { // No changes return; } // There were at least some changes ... this.nodeTypesLock.writeLock().lock(); try { // Re-register the node types that were changed or added ... SessionCache systemCache = repository.createSystemSession(context, false); SystemContent system = new SystemContent(systemCache); Collection<NodeTypeDefinition> nodeTypes = system.readNodeTypes(nodeTypesToRefresh); registerNodeTypes(nodeTypes, false, false, false); // Unregister those that were removed ... unregisterNodeType(nodeTypesToDelete, false); } catch (Throwable e) { logger.error(e, JcrI18n.errorRefreshingNodeTypes, repository.name()); } finally { this.nodeTypesLock.writeLock().unlock(); } }