You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/09/03 15:34:44 UTC

svn commit: r691606 - in /jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name: HashCache.java PathFactoryImpl.java PathMap.java

Author: mreutegg
Date: Wed Sep  3 06:34:43 2008
New Revision: 691606

URL: http://svn.apache.org/viewvc?rev=691606&view=rev
Log:
JCR-1715: Prevent excessive Path.Element instances

Modified:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathMap.java

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java?rev=691606&r1=691605&r2=691606&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java Wed Sep  3 06:34:43 2008
@@ -25,7 +25,7 @@
  *
  * @see https://issues.apache.org/jira/browse/JCR-1663
  */
-class HashCache {
+public class HashCache {
 
     /**
      * Size of the cache (must be a power of two). Note that this is the

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java?rev=691606&r1=691605&r2=691606&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java Wed Sep  3 06:34:43 2008
@@ -54,6 +54,8 @@
     private static final Path CURRENT_PATH = new PathImpl(new Path.Element[]{CURRENT_ELEMENT}, true);
     private static final Path PARENT_PATH = new PathImpl(new Path.Element[]{PARENT_ELEMENT}, true);
 
+    private final HashCache ELEMENT_CACHE = new HashCache();
+
     private PathFactoryImpl() {}
 
     public static PathFactory getInstance() {
@@ -180,7 +182,7 @@
         } else if (name.equals(ROOT_NAME)) {
             return ROOT_ELEMENT;
         } else {
-            return new Element(name, Path.INDEX_UNDEFINED);
+            return getCachedElement(new Element(name, Path.INDEX_UNDEFINED));
         }
     }
 
@@ -220,7 +222,7 @@
         int pos = elementString.indexOf('[');
         if (pos == -1) {
             Name name = NAME_FACTORY.create(elementString);
-            return new Element(name, Path.INDEX_UNDEFINED);
+            return getCachedElement(new Element(name, Path.INDEX_UNDEFINED));
         }
         Name name = NAME_FACTORY.create(elementString.substring(0, pos));
         int pos1 = elementString.indexOf(']');
@@ -644,6 +646,20 @@
     }
 
     //-------------------------------------------------------< Path.Element >---
+
+    /**
+     * If a cached copy of the given element already exists, then returns
+     * that copy. Otherwise the given element is cached and returned. This
+     * method only works correctly with elements that have an undefined index!
+     *
+     * @param element the element to return from the cache
+     * @return the given element or a previously cached copy
+     */
+    private Element getCachedElement(Element element) {
+        assert element.getIndex() == Path.INDEX_UNDEFINED;
+        return (Element) ELEMENT_CACHE.get(element);
+    }
+
     /**
      * Object representation of a single JCR path element.
      *

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathMap.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathMap.java?rev=691606&r1=691605&r2=691606&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathMap.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathMap.java Wed Sep  3 06:34:43 2008
@@ -131,7 +131,7 @@
      * Internal class holding the object associated with a certain
      * path element.
      */
-    public static class Element {
+    public final static class Element {
 
         /**
          * Parent element
@@ -154,9 +154,11 @@
         private Object obj;
 
         /**
-         * Name associated with this element
+         * Path.Element suitable for path construction associated with this
+         * element. The path element will never have a default index. Instead an
+         * undefined index value is set in that case.
          */
-        private Name name;
+        private Path.Element pathElement;
 
         /**
          * 1-based index associated with this element where index=0 is
@@ -169,8 +171,13 @@
          * @param nameIndex path element of this child
          */
         private Element(Path.Element nameIndex) {
-            this.name = nameIndex.getName();
             this.index = nameIndex.getIndex();
+            if (nameIndex.denotesName()) {
+                updatePathElement(nameIndex.getName(), index);
+            } else {
+                // root, current or parent
+                this.pathElement = nameIndex;
+            }
         }
 
         /**
@@ -185,6 +192,20 @@
         }
 
         /**
+         * Updates the {@link #pathElement} with a new name and index value.
+         *
+         * @param name the new name.
+         * @param index the new index.
+         */
+        private void updatePathElement(Name name, int index) {
+            if (index == Path.INDEX_DEFAULT) {
+                pathElement = PATH_FACTORY.createElement(name);
+            } else {
+                pathElement = PATH_FACTORY.createElement(name, index);
+            }
+        }
+
+        /**
          * Insert an empty child. Will shift all children having an index
          * greater than or equal to the child inserted to the right.
          * @param nameIndex position where child is inserted
@@ -199,6 +220,7 @@
                         Element element = (Element) list.get(i);
                         if (element != null) {
                             element.index = element.getNormalizedIndex() + 1;
+                            element.updatePathElement(element.getName(), element.index);
                         }
                     }
                     list.add(index, null);
@@ -252,8 +274,8 @@
             }
 
             element.parent = this;
-            element.name = nameIndex.getName();
             element.index = nameIndex.getIndex();
+            element.updatePathElement(nameIndex.getName(), element.index);
 
             childrenCount++;
         }
@@ -305,6 +327,7 @@
                     Element sibling = (Element) list.get(i);
                     if (sibling != null) {
                         sibling.index--;
+                        sibling.updatePathElement(sibling.getName(), sibling.index);
                     }
                 }
                 list.remove(index);
@@ -409,7 +432,7 @@
          * @return name
          */
         public Name getName() {
-            return name;
+            return pathElement.getName();
         }
 
         /**
@@ -430,11 +453,7 @@
          * @return 1-based index
          */
         public int getNormalizedIndex() {
-            if (index == Path.INDEX_UNDEFINED) {
-                return Path.INDEX_DEFAULT;
-            } else {
-                return index;
-            }
+            return pathElement.getNormalizedIndex();
         }
 
         /**
@@ -443,9 +462,9 @@
          */
         public Path.Element getPathElement() {
             if (index < Path.INDEX_DEFAULT) {
-                return PATH_FACTORY.create(name).getNameElement();
+                return PATH_FACTORY.create(getName()).getNameElement();
             } else {
-                return PATH_FACTORY.create(name, index).getNameElement();
+                return PATH_FACTORY.create(getName(), index).getNameElement();
             }
         }
 
@@ -475,11 +494,7 @@
                 return;
             }
             parent.getPath(builder);
-            if (index == Path.INDEX_UNDEFINED || index == Path.INDEX_DEFAULT) {
-                builder.addLast(name);
-            } else {
-                builder.addLast(name, index);
-            }
+            builder.addLast(pathElement);
         }
 
         /**