Return-Path: Delivered-To: apmail-incubator-jackrabbit-commits-archive@www.apache.org Received: (qmail 31742 invoked from network); 10 Feb 2006 14:06:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 10 Feb 2006 14:06:02 -0000 Received: (qmail 62141 invoked by uid 500); 10 Feb 2006 14:05:57 -0000 Mailing-List: contact jackrabbit-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jackrabbit-dev@incubator.apache.org Delivered-To: mailing list jackrabbit-commits@incubator.apache.org Received: (qmail 62130 invoked by uid 500); 10 Feb 2006 14:05:57 -0000 Delivered-To: apmail-incubator-jackrabbit-cvs@incubator.apache.org Received: (qmail 62120 invoked by uid 99); 10 Feb 2006 14:05:56 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Feb 2006 06:05:56 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Fri, 10 Feb 2006 06:05:55 -0800 Received: (qmail 31361 invoked by uid 65534); 10 Feb 2006 14:05:34 -0000 Message-ID: <20060210140534.31360.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r376692 - in /incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype: EffectiveNodeTypeCache.java NodeTypeDef.java NodeTypeImpl.java NodeTypeRegistry.java Date: Fri, 10 Feb 2006 14:05:33 -0000 To: jackrabbit-cvs@incubator.apache.org From: stefan@apache.org X-Mailer: svnmailer-1.0.6 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: stefan Date: Fri Feb 10 06:05:31 2006 New Revision: 376692 URL: http://svn.apache.org/viewcvs?rev=376692&view=rev Log: JCR-275: added NodeTypeRegistry.unregisterNodeTypes(Collection) - some additional cleaning up of implementation Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeTypeCache.java incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDef.java incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeTypeCache.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeTypeCache.java?rev=376692&r1=376691&r2=376692&view=diff ============================================================================== --- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeTypeCache.java (original) +++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeTypeCache.java Fri Feb 10 06:05:31 2006 @@ -107,8 +107,17 @@ * * @see WeightedKey#compareTo */ - Iterator keys() { + Iterator keyIterator() { return sortedKeys.iterator(); + } + + /** + * Returns the set of keys. + * + * @return the set of keys. + */ + Set keySet() { + return Collections.unmodifiableSet(sortedKeys); } //-------------------------------------------------------------< Dumpable > Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDef.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDef.java?rev=376692&r1=376691&r2=376692&view=diff ============================================================================== --- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDef.java (original) +++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDef.java Fri Feb 10 06:05:31 2006 @@ -44,6 +44,7 @@ public NodeTypeDef() { dependencies = null; name = null; + primaryItemName = null; nodeDefs = NodeDef.EMPTY_ARRAY; propDefs = PropDef.EMPTY_ARRAY; supertypes = QName.EMPTY_ARRAY; @@ -51,42 +52,6 @@ orderableChildNodes = false; } - public Object clone() throws CloneNotSupportedException { - // create a shallow copy - NodeTypeDef clone = (NodeTypeDef) super.clone(); - // clear dependencies (will be lazily built) - clone.resetDependencies(); - return clone; - } - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NodeTypeDef) { - NodeTypeDef other = (NodeTypeDef) obj; - return (name == null ? other.name == null : name.equals(other.name)) - && (primaryItemName == null ? other.primaryItemName == null : primaryItemName.equals(other.primaryItemName)) - && Arrays.equals(supertypes, other.supertypes) - && mixin == other.mixin - && orderableChildNodes == other.orderableChildNodes - && Arrays.equals(propDefs, other.propDefs) - && Arrays.equals(nodeDefs, other.nodeDefs); - } - return false; - } - - /** - * Returns zero to satisfy the Object equals/hashCode contract. - * This class is mutable and not meant to be used as a hash key. - * - * @return always zero - * @see Object#hashCode() - */ - public int hashCode() { - return 0; - } - /** * Returns a collection of node type QNames that are being * referenced by this node type definition (e.g. as supertypes, as @@ -144,6 +109,7 @@ dependencies = null; } + //----------------------------------------------------< setters & getters > /** * Sets the name of the node type being defined. * @@ -197,6 +163,7 @@ * @param defs An array of PropertyDef objects. */ public void setPropertyDefs(PropDef[] defs) { + resetDependencies(); propDefs = defs; } @@ -279,5 +246,46 @@ */ public NodeDef[] getChildNodeDefs() { return nodeDefs; + } + + //-------------------------------------------< java.lang.Object overrides > + public Object clone() { + NodeTypeDef clone = new NodeTypeDef(); + clone.name = name; + clone.primaryItemName = primaryItemName; + clone.supertypes = (QName[]) supertypes.clone(); + clone.mixin = mixin; + clone.orderableChildNodes = orderableChildNodes; + clone.nodeDefs = (NodeDef[]) nodeDefs.clone(); + clone.propDefs = (PropDef[]) propDefs.clone(); + return clone; + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NodeTypeDef) { + NodeTypeDef other = (NodeTypeDef) obj; + return (name == null ? other.name == null : name.equals(other.name)) + && (primaryItemName == null ? other.primaryItemName == null : primaryItemName.equals(other.primaryItemName)) + && Arrays.equals(supertypes, other.supertypes) + && mixin == other.mixin + && orderableChildNodes == other.orderableChildNodes + && Arrays.equals(propDefs, other.propDefs) + && Arrays.equals(nodeDefs, other.nodeDefs); + } + return false; + } + + /** + * Returns zero to satisfy the Object equals/hashCode contract. + * This class is mutable and not meant to be used as a hash key. + * + * @return always zero + * @see Object#hashCode() + */ + public int hashCode() { + return 0; } } Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java?rev=376692&r1=376691&r2=376692&view=diff ============================================================================== --- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java (original) +++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java Fri Feb 10 06:05:31 2006 @@ -66,14 +66,7 @@ this.ent = ent; this.ntMgr = ntMgr; this.nsResolver = nsResolver; - try { - // store a clone of the definition - this.ntd = (NodeTypeDef) ntd.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } + this.ntd = ntd; } /** @@ -94,14 +87,8 @@ * @return the definition of this node type */ public NodeTypeDef getDefinition() { - try { - // return a clone of the definition - return (NodeTypeDef) ntd.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } + // return clone to make sure nobody messes around with the 'live' definition + return (NodeTypeDef) ntd.clone(); } /** Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?rev=376692&r1=376691&r2=376692&view=diff ============================================================================== --- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original) +++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Fri Feb 10 06:05:31 2006 @@ -230,13 +230,7 @@ entCache.put(ent); // register clone of node type definition - try { - ntd = (NodeTypeDef) ntd.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } + ntd = (NodeTypeDef) ntd.clone(); registeredNTDefs.put(name, ntd); // store property & child node definitions of new node type by id @@ -252,31 +246,86 @@ return ent; } - private void internalUnregister(QName name) - throws NoSuchNodeTypeException, RepositoryException { - if (!registeredNTDefs.containsKey(name)) { - throw new NoSuchNodeTypeException(name.toString()); + /** + * Validates and registers the specified collection of NodeTypeDef + * objects. An InvalidNodeTypeDefException is thrown if the + * validation of any of the contained NodeTypeDef objects fails. + *

