jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r792142 [5/35] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/ jackrabbit-core/src/main/java/org/apache/jackrabb...
Date Wed, 08 Jul 2009 13:57:46 GMT
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Wed Jul  8 13:57:13 2009
@@ -93,22 +93,25 @@
     private final PathMap lockMap = new PathMap();
 
     private final ReentrantLock lockMapLock = new ReentrantLock(){
-        
+
         private Xid activeXid;
-        
+
         public void acquire() throws InterruptedException {
-            if (Thread.interrupted()) throw new InterruptedException();
+            if (Thread.interrupted()) {
+                throw new InterruptedException();
+            }
             Thread caller = Thread.currentThread();
-            synchronized(this) {
+            synchronized (this) {
                 boolean allow = TransactionContext.isCurrentXid(activeXid, caller == owner_);
                 if (allow) {
                     ++holds_;
                 } else {
-                    try {  
-                        while (owner_ != null) 
-                            wait(); 
+                    try {
+                        while (owner_ != null) {
+                            wait();
+                        }
                         owner_ = caller;
-                        activeXid = (Xid) TransactionContext.getCurrentXid();
+                        activeXid = TransactionContext.getCurrentXid();
                         holds_ = 1;
                     } catch (InterruptedException ex) {
                         notify();
@@ -117,18 +120,18 @@
                 }
             }
         }
-        
+
         public synchronized void release()  {
             boolean allow = TransactionContext.isCurrentXid(activeXid, Thread.currentThread() == owner_);
-            if (!allow)
-                throw new Error("Illegal Lock usage"); 
-
+            if (!allow) {
+                throw new Error("Illegal Lock usage");
+            }
             if (--holds_ == 0) {
                 owner_ = null;
                 activeXid = null;
-                notify(); 
+                notify();
             }
-        }       
+        }
     };
 
     /**
@@ -219,7 +222,7 @@
                 sysSession.getItemManager().getItem(lockToken.getId());
             Path path = getPath(sysSession, lockToken.getId());
 
-            LockInfo info = new LockInfo(lockToken, false,
+            InternalLockInfo info = new InternalLockInfo(lockToken, false,
                     node.getProperty(NameConstants.JCR_LOCKISDEEP).getBoolean(),
                     node.getProperty(NameConstants.JCR_LOCKOWNER).getString());
             info.setLive(true);
@@ -239,12 +242,12 @@
             return;
         }
 
-        final ArrayList<LockInfo> list = new ArrayList<LockInfo>();
+        final ArrayList<AbstractLockInfo> list = new ArrayList<AbstractLockInfo>();
 
         lockMap.traverse(new PathMap.ElementVisitor() {
             public void elementVisited(PathMap.Element element) {
-                LockInfo info = (LockInfo) element.get();
-                if (!info.sessionScoped) {
+                AbstractLockInfo info = (AbstractLockInfo) element.get();
+                if (!info.isSessionScoped()) {
                     list.add(info);
                 }
             }
@@ -257,8 +260,8 @@
             writer = new BufferedWriter(
                     new OutputStreamWriter(locksFile.getOutputStream()));
             for (int i = 0; i < list.size(); i++) {
-                AbstractLockInfo info = (AbstractLockInfo) list.get(i);
-                writer.write(info.lockToken.toString());
+                AbstractLockInfo info = list.get(i);
+                writer.write(info.getLockToken());
                 writer.newLine();
             }
         } catch (FileSystemException fse) {
@@ -275,7 +278,7 @@
     }
 
     static SessionLockManager getSessionLockManager(SessionImpl session) throws RepositoryException {
-        Workspace wsp = (Workspace) session.getWorkspace();
+        Workspace wsp = session.getWorkspace();
         return (SessionLockManager) wsp.getLockManager();
     }
 
@@ -299,7 +302,7 @@
 
         SessionImpl session = (SessionImpl) node.getSession();
         String lockOwner = (ownerInfo != null) ? ownerInfo : session.getUserID();
-        LockInfo info = new LockInfo(new LockToken(node.getNodeId()),
+        InternalLockInfo info = new InternalLockInfo(new LockToken(node.getNodeId()),
                 isSessionScoped, isDeep, lockOwner, timeoutHint);
 
         ClusterOperation operation = null;
@@ -321,7 +324,7 @@
             if (other != null) {
                 if (element.hasPath(path)) {
                     throw new LockException("Node already locked: " + node);
-                } else if (other.deep) {
+                } else if (other.isDeep()) {
                     throw new LockException(
                             "Parent node has a deep lock: " + node);
                 }
@@ -336,11 +339,11 @@
             info.setLive(true);
             session.addListener(info);
             if (!info.isSessionScoped()) {
-                getSessionLockManager(session).lockTokenAdded(info.lockToken.toString());
+                getSessionLockManager(session).lockTokenAdded(info.getLockToken());
             }
             lockMap.put(path, info);
 
-            if (!info.sessionScoped) {
+            if (!info.isSessionScoped()) {
                 save();
                 successful = true;
             }
@@ -383,16 +386,14 @@
             if (info == null) {
                 throw new LockException("Node not locked: " + node);
             }
-            if (session != info.getLockHolder()) {
-                throw new LockException("Node not locked by session: " + node);
-            }
+            checkUnlock(info, session);
 
             getSessionLockManager(session).lockTokenRemoved(info.getLockToken(session));
-            
+
             element.set(null);
             info.setLive(false);
 
-            if (!info.sessionScoped) {
+            if (!info.isSessionScoped()) {
                 save();
                 successful = true;
             }
@@ -418,12 +419,12 @@
         lockMap.traverse(new PathMap.ElementVisitor() {
             public void elementVisited(PathMap.Element element) {
                 LockInfo info = (LockInfo) element.get();
-                if (info.isLive() && info.getLockHolder().equals(session)) {
+                if (info.isLive() && info.isLockHolder(session)) {
                     infos.add(info);
                 }
             }
         }, false);
-        return (AbstractLockInfo[]) infos.toArray(new AbstractLockInfo[infos.size()]);
+        return infos.toArray(new AbstractLockInfo[infos.size()]);
     }
 
     /**
@@ -446,7 +447,7 @@
             PathMap.Element element = lockMap.map(path, false);
             AbstractLockInfo info = (AbstractLockInfo) element.get();
             if (info != null) {
-                if (element.hasPath(path) || info.deep) {
+                if (element.hasPath(path) || info.isDeep()) {
                     return info;
                 }
             }
@@ -558,28 +559,6 @@
     /**
      * {@inheritDoc}
      */
-    public boolean isLockHolder(Session session, NodeImpl node)
-            throws RepositoryException {
-        acquire();
-
-        try {
-            SessionImpl nodeSession = (SessionImpl) node.getSession();
-            PathMap.Element element = lockMap.map(getPath(nodeSession, node.getId()), true);
-            if (element == null) {
-                return false;
-            }
-            AbstractLockInfo info = (AbstractLockInfo) element.get();
-            return info != null && info.getLockHolder() == session;
-        } catch (ItemNotFoundException e) {
-            return false;
-        } finally {
-            release();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public boolean isLocked(NodeImpl node) throws RepositoryException {
         acquire();
 
@@ -621,20 +600,78 @@
             throws LockException, RepositoryException {
 
         PathMap.Element element = lockMap.map(path, false);
-        AbstractLockInfo info = (AbstractLockInfo) element.get();
+        LockInfo info = (LockInfo) element.get();
         if (info != null) {
-            if (element.hasPath(path) || info.deep) {
-                if (session != info.getLockHolder()) {
-                    throw new LockException("Node locked.");
-                }
+            if (element.hasPath(path) || info.isDeep()) {
+                checkLock(info, session);
             }
         }
     }
 
     /**
+     * Check whether a lock info allows access to a session. May be overridden
+     * by subclasses to allow access to nodes for sessions other than the
+     * lock holder itself.
+     * <p/>
+     * Default implementation allows access to the lock holder only.
+     *
+     * @param info info to check
+     * @param session session
+     * @throws LockException if write access to the specified path is not allowed
+     * @throws RepositoryException if some other error occurs
+     */
+    protected void checkLock(LockInfo info, Session session)
+            throws LockException, RepositoryException {
+
+        if (!info.isLockHolder(session)) {
+            throw new LockException("Node locked.");
+        }
+    }
+
+    /**
      * {@inheritDoc}
      */
-    public void lockTokenAdded(SessionImpl session, String lt) throws LockException, RepositoryException {
+    public void checkUnlock(Session session, NodeImpl node)
+            throws LockException, RepositoryException {
+
+        // check whether node is locked by this session
+        PathMap.Element element = lockMap.map(getPath((SessionImpl) session,
+                node.getId()), true);
+        if (element == null) {
+            throw new LockException("Node not locked: " + node);
+        }
+        AbstractLockInfo info = (AbstractLockInfo) element.get();
+        if (info == null) {
+            throw new LockException("Node not locked: " + node);
+        }
+        checkUnlock(info, session);
+    }
+
+    /**
+     * Check whether a session is allowed to unlock a node. May be overridden
+     * by subclasses to allow this to sessions other than the lock holder
+     * itself.
+     * <p/>
+     * Default implementation allows unlocking to the lock holder only.
+     *
+     * @param info info to check
+     * @param session session
+     * @throws LockException if unlocking is denied
+     * @throws RepositoryException if some other error occurs
+     */
+    protected void checkUnlock(LockInfo info, Session session)
+            throws LockException, RepositoryException {
+
+        if (!info.isLockHolder(session)) {
+            throw new LockException("Node not locked by session: "
+                    + info.getId());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addLockToken(SessionImpl session, String lt) throws LockException, RepositoryException {
         try {
             LockToken lockToken = LockToken.parse(lt);
 
@@ -644,10 +681,12 @@
             if (element != null) {
                 AbstractLockInfo info = (AbstractLockInfo) element.get();
                 if (info != null) {
-                    if (info.getLockHolder() == null) {
+                    if (info.isLockHolder(session)) {
+                        // nothing to do
+                    } else if (info.getLockHolder() == null) {
                         info.setLockHolder(session);
-                        if (info instanceof LockInfo) {
-                            session.addListener((LockInfo) info);
+                        if (info instanceof InternalLockInfo) {
+                            session.addListener((InternalLockInfo) info);
                         }
                     } else {
                         String msg = "Cannot add lock token: lock already held by other session.";
@@ -668,18 +707,22 @@
     /**
      * {@inheritDoc}
      */
-    public void lockTokenRemoved(SessionImpl session, String lt) throws LockException, RepositoryException {
+    public void removeLockToken(SessionImpl session, String lt)
+            throws LockException, RepositoryException {
+
         try {
             LockToken lockToken = LockToken.parse(lt);
 
-            NodeImpl node = (NodeImpl)
-                this.sysSession.getItemManager().getItem(lockToken.getId());
+            NodeImpl node = (NodeImpl) this.sysSession.getItemManager()
+                    .getItem(lockToken.getId());
             PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
             if (element != null) {
                 AbstractLockInfo info = (AbstractLockInfo) element.get();
                 if (info != null) {
-                    if (session == info.getLockHolder()) {
+                    if (info.isLockHolder(session)) {
                         info.setLockHolder(null);
+                    } else if (info.getLockHolder() == null) {
+                        // nothing to do
                     } else {
                         String msg = "Cannot remove lock token: lock held by other session.";
                         log.warn(msg);
@@ -1020,13 +1063,13 @@
      * its position.
      */
     private void refresh(PathMap.Element element) {
-        final ArrayList infos = new ArrayList();
+        final ArrayList<AbstractLockInfo> infos = new ArrayList<AbstractLockInfo>();
         boolean needsSave = false;
 
         // save away non-empty children
         element.traverse(new PathMap.ElementVisitor() {
             public void elementVisited(PathMap.Element element) {
-                LockInfo info = (LockInfo) element.get();
+                AbstractLockInfo info = (AbstractLockInfo) element.get();
                 infos.add(info);
             }
         }, false);
@@ -1037,14 +1080,14 @@
         // now re-insert at appropriate location or throw away if node
         // does no longer exist
         for (int i = 0; i < infos.size(); i++) {
-            LockInfo info = (LockInfo) infos.get(i);
+            AbstractLockInfo info = infos.get(i);
             try {
-                NodeImpl node = (NodeImpl) sysSession.getItemManager().
-                        getItem(info.getId());
+                NodeImpl node = (NodeImpl) sysSession.getItemManager().getItem(
+                        info.getId());
                 lockMap.put(node.getPrimaryPath(), info);
             } catch (RepositoryException e) {
                 info.setLive(false);
-                if (!info.sessionScoped) {
+                if (!info.isSessionScoped()) {
                     needsSave = true;
                 }
             }
@@ -1125,7 +1168,7 @@
      * Contains information about a lock and gets placed inside the child
      * information of a {@link org.apache.jackrabbit.spi.commons.name.PathMap}.
      */
-    class LockInfo extends AbstractLockInfo implements SessionListener {
+    class InternalLockInfo extends AbstractLockInfo implements SessionListener {
 
         /**
          * Create a new instance of this class.
@@ -1135,8 +1178,8 @@
          * @param deep          whether lock is deep
          * @param lockOwner     owner of lock
          */
-        public LockInfo(LockToken lockToken, boolean sessionScoped,
-                        boolean deep, String lockOwner) {
+        public InternalLockInfo(LockToken lockToken, boolean sessionScoped,
+                                boolean deep, String lockOwner) {
             this(lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE);
         }
 
@@ -1149,8 +1192,8 @@
          * @param lockOwner     owner of lock
          * @param timeoutHint
          */
-        public LockInfo(LockToken lockToken, boolean sessionScoped,
-                        boolean deep, String lockOwner, long timeoutHint) {
+        public InternalLockInfo(LockToken lockToken, boolean sessionScoped,
+                                boolean deep, String lockOwner, long timeoutHint) {
             super(lockToken, sessionScoped, deep, lockOwner, timeoutHint);
         }
 
@@ -1164,8 +1207,8 @@
          *     from the session and set the lockHolder field to <code>null</code>.
          */
         public void loggingOut(SessionImpl session) {
-            if (live) {
-                if (sessionScoped) {
+            if (isLive()) {
+                if (isSessionScoped()) {
                     // if no session currently holds lock, reassign
                     SessionImpl lockHolder = getLockHolder();
                     if (lockHolder == null) {
@@ -1185,15 +1228,13 @@
                             NodeImpl node = (NodeImpl) systemSession.getItemManager().getItem(getId());
                             node.unlock();
                         } catch (RepositoryException re) {
-                            log.warn("Unable to remove session-scoped lock on node '" + lockToken + "': " + e.getMessage());
+                            log.warn("Unable to remove session-scoped lock on node '" + getLockToken() + "': " + e.getMessage());
                             log.debug("Root cause: ", e);
                         }
                     }
-                } else {
-                    if (session == lockHolder) {
-                        session.removeLockToken(lockToken.toString());
-                        lockHolder = null;
-                    }
+                } else if (isLockHolder(session)) {
+                    session.removeLockToken(getLockToken());
+                    setLockHolder(null);
                 }
             }
         }
@@ -1227,7 +1268,7 @@
             Path path = getPath(sysSession, nodeId);
 
             // create lock token
-            LockInfo info = new LockInfo(new LockToken(nodeId), false, isDeep, lockOwner);
+            InternalLockInfo info = new InternalLockInfo(new LockToken(nodeId), false, isDeep, lockOwner);
             info.setLive(true);
             lockMap.put(path, info);
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java Wed Jul  8 13:57:13 2009
@@ -72,7 +72,7 @@
      */
     public void addLockToken(String lockToken) throws LockException, RepositoryException {
         if (!lockTokens.contains(lockToken)) {
-            systemLockMgr.lockTokenAdded(session, lockToken);
+            systemLockMgr.addLockToken(session, lockToken);
         } else {
             log.debug("Lock token already present with session -> no effect.");
         }
@@ -83,7 +83,7 @@
      */
     public void removeLockToken(String lockToken) throws LockException, RepositoryException {
         if (lockTokens.contains(lockToken)) {
-            systemLockMgr.lockTokenRemoved(session, lockToken);
+            systemLockMgr.removeLockToken(session, lockToken);
         } else {
             throw new LockException("Lock token " + lockToken + " not present with session.");
         }
@@ -120,14 +120,14 @@
             while (node.isNew()) {
                 node = (NodeImpl) node.getParent();
             }
-            Lock l = (Lock) systemLockMgr.getLock(node);
+            Lock l = systemLockMgr.getLock(node);
             if (l.isDeep()) {
                 return l;
             } else {
                 throw new LockException("Node not locked: " + node);
             }
         } else {
-            return (Lock) systemLockMgr.getLock(node);
+            return systemLockMgr.getLock(node);
         }
     }
 
@@ -157,7 +157,7 @@
         checkLockable(node);
 
         synchronized (systemLockMgr) {
-            return (Lock) systemLockMgr.lock(node, isDeep, isSessionScoped, timeoutHint, ownerInfo);
+            return systemLockMgr.lock(node, isDeep, isSessionScoped, timeoutHint, ownerInfo);
         }
     }
 
@@ -179,9 +179,7 @@
             if (!systemLockMgr.holdsLock(node)) {
                 throw new LockException("Node not locked: " + node);
             }
-            if (!systemLockMgr.isLockHolder(session, node)) {
-                throw new LockException("Node not locked by session: " + node);
-            }
+            systemLockMgr.checkUnlock(session, node);
             systemLockMgr.unlock(node);
         }
     }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java Wed Jul  8 13:57:13 2009
@@ -56,17 +56,19 @@
     /**
      * Map of locked nodes, indexed by their (internal) id.
      */
-    private final Map lockedNodesMap = new HashMap();
+    private final Map<NodeId, XALockInfo> lockedNodesMap =
+            new HashMap<NodeId, XALockInfo>();
 
     /**
      * Map of unlocked nodes, indexed by their (internal) id.
      */
-    private final Map unlockedNodesMap = new HashMap();
+    private final Map<NodeId, XALockInfo> unlockedNodesMap =
+            new HashMap<NodeId, XALockInfo>();
 
     /**
      * List of lock/unlock operations.
      */
-    private final List operations = new ArrayList();
+    private final List<XALockInfo> operations = new ArrayList<XALockInfo>();
 
     /**
      * Operation index.
@@ -129,7 +131,7 @@
         NodeId id = node.getNodeId();
 
         // check negative set first
-        LockInfo info = (LockInfo) unlockedNodesMap.get(id);
+        XALockInfo info = unlockedNodesMap.get(id);
         if (info != null) {
             // if settings are compatible, this is effectively a no-op
             if (info.deep == isDeep && info.sessionScoped == isSessionScoped) {
@@ -146,7 +148,7 @@
 
         // create a new lock info for this node
         String lockOwner = (ownerInfo != null) ? ownerInfo : node.getSession().getUserID();
-        info = new LockInfo(node, new LockToken(id), isSessionScoped, isDeep, lockOwner);
+        info = new XALockInfo(node, new LockToken(id), isSessionScoped, isDeep, lockOwner);
         SessionImpl session = (SessionImpl) node.getSession();
         info.setLockHolder(session);
         info.setLive(true);
@@ -168,7 +170,7 @@
         NodeId id = node.getNodeId();
 
         // check positive set first
-        AbstractLockInfo info = (LockInfo) lockedNodesMap.get(id);
+        AbstractLockInfo info = lockedNodesMap.get(id);
         if (info != null) {
             lockedNodesMap.remove(id);
             operations.remove(info);
@@ -177,12 +179,12 @@
             info = getLockInfo(node);
             if (info == null || !info.getId().equals(id)) {
                 throw new LockException("Node not locked.");
-            } else if (info.getLockHolder() != node.getSession()) {
+            } else if (!info.isLockHolder(node.getSession())) {
                 throw new LockException("Node not locked by this session.");
             }
-            info = new LockInfo(node, info);
-            unlockedNodesMap.put(id, info);
-            operations.add(info);
+            XALockInfo xaInfo = new XALockInfo(node, info);
+            unlockedNodesMap.put(id, xaInfo);
+            operations.add(xaInfo);
         }
 
     }
@@ -194,8 +196,7 @@
      * @throws RepositoryException if an error occurs
      */
     public boolean isLocked(NodeImpl node) throws RepositoryException {
-        AbstractLockInfo info = getLockInfo(node);
-        return info != null;
+        return getLockInfo(node) != null;
     }
 
     /**
@@ -218,7 +219,7 @@
         if (!lockedNodesMap.isEmpty()) {
             NodeImpl current = node;
             for (;;) {
-                LockInfo info = (LockInfo) lockedNodesMap.get(current.getId());
+                XALockInfo info = lockedNodesMap.get(current.getId());
                 if (info != null) {
                     if (info.getId().equals(id) || info.deep) {
                         return info;
@@ -244,9 +245,10 @@
      */
     public AbstractLockInfo[] getLockInfos(SessionImpl session)
             throws RepositoryException {
-        ArrayList result = new ArrayList();
 
-        // get lock infos from global lock manager first
+        ArrayList<AbstractLockInfo> result = new ArrayList<AbstractLockInfo>();
+
+        // get lock informations from global lock manager first
         AbstractLockInfo[] infos = lockMgr.getLockInfos(session);
         for (int i = 0; i < infos.length; i++) {
             AbstractLockInfo info = infos[i];
@@ -256,7 +258,7 @@
             }
         }
 
-        // add 'uncommitted' lock infos
+        // add 'uncommitted' lock informations
         result.addAll(lockedNodesMap.values());
 
         return (AbstractLockInfo[]) result.toArray(new AbstractLockInfo[result.size()]);
@@ -264,9 +266,9 @@
 
     /**
      * Add lock token to this environment.
-     * @param session 
+     * @param session
      * @param lt lock token
-     * @throws RepositoryException 
+     * @throws RepositoryException
      */
     public void addLockToken(SessionImpl session, String lt) throws RepositoryException {
         try {
@@ -274,7 +276,9 @@
             NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
             AbstractLockInfo info = getLockInfo(node);
             if (info != null) {
-                if (info.getLockHolder() == null) {
+                if (info.isLockHolder(session)) {
+                    // nothing to do
+                } else if (info.getLockHolder() == null) {
                     info.setLockHolder(session);
                 } else {
                     String msg = "Cannot add lock token: lock already held by other session.";
@@ -293,9 +297,9 @@
 
     /**
      * Remove lock token from this environment.
-     * @param session 
+     * @param session
      * @param lt lock token
-     * @throws RepositoryException 
+     * @throws RepositoryException
      */
     public void removeLockToken(SessionImpl session, String lt) throws RepositoryException {
         try {
@@ -304,8 +308,10 @@
             NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
             AbstractLockInfo info = getLockInfo(node);
             if (info != null) {
-                if (session == info.getLockHolder()) {
+                if (info.isLockHolder(session)) {
                     info.setLockHolder(null);
+                } else if (info.getLockHolder() == null) {
+                    // nothing to do
                 } else {
                     String msg = "Cannot remove lock token: lock held by other session.";
                     log.warn(msg);
@@ -322,7 +328,7 @@
     }
 
     static SessionLockManager getSessionLockManager(SessionImpl session) throws RepositoryException {
-        Workspace wsp = (Workspace) session.getWorkspace();
+        Workspace wsp = session.getWorkspace();
         return (SessionLockManager) wsp.getLockManager();
     }
 
@@ -338,7 +344,7 @@
             try {
                 while (opIndex < operations.size()) {
                     try {
-                        LockInfo info = (LockInfo) operations.get(opIndex);
+                        XALockInfo info = operations.get(opIndex);
                         info.update();
                     } catch (RepositoryException e) {
                         throw new TransactionException("Unable to update.", e);
@@ -349,7 +355,7 @@
                 if (opIndex < operations.size()) {
                     while (opIndex > 0) {
                         try {
-                            LockInfo info = (LockInfo) operations.get(opIndex - 1);
+                            XALockInfo info = operations.get(opIndex - 1);
                             info.undo();
                         } catch (RepositoryException e) {
                             log.error("Unable to undo lock operation.", e);
@@ -392,7 +398,7 @@
             if (!operations.isEmpty()) {
                 while (opIndex > 0) {
                     try {
-                        LockInfo info = (LockInfo) operations.get(opIndex - 1);
+                        XALockInfo info = operations.get(opIndex - 1);
                         info.undo();
                     } catch (RepositoryException e) {
                         log.error("Unable to undo lock operation.", e);
@@ -411,8 +417,8 @@
      * XA environment.
      */
     public boolean differentXAEnv(AbstractLockInfo info) {
-        if (info instanceof LockInfo) {
-            LockInfo lockInfo = (LockInfo) info;
+        if (info instanceof XALockInfo) {
+            XALockInfo lockInfo = (XALockInfo) info;
             return lockInfo.getXAEnv() != this;
         }
         return true;
@@ -421,7 +427,7 @@
     /**
      * Information about a lock used inside transactions.
      */
-    class LockInfo extends AbstractLockInfo {
+    class XALockInfo extends AbstractLockInfo {
 
         /**
          * Node being locked/unlocked.
@@ -440,10 +446,11 @@
          * @param deep          whether lock is deep
          * @param lockOwner     owner of lock
          */
-        public LockInfo(NodeImpl node, LockToken lockToken,
-                        boolean sessionScoped, boolean deep, String lockOwner) {
+        public XALockInfo(NodeImpl node, LockToken lockToken,
+                          boolean sessionScoped, boolean deep, String lockOwner) {
 
-            this(node, lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE);
+            this(node, lockToken, sessionScoped, deep, lockOwner,
+                    TIMEOUT_INFINITE);
         }
 
         /**
@@ -453,9 +460,9 @@
          * @param deep          whether lock is deep
          * @param lockOwner     owner of lock
          */
-        public LockInfo(NodeImpl node, LockToken lockToken,
-                        boolean sessionScoped, boolean deep, String lockOwner,
-                        long timeoutHint) {
+        public XALockInfo(NodeImpl node, LockToken lockToken,
+                          boolean sessionScoped, boolean deep, String lockOwner,
+                          long timeoutHint) {
 
             super(lockToken, sessionScoped, deep, lockOwner, timeoutHint);
             this.node = node;
@@ -465,7 +472,7 @@
          * Create a new instance of this class. Used to signal an
          * unlock operation on some existing lock information.
          */
-        public LockInfo(NodeImpl node, AbstractLockInfo info) {
+        public XALockInfo(NodeImpl node, AbstractLockInfo info) {
             super(info.lockToken, info.sessionScoped, info.deep, info.lockOwner, info.getSecondsRemaining());
 
             this.node = node;

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java Wed Jul  8 13:57:13 2009
@@ -80,7 +80,7 @@
             info = lockMgr.internalLock(node, isDeep, isSessionScoped, timoutHint, ownerInfo);
         }
         lockMgr.writeLockProperties(node, info.lockOwner, info.deep);
-        return new XALock(this, info, node);
+        return new XALockImpl(this, info, node);
     }
 
     /**
@@ -98,7 +98,7 @@
         }
         SessionImpl session = (SessionImpl) node.getSession();
         NodeImpl holder = (NodeImpl) session.getItemManager().getItem(info.getId());
-        return new XALock(this, info, holder);
+        return new XALockImpl(this, info, holder);
     }
 
     /**
@@ -112,12 +112,12 @@
             infos = lockMgr.getLockInfos(session);
         }
 
-        XALock[] locks = new XALock[infos.length];
+        XALockImpl[] locks = new XALockImpl[infos.length];
 
         for (int i = 0; i < infos.length; i++) {
             AbstractLockInfo info = infos[i];
             NodeImpl holder = (NodeImpl) session.getItemManager().getItem(info.getId());
-            locks[i] = new XALock(this, info, holder);
+            locks[i] = new XALockImpl(this, info, holder);
         }
         return locks;
     }
@@ -150,75 +150,83 @@
     /**
      * {@inheritDoc}
      */
-    public boolean isLockHolder(Session session, NodeImpl node)
-            throws RepositoryException {
+    public boolean isLocked(NodeImpl node) throws RepositoryException {
         AbstractLockInfo info;
         if (isInXA()) {
             info = xaEnv.getLockInfo(node);
         } else {
             info = lockMgr.getLockInfo(node.getNodeId());
         }
-        return info != null && info.getId().equals(node.getId())
-                && info.getLockHolder() == session;
+        return info != null;
     }
 
     /**
      * {@inheritDoc}
      */
-    public boolean isLocked(NodeImpl node) throws RepositoryException {
+    public void checkLock(NodeImpl node) throws LockException, RepositoryException {
         AbstractLockInfo info;
         if (isInXA()) {
             info = xaEnv.getLockInfo(node);
+            if (info != null && !info.isLockHolder(node.getSession())) {
+                throw new LockException("Node locked.");
+            }
         } else {
-            info = lockMgr.getLockInfo(node.getNodeId());
+            lockMgr.checkLock(node);
         }
-        return info != null;
     }
 
     /**
      * {@inheritDoc}
      */
-    public void checkLock(NodeImpl node) throws LockException, RepositoryException {
-        AbstractLockInfo info;
+    public void checkLock(Path path, Session session)
+            throws LockException, RepositoryException {
+
         if (isInXA()) {
-            info = xaEnv.getLockInfo(node);
+            SessionImpl sessionImpl = (SessionImpl) session;
+            checkLock(sessionImpl.getItemManager().getNode(path));
         } else {
-            info = lockMgr.getLockInfo(node.getNodeId());
-        }
-        if (info != null && info.getLockHolder() != node.getSession()) {
-            throw new LockException("Node locked.");
+            lockMgr.checkLock(path, session);
         }
     }
 
     /**
      * {@inheritDoc}
      */
-    public void checkLock(Path path, Session session)
+    public void checkUnlock(Session session, NodeImpl node)
             throws LockException, RepositoryException {
 
-        SessionImpl sessionImpl = (SessionImpl) session;
-        checkLock(sessionImpl.getItemManager().getNode(path));
+        if (isInXA()) {
+            AbstractLockInfo info = xaEnv.getLockInfo(node);
+            if (info == null || !info.getId().equals(node.getId())) {
+                throw new LockException("Node not locked: " + node);
+            }
+            if (!info.isLockHolder(session)) {
+                throw new LockException("Node not locked by session: " + node);
+            }
+        } else {
+            lockMgr.checkUnlock(session, node);
+        }
     }
 
     /**
      * {@inheritDoc}
      */
-    public void lockTokenAdded(SessionImpl session, String lt) throws RepositoryException {
+    public void addLockToken(SessionImpl session, String lt) throws RepositoryException {
         if (isInXA()) {
             xaEnv.addLockToken(session, lt);
         } else {
-            lockMgr.lockTokenAdded(session, lt);
+            lockMgr.addLockToken(session, lt);
         }
     }
 
     /**
      * {@inheritDoc}
      */
-    public void lockTokenRemoved(SessionImpl session, String lt) throws RepositoryException {
+    public void removeLockToken(SessionImpl session, String lt) throws RepositoryException {
         if (isInXA()) {
             xaEnv.removeLockToken(session, lt);
         } else {
-            lockMgr.lockTokenRemoved(session, lt);
+            lockMgr.removeLockToken(session, lt);
         }
     }
 
@@ -293,7 +301,7 @@
         if (isInXA()) {
             return xaEnv.differentXAEnv(info);
         } else {
-            return info instanceof XAEnvironment.LockInfo;
+            return info instanceof XAEnvironment.XALockInfo;
         }
     }
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java Wed Jul  8 13:57:13 2009
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QValueConstraint;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -28,7 +29,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeSet;
@@ -44,26 +44,33 @@
     private static Logger log = LoggerFactory.getLogger(EffectiveNodeType.class);
 
     // list of explicitly aggregated {i.e. merged) node types
-    private final TreeSet mergedNodeTypes;
+    private final TreeSet<Name> mergedNodeTypes;
     // list of implicitly aggregated {through inheritance) node types
-    private final TreeSet inheritedNodeTypes;
+    private final TreeSet<Name> inheritedNodeTypes;
     // list of all either explicitly (through aggregation) or implicitly
     // (through inheritance) included node types.
-    private final TreeSet allNodeTypes;
+    private final TreeSet<Name> allNodeTypes;
     // map of named item definitions (maps name to list of definitions)
-    private final HashMap namedItemDefs;
+    private final HashMap<Name, List<ItemDef>> namedItemDefs;
     // list of unnamed item definitions (i.e. residual definitions)
-    private final ArrayList unnamedItemDefs;
+    private final ArrayList<ItemDef> unnamedItemDefs;
+
+    // flag indicating whether any included node type supports orderable child nodes
+    private boolean orderableChildNodes;
+
+    private Name primaryItemName;
 
     /**
      * private constructor.
      */
     private EffectiveNodeType() {
-        mergedNodeTypes = new TreeSet();
-        inheritedNodeTypes = new TreeSet();
-        allNodeTypes = new TreeSet();
-        namedItemDefs = new HashMap();
-        unnamedItemDefs = new ArrayList();
+        mergedNodeTypes = new TreeSet<Name>();
+        inheritedNodeTypes = new TreeSet<Name>();
+        allNodeTypes = new TreeSet<Name>();
+        namedItemDefs = new HashMap<Name, List<ItemDef>>();
+        unnamedItemDefs = new ArrayList<ItemDef>();
+        orderableChildNodes = false;
+        primaryItemName = null;
     }
 
     /**
@@ -84,7 +91,7 @@
      */
     static EffectiveNodeType create(NodeTypeDef ntd,
                                     EffectiveNodeTypeCache entCache,
-                                    Map ntdCache)
+                                    Map<Name, NodeTypeDef> ntdCache)
             throws NodeTypeConflictException, NoSuchNodeTypeException {
         // create empty effective node type instance
         EffectiveNodeType ent = new EffectiveNodeType();
@@ -97,35 +104,35 @@
         // map of all item definitions (maps id to definition)
         // used to effectively detect ambiguous child definitions where
         // ambiguity is defined in terms of definition identity
-        HashMap itemDefIds = new HashMap();
+        HashMap<Object, ItemDef> itemDefIds = new HashMap<Object, ItemDef>();
 
         NodeDef[] cnda = ntd.getChildNodeDefs();
-        for (int i = 0; i < cnda.length; i++) {
+        for (NodeDef aCnda : cnda) {
             // check if child node definition would be ambiguous within
             // this node type definition
-            if (itemDefIds.containsKey(cnda[i].getId())) {
+            if (itemDefIds.containsKey(aCnda.getId())) {
                 // conflict
                 String msg;
-                if (cnda[i].definesResidual()) {
+                if (aCnda.definesResidual()) {
                     msg = ntName + " contains ambiguous residual child node definitions";
                 } else {
                     msg = ntName + " contains ambiguous definitions for child node named "
-                            + cnda[i].getName();
+                            + aCnda.getName();
                 }
                 log.debug(msg);
                 throw new NodeTypeConflictException(msg);
             } else {
-                itemDefIds.put(cnda[i].getId(), cnda[i]);
+                itemDefIds.put(aCnda.getId(), aCnda);
             }
-            if (cnda[i].definesResidual()) {
+            if (aCnda.definesResidual()) {
                 // residual node definition
-                ent.unnamedItemDefs.add(cnda[i]);
+                ent.unnamedItemDefs.add(aCnda);
             } else {
                 // named node definition
-                Name name = cnda[i].getName();
-                List defs = (List) ent.namedItemDefs.get(name);
+                Name name = aCnda.getName();
+                List<ItemDef> defs = ent.namedItemDefs.get(name);
                 if (defs == null) {
-                    defs = new ArrayList();
+                    defs = new ArrayList<ItemDef>();
                     ent.namedItemDefs.put(name, defs);
                 }
                 if (defs.size() > 0) {
@@ -133,9 +140,8 @@
                      * there already exists at least one definition with that
                      * name; make sure none of them is auto-create
                      */
-                    for (int j = 0; j < defs.size(); j++) {
-                        ItemDef def = (ItemDef) defs.get(j);
-                        if (cnda[i].isAutoCreated() || def.isAutoCreated()) {
+                    for (ItemDef def : defs) {
+                        if (aCnda.isAutoCreated() || def.isAutoCreated()) {
                             // conflict
                             String msg = "There are more than one 'auto-create' item definitions for '"
                                     + name + "' in node type '" + ntName + "'";
@@ -144,36 +150,36 @@
                         }
                     }
                 }
-                defs.add(cnda[i]);
+                defs.add(aCnda);
             }
         }
         PropDef[] pda = ntd.getPropertyDefs();
-        for (int i = 0; i < pda.length; i++) {
+        for (PropDef aPda : pda) {
             // check if property definition would be ambiguous within
             // this node type definition
-            if (itemDefIds.containsKey(pda[i].getId())) {
+            if (itemDefIds.containsKey(aPda.getId())) {
                 // conflict
                 String msg;
-                if (pda[i].definesResidual()) {
+                if (aPda.definesResidual()) {
                     msg = ntName + " contains ambiguous residual property definitions";
                 } else {
                     msg = ntName + " contains ambiguous definitions for property named "
-                            + pda[i].getName();
+                            + aPda.getName();
                 }
                 log.debug(msg);
                 throw new NodeTypeConflictException(msg);
             } else {
-                itemDefIds.put(pda[i].getId(), pda[i]);
+                itemDefIds.put(aPda.getId(), aPda);
             }
-            if (pda[i].definesResidual()) {
+            if (aPda.definesResidual()) {
                 // residual property definition
-                ent.unnamedItemDefs.add(pda[i]);
+                ent.unnamedItemDefs.add(aPda);
             } else {
                 // named property definition
-                Name name = pda[i].getName();
-                List defs = (List) ent.namedItemDefs.get(name);
+                Name name = aPda.getName();
+                List<ItemDef> defs = ent.namedItemDefs.get(name);
                 if (defs == null) {
-                    defs = new ArrayList();
+                    defs = new ArrayList<ItemDef>();
                     ent.namedItemDefs.put(name, defs);
                 }
                 if (defs.size() > 0) {
@@ -181,9 +187,8 @@
                      * there already exists at least one definition with that
                      * name; make sure none of them is auto-create
                      */
-                    for (int j = 0; j < defs.size(); j++) {
-                        ItemDef def = (ItemDef) defs.get(j);
-                        if (pda[i].isAutoCreated() || def.isAutoCreated()) {
+                    for (ItemDef def : defs) {
+                        if (aPda.isAutoCreated() || def.isAutoCreated()) {
                             // conflict
                             String msg = "There are more than one 'auto-create' item definitions for '"
                                     + name + "' in node type '" + ntName + "'";
@@ -192,7 +197,7 @@
                         }
                     }
                 }
-                defs.add(pda[i]);
+                defs.add(aPda);
             }
         }
 
@@ -204,6 +209,34 @@
             ent.internalMerge(base, true);
         }
 
+        // resolve 'orderable child nodes' attribute value (JCR-1947)
+        if (ntd.hasOrderableChildNodes()) {
+            ent.orderableChildNodes = true;
+        } else {
+            Name[] nta = ent.getInheritedNodeTypes();
+            for (Name aNta : nta) {
+                NodeTypeDef def = ntdCache.get(aNta);
+                if (def.hasOrderableChildNodes()) {
+                    ent.orderableChildNodes = true;
+                    break;
+                }
+            }
+        }
+
+        // resolve 'primary item' attribute value (JCR-1947)
+        if (ntd.getPrimaryItemName() != null) {
+            ent.primaryItemName = ntd.getPrimaryItemName();
+        } else {
+            Name[] nta = ent.getInheritedNodeTypes();
+            for (Name aNta : nta) {
+                NodeTypeDef def = ntdCache.get(aNta);
+                if (def.getPrimaryItemName() != null) {
+                    ent.primaryItemName = def.getPrimaryItemName();
+                    break;
+                }
+            }
+        }
+
         // we're done
         return ent;
     }
@@ -218,54 +251,65 @@
         return new EffectiveNodeType();
     }
 
+    /**
+     * Returns true if any of the included node types supports
+     * 'orderable child nodes'; returns false otherwise.
+     * @return <code>true</code> if this effective node type has orderable child nodes
+     */
+    public boolean hasOrderableChildNodes() {
+        return orderableChildNodes;
+    }
+    
+    public Name getPrimaryItemName() {
+        return primaryItemName;
+    }
+
     public Name[] getMergedNodeTypes() {
-        return (Name[]) mergedNodeTypes.toArray(new Name[mergedNodeTypes.size()]);
+        return mergedNodeTypes.toArray(new Name[mergedNodeTypes.size()]);
     }
 
     public Name[] getInheritedNodeTypes() {
-        return (Name[]) inheritedNodeTypes.toArray(new Name[inheritedNodeTypes.size()]);
+        return inheritedNodeTypes.toArray(new Name[inheritedNodeTypes.size()]);
     }
 
     public Name[] getAllNodeTypes() {
-        return (Name[]) allNodeTypes.toArray(new Name[allNodeTypes.size()]);
+        return allNodeTypes.toArray(new Name[allNodeTypes.size()]);
     }
 
     public ItemDef[] getAllItemDefs() {
         if (namedItemDefs.size() == 0 && unnamedItemDefs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size() + unnamedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            defs.addAll((List) iter.next());
+        ArrayList<ItemDef> defs = new ArrayList<ItemDef>(namedItemDefs.size() + unnamedItemDefs.size());
+        for (List<ItemDef> itemDefs : namedItemDefs.values()) {
+            defs.addAll(itemDefs);
         }
         defs.addAll(unnamedItemDefs);
         if (defs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        return (ItemDef[]) defs.toArray(new ItemDef[defs.size()]);
+        return defs.toArray(new ItemDef[defs.size()]);
     }
 
     public ItemDef[] getNamedItemDefs() {
         if (namedItemDefs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            defs.addAll((List) iter.next());
+        ArrayList<ItemDef> defs = new ArrayList<ItemDef>(namedItemDefs.size());
+        for (List<ItemDef> itemDefs : namedItemDefs.values()) {
+            defs.addAll(itemDefs);
         }
         if (defs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        return (ItemDef[]) defs.toArray(new ItemDef[defs.size()]);
+        return defs.toArray(new ItemDef[defs.size()]);
     }
 
     public ItemDef[] getUnnamedItemDefs() {
         if (unnamedItemDefs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        return (ItemDef[]) unnamedItemDefs.toArray(new ItemDef[unnamedItemDefs.size()]);
+        return unnamedItemDefs.toArray(new ItemDef[unnamedItemDefs.size()]);
     }
 
     public boolean hasNamedItemDef(Name name) {
@@ -273,99 +317,85 @@
     }
 
     public ItemDef[] getNamedItemDefs(Name name) {
-        List defs = (List) namedItemDefs.get(name);
+        List<ItemDef> defs = namedItemDefs.get(name);
         if (defs == null || defs.size() == 0) {
             return ItemDef.EMPTY_ARRAY;
         }
-        return (ItemDef[]) defs.toArray(new ItemDef[defs.size()]);
+        return defs.toArray(new ItemDef[defs.size()]);
     }
 
     public NodeDef[] getAllNodeDefs() {
         if (namedItemDefs.size() == 0 && unnamedItemDefs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size() + unnamedItemDefs.size());
-        Iterator iter = unnamedItemDefs.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(namedItemDefs.size() + unnamedItemDefs.size());
+        for (ItemDef def : unnamedItemDefs) {
             if (def.definesNode()) {
-                defs.add(def);
+                defs.add((NodeDef) def);
             }
         }
-        iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        for (List<ItemDef> list: namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (def.definesNode()) {
-                    defs.add(def);
+                    defs.add((NodeDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     public NodeDef[] getNamedNodeDefs() {
         if (namedItemDefs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (def.definesNode()) {
-                    defs.add(def);
+                    defs.add((NodeDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     public NodeDef[] getNamedNodeDefs(Name name) {
-        List list = (List) namedItemDefs.get(name);
+        List<ItemDef> list = namedItemDefs.get(name);
         if (list == null || list.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(list.size());
-        Iterator iter = list.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(list.size());
+        for (ItemDef def : list) {
             if (def.definesNode()) {
-                defs.add(def);
+                defs.add((NodeDef) def);
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     public NodeDef[] getUnnamedNodeDefs() {
         if (unnamedItemDefs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(unnamedItemDefs.size());
-        Iterator iter = unnamedItemDefs.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(unnamedItemDefs.size());
+        for (ItemDef def : unnamedItemDefs) {
             if (def.definesNode()) {
-                defs.add(def);
+                defs.add((NodeDef) def);
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     public NodeDef[] getAutoCreateNodeDefs() {
@@ -374,110 +404,92 @@
         if (namedItemDefs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (def.definesNode() && def.isAutoCreated()) {
-                    defs.add(def);
+                    defs.add((NodeDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     public PropDef[] getAllPropDefs() {
         if (namedItemDefs.size() == 0 && unnamedItemDefs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size() + unnamedItemDefs.size());
-        Iterator iter = unnamedItemDefs.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(namedItemDefs.size() + unnamedItemDefs.size());
+        for (ItemDef def : unnamedItemDefs) {
             if (!def.definesNode()) {
-                defs.add(def);
+                defs.add((PropDef) def);
             }
         }
-        iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        for (List<ItemDef> list: namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (!def.definesNode()) {
-                    defs.add(def);
+                    defs.add((PropDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public PropDef[] getNamedPropDefs() {
         if (namedItemDefs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (!def.definesNode()) {
-                    defs.add(def);
+                    defs.add((PropDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public PropDef[] getNamedPropDefs(Name name) {
-        List list = (List) namedItemDefs.get(name);
+        List<ItemDef> list = namedItemDefs.get(name);
         if (list == null || list.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(list.size());
-        Iterator iter = list.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(list.size());
+        for (ItemDef def : list) {
             if (!def.definesNode()) {
-                defs.add(def);
+                defs.add((PropDef) def);
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public PropDef[] getUnnamedPropDefs() {
         if (unnamedItemDefs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(unnamedItemDefs.size());
-        Iterator iter = unnamedItemDefs.iterator();
-        while (iter.hasNext()) {
-            ItemDef def = (ItemDef) iter.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(unnamedItemDefs.size());
+        for (ItemDef def : unnamedItemDefs) {
             if (!def.definesNode()) {
-                defs.add(def);
+                defs.add((PropDef) def);
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public PropDef[] getAutoCreatePropDefs() {
@@ -486,22 +498,18 @@
         if (namedItemDefs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (!def.definesNode() && def.isAutoCreated()) {
-                    defs.add(def);
+                    defs.add((PropDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public PropDef[] getMandatoryPropDefs() {
@@ -510,22 +518,18 @@
         if (namedItemDefs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<PropDef> defs = new ArrayList<PropDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (!def.definesNode() && def.isMandatory()) {
-                    defs.add(def);
+                    defs.add((PropDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return PropDef.EMPTY_ARRAY;
         }
-        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
+        return defs.toArray(new PropDef[defs.size()]);
     }
 
     public NodeDef[] getMandatoryNodeDefs() {
@@ -534,22 +538,18 @@
         if (namedItemDefs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                ItemDef def = (ItemDef) iter1.next();
+        ArrayList<NodeDef> defs = new ArrayList<NodeDef>(namedItemDefs.size());
+        for (List<ItemDef> list : namedItemDefs.values()) {
+            for (ItemDef def : list) {
                 if (def.definesNode() && def.isMandatory()) {
-                    defs.add(def);
+                    defs.add((NodeDef) def);
                 }
             }
         }
         if (defs.size() == 0) {
             return NodeDef.EMPTY_ARRAY;
         }
-        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
+        return defs.toArray(new NodeDef[defs.size()]);
     }
 
     /**
@@ -599,20 +599,20 @@
             throw new ConstraintViolationException("the property is not multi-valued");
         }
 
-        ValueConstraint[] constraints = pd.getValueConstraints();
+        QValueConstraint[] constraints = pd.getValueConstraints();
         if (constraints == null || constraints.length == 0) {
             // no constraints to check
             return;
         }
         if (values != null && values.length > 0) {
             // check value constraints on every value
-            for (int i = 0; i < values.length; i++) {
+            for (InternalValue value : values) {
                 // constraints are OR-ed together
                 boolean satisfied = false;
                 ConstraintViolationException cve = null;
-                for (int j = 0; j < constraints.length; j++) {
+                for (QValueConstraint constraint : constraints) {
                     try {
-                        constraints[j].check(values[i]);
+                        constraint.check(value);
                         satisfied = true;
                         break;
                     } catch (ConstraintViolationException e) {
@@ -652,6 +652,15 @@
     public void checkAddNodeConstraints(Name name, Name nodeTypeName,
                                         NodeTypeRegistry ntReg)
             throws ConstraintViolationException, NoSuchNodeTypeException {
+        if (nodeTypeName != null) {
+            NodeTypeDef ntDef = ntReg.getNodeTypeDef(nodeTypeName);
+            if (ntDef.isAbstract()) {
+                throw new ConstraintViolationException(nodeTypeName + " is abstract.");
+            }
+            if (ntDef.isMixin()) {
+                throw new ConstraintViolationException(nodeTypeName + " is mixin.");
+            }
+        }
         NodeDef nd = getApplicableChildNodeDef(name, nodeTypeName, ntReg);
         if (nd.isProtected()) {
             throw new ConstraintViolationException(name + " is protected");
@@ -686,9 +695,9 @@
 
         // try named node definitions first
         ItemDef[] defs = getNamedItemDefs(name);
-        for (int i = 0; i < defs.length; i++) {
-            if (defs[i].definesNode()) {
-                NodeDef nd = (NodeDef) defs[i];
+        for (ItemDef def : defs) {
+            if (def.definesNode()) {
+                NodeDef nd = (NodeDef) def;
                 Name[] types = nd.getRequiredPrimaryTypes();
                 // node definition with that name exists
                 if (entTarget != null && types != null) {
@@ -707,8 +716,7 @@
         // no item with that name defined;
         // try residual node definitions
         NodeDef[] nda = getUnnamedNodeDefs();
-        for (int i = 0; i < nda.length; i++) {
-            NodeDef nd = nda[i];
+        for (NodeDef nd : nda) {
             if (entTarget != null && nd.getRequiredPrimaryTypes() != null) {
                 // check 'required primary types' constraint
                 if (!entTarget.includesNodeTypes(nd.getRequiredPrimaryTypes())) {
@@ -810,37 +818,33 @@
 
     private PropDef getMatchingPropDef(PropDef[] defs, int type) {
         PropDef match = null;
-        for (int i = 0; i < defs.length; i++) {
-            ItemDef def = defs[i];
-            if (!def.definesNode()) {
-                PropDef pd = (PropDef) def;
-                int reqType = pd.getRequiredType();
-                // match type
-                if (reqType == PropertyType.UNDEFINED
-                        || type == PropertyType.UNDEFINED
-                        || reqType == type) {
-                    if (match == null) {
-                        match = pd;
+        for (PropDef pd : defs) {
+            int reqType = pd.getRequiredType();
+            // match type
+            if (reqType == PropertyType.UNDEFINED
+                    || type == PropertyType.UNDEFINED
+                    || reqType == type) {
+                if (match == null) {
+                    match = pd;
+                } else {
+                    // check if this definition is a better match than
+                    // the one we've already got
+                    if (match.getRequiredType() != pd.getRequiredType()) {
+                        if (match.getRequiredType() == PropertyType.UNDEFINED) {
+                            // found better match
+                            match = pd;
+                        }
                     } else {
-                        // check if this definition is a better match than
-                        // the one we've already got
-                        if (match.getRequiredType() != pd.getRequiredType()) {
-                            if (match.getRequiredType() == PropertyType.UNDEFINED) {
-                                // found better match
-                                match = pd;
-                            }
-                        } else {
-                            if (match.isMultiple() && !pd.isMultiple()) {
-                                // found better match
-                                match = pd;
-                            }
+                        if (match.isMultiple() && !pd.isMultiple()) {
+                            // found better match
+                            match = pd;
                         }
                     }
-                    if (match.getRequiredType() != PropertyType.UNDEFINED
-                            && !match.isMultiple()) {
-                        // found best possible match, get outta here
-                        return match;
-                    }
+                }
+                if (match.getRequiredType() != PropertyType.UNDEFINED
+                        && !match.isMultiple()) {
+                    // found best possible match, get outta here
+                    return match;
                 }
             }
         }
@@ -850,25 +854,21 @@
     private PropDef getMatchingPropDef(PropDef[] defs, int type,
                                        boolean multiValued) {
         PropDef match = null;
-        for (int i = 0; i < defs.length; i++) {
-            ItemDef def = defs[i];
-            if (!def.definesNode()) {
-                PropDef pd = (PropDef) def;
-                int reqType = pd.getRequiredType();
-                // match type
-                if (reqType == PropertyType.UNDEFINED
-                        || type == PropertyType.UNDEFINED
-                        || reqType == type) {
-                    // match multiValued flag
-                    if (multiValued == pd.isMultiple()) {
-                        // found match
-                        if (pd.getRequiredType() != PropertyType.UNDEFINED) {
-                            // found best possible match, get outta here
-                            return pd;
-                        } else {
-                            if (match == null) {
-                                match = pd;
-                            }
+        for (PropDef pd : defs) {
+            int reqType = pd.getRequiredType();
+            // match type
+            if (reqType == PropertyType.UNDEFINED
+                    || type == PropertyType.UNDEFINED
+                    || reqType == type) {
+                // match multiValued flag
+                if (multiValued == pd.isMultiple()) {
+                    // found match
+                    if (pd.getRequiredType() != PropertyType.UNDEFINED) {
+                        // found best possible match, get outta here
+                        return pd;
+                    } else {
+                        if (match == null) {
+                            match = pd;
                         }
                     }
                 }
@@ -888,11 +888,11 @@
          */
         ItemDef[] defs = getNamedItemDefs(name);
         if (defs != null) {
-            for (int i = 0; i < defs.length; i++) {
-                if (defs[i].isMandatory()) {
+            for (ItemDef def : defs) {
+                if (def.isMandatory()) {
                     throw new ConstraintViolationException("can't remove mandatory item");
                 }
-                if (defs[i].isProtected()) {
+                if (def.isProtected()) {
                     throw new ConstraintViolationException("can't remove protected item");
                 }
             }
@@ -910,11 +910,11 @@
          */
         ItemDef[] defs = getNamedNodeDefs(name);
         if (defs != null) {
-            for (int i = 0; i < defs.length; i++) {
-                if (defs[i].isMandatory()) {
+            for (ItemDef def : defs) {
+                if (def.isMandatory()) {
                     throw new ConstraintViolationException("can't remove mandatory node");
                 }
-                if (defs[i].isProtected()) {
+                if (def.isProtected()) {
                     throw new ConstraintViolationException("can't remove protected node");
                 }
             }
@@ -932,11 +932,11 @@
          */
         ItemDef[] defs = getNamedPropDefs(name);
         if (defs != null) {
-            for (int i = 0; i < defs.length; i++) {
-                if (defs[i].isMandatory()) {
+            for (ItemDef def : defs) {
+                if (def.isMandatory()) {
                     throw new ConstraintViolationException("can't remove mandatory property");
                 }
-                if (defs[i].isProtected()) {
+                if (def.isProtected()) {
                     throw new ConstraintViolationException("can't remove protected property");
                 }
             }
@@ -954,7 +954,7 @@
     EffectiveNodeType merge(EffectiveNodeType other)
             throws NodeTypeConflictException {
         // create a clone of this instance and perform the merge on
-        // the 'clone' to avoid a potentially inconsistant state
+        // the 'clone' to avoid a potentially inconsistent state
         // of this instance if an exception is thrown during
         // the merge.
         EffectiveNodeType copy = (EffectiveNodeType) clone();
@@ -979,10 +979,10 @@
             throws NodeTypeConflictException {
         Name[] nta = other.getAllNodeTypes();
         int includedCount = 0;
-        for (int i = 0; i < nta.length; i++) {
-            if (includesNodeType(nta[i])) {
+        for (Name aNta : nta) {
+            if (includesNodeType(aNta)) {
                 // redundant node type
-                log.debug("node type '" + nta[i] + "' is already contained.");
+                log.debug("node type '" + aNta + "' is already contained.");
                 includedCount++;
             }
         }
@@ -993,19 +993,17 @@
 
         // named item definitions
         ItemDef[] defs = other.getNamedItemDefs();
-        for (int i = 0; i < defs.length; i++) {
-            ItemDef def = defs[i];
+        for (ItemDef def : defs) {
             if (includesNodeType(def.getDeclaringNodeType())) {
                 // ignore redundant definitions
                 continue;
             }
             Name name = def.getName();
-            List existingDefs = (List) namedItemDefs.get(name);
+            List<ItemDef> existingDefs = namedItemDefs.get(name);
             if (existingDefs != null) {
                 if (existingDefs.size() > 0) {
                     // there already exists at least one definition with that name
-                    for (int j = 0; j < existingDefs.size(); j++) {
-                        ItemDef existingDef = (ItemDef) existingDefs.get(j);
+                    for (ItemDef existingDef : existingDefs) {
                         // make sure none of them is auto-create
                         if (def.isAutoCreated() || existingDef.isAutoCreated()) {
                             // conflict
@@ -1053,7 +1051,7 @@
                     }
                 }
             } else {
-                existingDefs = new ArrayList();
+                existingDefs = new ArrayList<ItemDef>();
                 namedItemDefs.put(name, existingDefs);
             }
             existingDefs.add(def);
@@ -1061,15 +1059,12 @@
 
         // residual item definitions
         defs = other.getUnnamedItemDefs();
-        for (int i = 0; i < defs.length; i++) {
-            ItemDef def = defs[i];
+        for (ItemDef def : defs) {
             if (includesNodeType(def.getDeclaringNodeType())) {
                 // ignore redundant definitions
                 continue;
             }
-            Iterator iter = unnamedItemDefs.iterator();
-            while (iter.hasNext()) {
-                ItemDef existing = (ItemDef) iter.next();
+            for (ItemDef existing : unnamedItemDefs) {
                 // compare with existing definition
                 if (def.definesNode() == existing.definesNode()) {
                     if (!def.definesNode()) {
@@ -1111,36 +1106,36 @@
             }
             unnamedItemDefs.add(def);
         }
-        for (int i = 0; i < nta.length; i++) {
-            allNodeTypes.add(nta[i]);
-        }
+        allNodeTypes.addAll(Arrays.asList(nta));
 
         if (supertype) {
             // implicit merge as result of inheritance
 
             // add other merged node types as supertypes
             nta = other.getMergedNodeTypes();
-            for (int i = 0; i < nta.length; i++) {
-                inheritedNodeTypes.add(nta[i]);
-            }
+            inheritedNodeTypes.addAll(Arrays.asList(nta));
             // add supertypes of other merged node types as supertypes
             nta = other.getInheritedNodeTypes();
-            for (int i = 0; i < nta.length; i++) {
-                inheritedNodeTypes.add(nta[i]);
-            }
+            inheritedNodeTypes.addAll(Arrays.asList(nta));
         } else {
             // explicit merge
 
             // merge with other merged node types
             nta = other.getMergedNodeTypes();
-            for (int i = 0; i < nta.length; i++) {
-                mergedNodeTypes.add(nta[i]);
-            }
+            mergedNodeTypes.addAll(Arrays.asList(nta));
             // add supertypes of other merged node types as supertypes
             nta = other.getInheritedNodeTypes();
-            for (int i = 0; i < nta.length; i++) {
-                inheritedNodeTypes.add(nta[i]);
-            }
+            inheritedNodeTypes.addAll(Arrays.asList(nta));
+        }
+
+        // update 'orderable child nodes' attribute value (JCR-1947)
+        if (other.hasOrderableChildNodes()) {
+            orderableChildNodes = true;
+        }
+
+        // update 'primary item' attribute value (JCR-1947)
+        if (primaryItemName == null && other.getPrimaryItemName() != null) {
+            primaryItemName = other.getPrimaryItemName();
         }
     }
 
@@ -1150,11 +1145,9 @@
         clone.mergedNodeTypes.addAll(mergedNodeTypes);
         clone.inheritedNodeTypes.addAll(inheritedNodeTypes);
         clone.allNodeTypes.addAll(allNodeTypes);
-        Iterator iter = namedItemDefs.keySet().iterator();
-        while (iter.hasNext()) {
-            Object key = iter.next();
-            List list = (List) namedItemDefs.get(key);
-            clone.namedItemDefs.put(key, new ArrayList(list));
+        for (Name name : namedItemDefs.keySet()) {
+            List<ItemDef> list = namedItemDefs.get(name);
+            clone.namedItemDefs.put(name, new ArrayList<ItemDef>(list));
         }
         clone.unnamedItemDefs.addAll(unnamedItemDefs);
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefImpl.java Wed Jul  8 13:57:13 2009
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.nodetype;
 
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QItemDefinition;
 
 import javax.jcr.version.OnParentVersionAction;
 
@@ -63,6 +64,15 @@
     public ItemDefImpl() {
     }
 
+    public ItemDefImpl(QItemDefinition def) {
+        name = def.getName();
+        declaringNodeType = def.getDeclaringNodeType();
+        autoCreated = def.isAutoCreated();
+        onParentVersion = def.getOnParentVersion();
+        writeProtected = def.isProtected();
+        mandatory = def.isMandatory();
+    }
+    
     /**
      * Sets the name of declaring node type.
      *

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefinitionImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefinitionImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ItemDefinitionImpl.java Wed Jul  8 13:57:13 2009
@@ -50,7 +50,8 @@
     protected final NodeTypeManagerImpl ntMgr;
 
     /**
-     * The name/path resolver used to translate qualified names to JCR names.
+     * The name/path resolver used to translate <code>Name</code>s to JCR name
+     * strings.
      */
     protected final NamePathResolver resolver;
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeDefImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeDefImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeDefImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeDefImpl.java Wed Jul  8 13:57:13 2009
@@ -17,10 +17,13 @@
 package org.apache.jackrabbit.core.nodetype;
 
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.QNodeDefinitionImpl;
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Set;
 
 /**
  * This class implements the <code>NodeDef</code> interface and additionally
@@ -36,7 +39,7 @@
     /**
      * The names of the required primary types.
      */
-    private HashSet requiredPrimaryTypes;
+    private Set<Name> requiredPrimaryTypes;
 
     /**
      * The 'allowsSameNameSiblings' flag.
@@ -55,12 +58,38 @@
      */
     public NodeDefImpl() {
         defaultPrimaryType = null;
-        requiredPrimaryTypes = new HashSet();
+        requiredPrimaryTypes = new HashSet<Name>();
         requiredPrimaryTypes.add(NameConstants.NT_BASE);
         allowsSameNameSiblings = false;
         id = null;
     }
 
+    public NodeDefImpl(QNodeDefinition nd) {
+        super(nd);
+        defaultPrimaryType = nd.getDefaultPrimaryType();
+        requiredPrimaryTypes = new HashSet<Name>(Arrays.asList(nd.getRequiredPrimaryTypes()));
+        allowsSameNameSiblings = nd.allowsSameNameSiblings();
+        id = null;
+    }
+
+    /**
+     * Returns the QNodeDefinition for this NodeDef
+     * @return the QNodeDefinition
+     */
+    public QNodeDefinition getQNodeDefinition() {
+        return new QNodeDefinitionImpl(
+                getName(),
+                getDeclaringNodeType(),
+                isAutoCreated(),
+                isMandatory(),
+                getOnParentVersion(),
+                isProtected(),
+                getDefaultPrimaryType(),
+                getRequiredPrimaryTypes(),
+                allowsSameNameSiblings()
+        );
+    }
+
     /**
      * Sets the name of default primary type.
      *
@@ -183,7 +212,7 @@
         if (requiredPrimaryTypes.isEmpty()) {
             return Name.EMPTY_ARRAY;
         }
-        return (Name[]) requiredPrimaryTypes.toArray(
+        return requiredPrimaryTypes.toArray(
                 new Name[requiredPrimaryTypes.size()]);
     }
 



Mime
View raw message