+ * Note that in the case an exception is thrown no node type will be + * eventually registered. + * + * @param ntDefs collection of NodeTypeDef objects + * @throws InvalidNodeTypeDefException + * @throws RepositoryException + * @see #registerNodeType + */ + private synchronized void internalRegister(Collection ntDefs) + throws InvalidNodeTypeDefException, RepositoryException { + + // @todo review + + // cache of pre-built aggregations of node types + EffectiveNodeTypeCache anEntCache = new EffectiveNodeTypeCache(entCache); + + // map of node type names and node type definitions + Map aRegisteredNTDefCache = new HashMap(registeredNTDefs); + + // temporarily register the node type definition + // and do some preliminary checks + for (Iterator iter = ntDefs.iterator(); iter.hasNext();) { + NodeTypeDef ntd = (NodeTypeDef) iter.next(); + QName name = ntd.getName(); + if (name != null && registeredNTDefs.containsKey(name)) { + String msg = name + " already exists"; + log.debug(msg); + throw new InvalidNodeTypeDefException(msg); + } + // add definition to temporary cache + aRegisteredNTDefCache.put(ntd.getName(), ntd); } - if (builtInNTDefs.contains(name)) { - throw new RepositoryException(name.toString() - + ": can't unregister built-in node type."); + + for (Iterator iter = ntDefs.iterator(); iter.hasNext();) { + NodeTypeDef ntd = (NodeTypeDef) iter.next(); + + EffectiveNodeType ent = validateNodeTypeDef(ntd, anEntCache, aRegisteredNTDefCache); + + // store new effective node type instance + anEntCache.put(ent); } + // since no exception was thrown so far the definitions are assumed to be valid + for (Iterator iter = ntDefs.iterator(); iter.hasNext();) { + NodeTypeDef ntd = (NodeTypeDef) iter.next(); + + // register clone of node type definition + ntd = (NodeTypeDef) ntd.clone(); + registeredNTDefs.put(ntd.getName(), ntd); + // store property & child node definitions of new node type by id + PropDef[] pda = ntd.getPropertyDefs(); + for (int i = 0; i < pda.length; i++) { + propDefs.put(pda[i].getId(), pda[i]); + } + NodeDef[] nda = ntd.getChildNodeDefs(); + for (int i = 0; i < nda.length; i++) { + nodeDefs.put(nda[i].getId(), nda[i]); + } + } + } + + private void internalUnregister(QName name) throws NoSuchNodeTypeException { NodeTypeDef ntd = (NodeTypeDef) registeredNTDefs.get(name); + if (ntd == null) { + throw new NoSuchNodeTypeException(name.toString()); + } registeredNTDefs.remove(name); /** * remove all affected effective node types from aggregates cache - * (collect keys first to prevent ConcurrentModificationException) + * (copy keys first to prevent ConcurrentModificationException) */ - Iterator iter = entCache.keys(); - ArrayList keys = new ArrayList(); - while (iter.hasNext()) { - keys.add(iter.next()); - } - iter = keys.iterator(); - while (iter.hasNext()) { + ArrayList keys = new ArrayList(entCache.keySet()); + for (Iterator keysIter = keys.iterator(); keysIter.hasNext();) { EffectiveNodeTypeCache.WeightedKey k = - (EffectiveNodeTypeCache.WeightedKey) iter.next(); + (EffectiveNodeTypeCache.WeightedKey) keysIter.next(); EffectiveNodeType ent = entCache.get(k); if (ent.includesNodeType(name)) { entCache.remove(k); @@ -294,6 +343,14 @@ } } + private void internalUnregister(Collection ntNames) + throws NoSuchNodeTypeException { + for (Iterator iter = ntNames.iterator(); iter.hasNext();) { + QName name = (QName) iter.next(); + internalUnregister(name); + } + } + /** * Add a NodeTypeRegistryListener * @@ -398,7 +455,9 @@ * @throws InvalidNodeTypeDefException * @throws RepositoryException */ - private EffectiveNodeType validateNodeTypeDef(NodeTypeDef ntd, EffectiveNodeTypeCache anEntCache, Map aRegisteredNTDefCache) + private EffectiveNodeType validateNodeTypeDef(NodeTypeDef ntd, + EffectiveNodeTypeCache anEntCache, + Map aRegisteredNTDefCache) throws InvalidNodeTypeDefException, RepositoryException { /** @@ -791,7 +850,9 @@ * @return * @throws NoSuchNodeTypeException */ - public synchronized EffectiveNodeType getEffectiveNodeType(QName ntName, EffectiveNodeTypeCache anEntCache, Map aRegisteredNTDefCache) + public synchronized EffectiveNodeType getEffectiveNodeType(QName ntName, + EffectiveNodeTypeCache anEntCache, + Map aRegisteredNTDefCache) throws NoSuchNodeTypeException { // 1. make sure that the specified node type exists if (!aRegisteredNTDefCache.containsKey(ntName)) { @@ -806,17 +867,8 @@ // 3. build effective node type try { - NodeTypeDef def = (NodeTypeDef) aRegisteredNTDefCache.get(ntName); - NodeTypeDef ntDef4ENT; - // return clone to make sure nobody messes around with the 'live' definition - try { - ntDef4ENT = (NodeTypeDef) def.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } - ent = EffectiveNodeType.create(this, ntDef4ENT, anEntCache, aRegisteredNTDefCache); + NodeTypeDef ntd = (NodeTypeDef) aRegisteredNTDefCache.get(ntName); + ent = EffectiveNodeType.create(this, ntd, anEntCache, aRegisteredNTDefCache); // store new effective node type anEntCache.put(ent); return ent; @@ -836,7 +888,9 @@ * @throws NodeTypeConflictException * @throws NoSuchNodeTypeException */ - public synchronized EffectiveNodeType getEffectiveNodeType(QName[] ntNames, EffectiveNodeTypeCache anEntCache, Map aRegisteredNTDefCache) + public synchronized EffectiveNodeType getEffectiveNodeType(QName[] ntNames, + EffectiveNodeTypeCache anEntCache, + Map aRegisteredNTDefCache) throws NodeTypeConflictException, NoSuchNodeTypeException { // 1. make sure every single node type exists for (int i = 0; i < ntNames.length; i++) { @@ -872,7 +926,7 @@ * aggregate (i.e. the cost of building it) */ boolean foundSubResult = false; - Iterator iter = anEntCache.keys(); + Iterator iter = anEntCache.keyIterator(); while (iter.hasNext()) { EffectiveNodeTypeCache.WeightedKey k = (EffectiveNodeTypeCache.WeightedKey) iter.next(); @@ -895,19 +949,9 @@ */ QName[] remainder = key.toArray(); for (int i = 0; i < remainder.length; i++) { - NodeTypeDef def = (NodeTypeDef) aRegisteredNTDefCache.get(remainder[i]); - NodeTypeDef clonedDef; - // return clone to make sure nobody messes around with the 'live' definition - try { - clonedDef = (NodeTypeDef) def.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } - + NodeTypeDef ntd = (NodeTypeDef) aRegisteredNTDefCache.get(remainder[i]); EffectiveNodeType ent = - EffectiveNodeType.create(this, clonedDef, anEntCache, aRegisteredNTDefCache); + EffectiveNodeType.create(this, ntd, anEntCache, aRegisteredNTDefCache); // store new effective node type anEntCache.put(ent); if (result == null) { @@ -975,7 +1019,9 @@ return getEffectiveNodeType(ntNames, entCache, registeredNTDefs); } - void checkForCircularInheritance(QName[] supertypes, Stack inheritanceChain, Map aRegisteredNTDefCache) + void checkForCircularInheritance(QName[] supertypes, + Stack inheritanceChain, + Map aRegisteredNTDefCache) throws InvalidNodeTypeDefException, RepositoryException { for (int i = 0; i < supertypes.length; i++) { QName nt = supertypes[i]; @@ -1062,7 +1108,8 @@ /** * Validates the NodeTypeDef and returns - * a registered EffectiveNodeType instance. + * an EffectiveNodeType object representing the newly + * registered node type. *

* The validation includes the following checks: *

    @@ -1118,176 +1165,110 @@ *

    * This method can be used to register a set of node types that have * dependencies on each other. - *

    - * Note that in the case an exception is thrown, some node types might have - * been nevertheless successfully registered. * - * @param newNTDefs a collection of NodeTypeDefs + * @param ntDefs a collection of NodeTypeDef objects * @throws InvalidNodeTypeDefException * @throws RepositoryException */ - public synchronized void registerNodeTypes(Collection newNTDefs) + public synchronized void registerNodeTypes(Collection ntDefs) throws InvalidNodeTypeDefException, RepositoryException { - // exceptions that might be thrown by internalRegister(Collection) - RepositoryException re = null; - InvalidNodeTypeDefException intde = null; - - try { - internalRegister(newNTDefs); - } catch (RepositoryException e) { - // store exception so it can be re-thrown later on - re = e; - } catch (InvalidNodeTypeDefException e) { - // store exception so it can be re-thrown later on - intde = e; - } - boolean allNodeTypeDefsAreValid = re == null && intde == null; - if (allNodeTypeDefsAreValid) { - Iterator validNTDsIterator = newNTDefs.iterator(); - while (validNTDsIterator.hasNext()) { - NodeTypeDef ntd = (NodeTypeDef) validNTDsIterator.next(); - // store property & child node definitions of new node type by id - customNTDefs.add(ntd); - } - persistCustomNodeTypeDefs(customNTDefs); - // notify listeners - for (Iterator iter = newNTDefs.iterator(); iter.hasNext();) { - NodeTypeDef ntDef = (NodeTypeDef) iter.next(); - notifyRegistered(ntDef.getName()); - } - } else { - // re-throw the exception - if (re != null) { - throw re; - } else if (intde != null) { - throw intde; - } + // validate and register new node type definitions + internalRegister(ntDefs); + // persist new node type definitions + for (Iterator iter = ntDefs.iterator(); iter.hasNext();) { + NodeTypeDef ntDef = (NodeTypeDef) iter.next(); + customNTDefs.add(ntDef); + } + persistCustomNodeTypeDefs(customNTDefs); + // notify listeners + for (Iterator iter = ntDefs.iterator(); iter.hasNext();) { + NodeTypeDef ntDef = (NodeTypeDef) iter.next(); + notifyRegistered(ntDef.getName()); } } /** - * Validates and registers the specified collection of NodeTypeDef - * objects. An InvalidNodeTypeDefException is thrown if the - * validation of any of the contained NodeTypeDef objects fails. + * Same as {@link #unregisterNodeType(QName)} except + * that a set of node types is unregistered instead of just one. *

    - * Note that in the case an exception is thrown no node type will be - * registered. + * This method can be used to unregister a set of node types that depend on + * each other. * - * @param newNTDefs collection of NodeTypeDef objects - * @throws InvalidNodeTypeDefException - * @throws RepositoryException - * @see #registerNodeType + * @param ntNames a collection of QName objects denoting the + * node types to be unregistered + * @throws NoSuchNodeTypeException if any of the specified names does not + * denote a registered node type. + * @throws RepositoryException if another error occurs + * @see #unregisterNodeType(QName) */ - private synchronized void internalRegister(Collection newNTDefs) - throws InvalidNodeTypeDefException, RepositoryException { - - // cache of pre-built aggregations of node types - EffectiveNodeTypeCache anEntCache = new EffectiveNodeTypeCache(entCache); - - // map of node type names and node type definitions - Map aRegisteredNTDefCache = new HashMap(registeredNTDefs); - - // temporarily register a clone of the node type definition - // and do some checks by the way - Iterator ntdNameIterator = newNTDefs.iterator(); - while (ntdNameIterator.hasNext()) { - Object ntdObject = ntdNameIterator.next(); - // check if the right type is used - if (!(ntdObject instanceof NodeTypeDef)) { - String msg = "The specified object is not of type " - + NodeTypeDef.class.getName(); - log.debug(msg); - throw new InvalidNodeTypeDefException(msg); - } else { - // check if the ntd is new - NodeTypeDef ntd = (NodeTypeDef) ntdObject; - QName name = ntd.getName(); - if (name != null && registeredNTDefs.containsKey(name)) { - String msg = name + " already exists"; - log.debug(msg); - throw new InvalidNodeTypeDefException(msg); - } - // clone the ntd and add it to the cache - NodeTypeDef clonedNTD; - try { - clonedNTD = (NodeTypeDef) ntd.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); + public synchronized void unregisterNodeTypes(Collection ntNames) + throws NoSuchNodeTypeException, RepositoryException { + // do some preliminary checks + for (Iterator iter = ntNames.iterator(); iter.hasNext();) { + QName ntName = (QName) iter.next(); + if (!registeredNTDefs.containsKey(ntName)) { + throw new NoSuchNodeTypeException(ntName.toString()); + } + if (builtInNTDefs.contains(ntName)) { + throw new RepositoryException(ntName.toString() + + ": can't unregister built-in node type."); + } + // check for node types other than those to be unregistered + // that depend on the given node types + Set dependents = getDependentNodeTypes(ntName); + dependents.removeAll(ntNames); + if (dependents.size() > 0) { + StringBuffer msg = new StringBuffer(); + msg.append(ntName + + " can not be removed because the following node types depend on it: "); + for (Iterator depIter = dependents.iterator(); depIter.hasNext();) { + msg.append(depIter.next()); + msg.append(" "); } - aRegisteredNTDefCache.put(clonedNTD.getName(), clonedNTD); + throw new RepositoryException(msg.toString()); } } - Iterator ntdIterator = newNTDefs.iterator(); - while (ntdIterator.hasNext()) { - NodeTypeDef ntd = (NodeTypeDef) ntdIterator.next(); - - EffectiveNodeType ent = validateNodeTypeDef(ntd, anEntCache, aRegisteredNTDefCache); - // store new effective node type instance - anEntCache.put(ent); + // make sure node types are not currently in use + for (Iterator iter = ntNames.iterator(); iter.hasNext();) { + QName ntName = (QName) iter.next(); + checkForReferencesInContent(ntName); } - // as no exception occured at this point, the ntds are valid - Iterator validNTDsIterator = newNTDefs.iterator(); - while (validNTDsIterator.hasNext()) { - NodeTypeDef ntd = (NodeTypeDef) validNTDsIterator.next(); - registeredNTDefs.put(ntd.getName(), ntd); - // store property & child node definitions of new node type by id - PropDef[] pda = ntd.getPropertyDefs(); - for (int i = 0; i < pda.length; i++) { - propDefs.put(pda[i].getId(), pda[i]); - } - NodeDef[] nda = ntd.getChildNodeDefs(); - for (int i = 0; i < nda.length; i++) { - nodeDefs.put(nda[i].getId(), nda[i]); - } + + // all preconditions are met, node types can now safely be unregistered + internalUnregister(ntNames); + + // persist removal of node type definitions & notify listeners + for (Iterator iter = ntNames.iterator(); iter.hasNext();) { + QName ntName = (QName) iter.next(); + customNTDefs.remove(ntName); + notifyUnregistered(ntName); } + persistCustomNodeTypeDefs(customNTDefs); } /** - * @param nodeTypeName - * @throws NoSuchNodeTypeException - * @throws RepositoryException + * Unregisters the specified node type. In order for a node type to be + * successfully unregistered it must meet the following conditions: + *

      + *
    1. the node type must obviously be registered.
    2. + *
    3. a built-in node type can not be unregistered.
    4. + *
    5. the node type must not have dependents, i.e. other node types that + * are referencing it.
    6. + *
    7. the node type must not be currently used by any workspace.
    8. + *
    + * + * @param ntName name of the node type to be unregistered + * @throws NoSuchNodeTypeException if ntName does not + * denote a registered node type. + * @throws RepositoryException if another error occurs. + * @see #unregisterNodeTypes(Collection) */ - public synchronized void unregisterNodeType(QName nodeTypeName) + public synchronized void unregisterNodeType(QName ntName) throws NoSuchNodeTypeException, RepositoryException { - if (!registeredNTDefs.containsKey(nodeTypeName)) { - throw new NoSuchNodeTypeException(nodeTypeName.toString()); - } - if (builtInNTDefs.contains(nodeTypeName)) { - throw new RepositoryException(nodeTypeName.toString() - + ": can't unregister built-in node type."); - } - - /** - * check if there are node types that have dependencies on the given - * node type - */ - Set dependentNTs = getDependentNodeTypes(nodeTypeName); - if (dependentNTs.size() > 0) { - StringBuffer msg = new StringBuffer(); - msg.append(nodeTypeName - + " could not be removed because the following node types are referencing it: "); - Iterator iterator = dependentNTs.iterator(); - while (iterator.hasNext()) { - msg.append(iterator.next()); - msg.append(" "); - } - throw new RepositoryException(msg.toString()); - } - - // make sure node type is not currently in use - checkForReferencesInContent(nodeTypeName); - - internalUnregister(nodeTypeName); - - // persist removal of node type definition - customNTDefs.remove(nodeTypeName); - persistCustomNodeTypeDefs(customNTDefs); - - // notify listeners - notifyUnregistered(nodeTypeName); + HashSet ntNames = new HashSet(); + ntNames.add(ntName); + unregisterNodeTypes(ntNames); } /** @@ -1370,7 +1351,7 @@ * Returns the names of those registered node types that have * dependencies on the given node type. * - * @param nodeTypeName + * @param nodeTypeName node type name * @return a set of node type QNames * @throws NoSuchNodeTypeException */ @@ -1410,13 +1391,7 @@ } NodeTypeDef def = (NodeTypeDef) registeredNTDefs.get(nodeTypeName); // return clone to make sure nobody messes around with the 'live' definition - try { - return (NodeTypeDef) def.clone(); - } catch (CloneNotSupportedException e) { - // should never get here - log.fatal("internal error", e); - throw new InternalError(e.getMessage()); - } + return (NodeTypeDef) def.clone(); } /**