You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2010/04/11 19:52:52 UTC

svn commit: r932959 - in /jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3: util/ version/

Author: thomasm
Date: Sun Apr 11 17:52:52 2010
New Revision: 932959

URL: http://svn.apache.org/viewvc?rev=932959&view=rev
Log:
Some code for a Jackrabbit 3 prototype

Added:
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Cache.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheElement.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheSimple.java
      - copied, changed from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Cache.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Constants.java
      - copied, changed from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Constants.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/DateUtils.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/ExceptionFactory.java
      - copied, changed from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ExceptionFactory.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Log.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LogObject.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/StringUtils.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/WeakIdentityHashMap.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionHistoryImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionIteratorImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionManagerImpl.java

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Cache.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Cache.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Cache.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Cache.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,52 @@
+package org.apache.jackrabbit.j3.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A simple cache implementation.
+ *
+ * @param <K> the key
+ * @param <V> the value
+ */
+public class Cache<K, V extends CacheElement> extends LinkedHashMap<K, V> {
+
+    private final int maxMemory;
+    private long memoryUsed;
+
+    public Cache(int maxMemory) {
+        this.maxMemory = maxMemory;
+    }
+
+    public V put(K key, V value) {
+        V old = super.put(key, value);
+        if (old != value) {
+            if (old != null) {
+                memoryUsed -= old.getMemoryUsed() + Constants.MEM_MAP_ENTRY;
+            }
+            memoryUsed += value.getMemoryUsed() + Constants.MEM_MAP_ENTRY;
+        }
+        return old;
+    }
+
+    public void putAll(Map<? extends K, ? extends V> map) {
+        throw ExceptionFactory.unsupportedOperation();
+    }
+
+    public V remove(Object key) {
+        V e = super.remove(key);
+        if (e != null) {
+            this.memoryUsed -= e.getMemoryUsed() + Constants.MEM_MAP_ENTRY;
+        }
+        return e;
+    }
+
+    protected  boolean  removeEldestEntry(Map.Entry<K, V> eldest) {
+        return memoryUsed > maxMemory;
+    }
+
+    public long getMemoryUsed() {
+        return memoryUsed;
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheElement.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheElement.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheElement.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+/**
+ * A cache element.
+ */
+public interface CacheElement {
+
+    /**
+     * Get the memory used in bytes.
+     *
+     * @return the number of bytes
+     */
+    int getMemoryUsed();
+
+}

Copied: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheSimple.java (from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Cache.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheSimple.java?p2=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheSimple.java&p1=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Cache.java&r1=928437&r2=932959&rev=932959&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Cache.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/CacheSimple.java Sun Apr 11 17:52:52 2010
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.j3;
+package org.apache.jackrabbit.j3.util;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -25,11 +25,11 @@ import java.util.Map;
  * @param <K> the key
  * @param <V> the value
  */
-public class Cache<K, V> extends LinkedHashMap<K, V> {
+public class CacheSimple<K, V> extends LinkedHashMap<K, V> {
 
     private final int maxSize;
 
-    public Cache(int maxSize) {
+    public CacheSimple(int maxSize) {
         this.maxSize = maxSize;
     }
 

Copied: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Constants.java (from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Constants.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Constants.java?p2=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Constants.java&p1=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Constants.java&r1=928437&r2=932959&rev=932959&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Constants.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Constants.java Sun Apr 11 17:52:52 2010
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.j3;
+package org.apache.jackrabbit.j3.util;
 
 /**
  * Constants used in this project.
@@ -26,4 +26,15 @@ public class Constants {
 
     public static final String FULL_VERSION = VERSION_MAJOR + "." + VERSION_MINOR + "." + BUILD;
 
+    public static final String DEFAULT_URL = "mem:";
+
+    public static final int MEM_CACHE_PER_REPOSITORY = 16 * 1024 * 1024;
+
+    public static final int MEM_MAP_ENTRY = 32;
+    public static final int MEM_NODE_DATA = 48;
+    public static final int MEM_VAL_LONG =  32;
+    public static final int MEM_VAL_BINARY = 32;
+    public static final int MEM_VAL_STRING = 64;
+    public static final int MEM_VAL_OBJ = 16;
+
 }

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/DateUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/DateUtils.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/DateUtils.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/DateUtils.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * This utility class provides helper methods
+ * to deal with date/time formatting using a specific ISO8601-compliant
+ * format (see <a href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a>).
+ * <p/>
+ * The currently supported format is:
+ * <pre>
+ *   &plusmn;YYYY-MM-DDThh:mm:ss.SSSTZD
+ * </pre>
+ * where:
+ * <pre>
+ *   &plusmn;YYYY = four-digit year with optional sign where values <= 0 are
+ *           denoting years BCE and values > 0 are denoting years CE,
+ *           e.g. -0001 denotes the year 2 BCE, 0000 denotes the year 1 BCE,
+ *           0001 denotes the year 1 CE, and so on...
+ *   MM    = two-digit month (01=January, etc.)
+ *   DD    = two-digit day of month (01 through 31)
+ *   hh    = two digits of hour (00 through 23) (am/pm NOT allowed)
+ *   mm    = two digits of minute (00 through 59)
+ *   ss    = two digits of second (00 through 59)
+ *   SSS   = three digits of milliseconds (000 through 999)
+ *   TZD   = time zone designator, Z for Zulu (i.e. UTC) or an offset from UTC
+ *           in the form of +hh:mm or -hh:mm
+ * </pre>
+ */
+public final class DateUtils {
+
+    /**
+     * Get the ISO8601 String that represents this Calendar.
+     *
+     * @param c the Calendar
+     * @return the String
+     */
+    public static String convertCalendarToString(Calendar c) {
+        return format(c);
+    }
+
+    /**
+     * Get the Calendar that represents this ISO8601 String.
+     *
+     * @param c the String
+     * @return the Calendar (always a new object)
+     */
+    public static Calendar convertStringToCalendar(String s) {
+        Calendar c = parse(s);
+        if (c == null) {
+            throw ExceptionFactory.illegalArgument("Invalid date: {0}", s);
+        }
+        return c;
+    }
+
+    /**
+     * Parses an ISO8601-compliant date/time string.
+     *
+     * @param text the date/time string to be parsed
+     * @return a <code>Calendar</code>, or <code>null</code> if the input could
+     *         not be parsed
+     * @throws IllegalArgumentException if a <code>null</code> argument is passed
+     */
+    private static Calendar parse(String text) {
+        if (text == null) {
+            throw ExceptionFactory.nullPointer();
+        }
+
+        // check optional leading sign
+        char sign;
+        int start;
+        if (text.startsWith("-")) {
+            sign = '-';
+            start = 1;
+        } else if (text.startsWith("+")) {
+            sign = '+';
+            start = 1;
+        } else {
+            sign = '+'; // no sign specified, implied '+'
+            start = 0;
+        }
+
+        /**
+         * the expected format of the remainder of the string is:
+         * YYYY-MM-DDThh:mm:ss.SSSTZD
+         *
+         * note that we cannot use java.text.SimpleDateFormat for
+         * parsing because it can't handle years <= 0 and TZD's
+         */
+
+        int year, month, day, hour, min, sec, ms;
+        String tzID;
+        try {
+            // year (YYYY)
+            year = Integer.parseInt(text.substring(start, start + 4));
+            start += 4;
+            // delimiter '-'
+            if (text.charAt(start) != '-') {
+                return null;
+            }
+            start++;
+            // month (MM)
+            month = Integer.parseInt(text.substring(start, start + 2));
+            start += 2;
+            // delimiter '-'
+            if (text.charAt(start) != '-') {
+                return null;
+            }
+            start++;
+            // day (DD)
+            day = Integer.parseInt(text.substring(start, start + 2));
+            start += 2;
+            // delimiter 'T'
+            if (text.charAt(start) != 'T') {
+                return null;
+            }
+            start++;
+            // hour (hh)
+            hour = Integer.parseInt(text.substring(start, start + 2));
+            start += 2;
+            // delimiter ':'
+            if (text.charAt(start) != ':') {
+                return null;
+            }
+            start++;
+            // minute (mm)
+            min = Integer.parseInt(text.substring(start, start + 2));
+            start += 2;
+            // delimiter ':'
+            if (text.charAt(start) != ':') {
+                return null;
+            }
+            start++;
+            // second (ss)
+            sec = Integer.parseInt(text.substring(start, start + 2));
+            start += 2;
+            // delimiter '.'
+            if (text.charAt(start) != '.') {
+                return null;
+            }
+            start++;
+            // millisecond (SSS)
+            ms = Integer.parseInt(text.substring(start, start + 3));
+            start += 3;
+            // time zone designator (Z or +00:00 or -00:00)
+            if (text.charAt(start) == '+' || text.charAt(start) == '-') {
+                // offset to UTC specified in the format +00:00/-00:00
+                tzID = "GMT" + text.substring(start);
+            } else if (text.substring(start).equals("Z")) {
+                tzID = "GMT";
+            } else {
+                // invalid time zone designator
+                return null;
+            }
+        } catch (IndexOutOfBoundsException e) {
+            return null;
+        } catch (NumberFormatException e) {
+            return null;
+        }
+
+        // very slow
+TimeZone tz = TimeZone.getTimeZone(tzID);
+        // the timezone is not modified, so we can cache it
+//        TimeZone tz = getImmutableTimeZone(tzID);
+
+        // verify id of returned time zone (getTimeZone defaults to "GMT")
+        if (!tz.getID().equals(tzID)) {
+            // invalid time zone
+            return null;
+        }
+
+        // initialize Calendar object
+        Calendar cal = Calendar.getInstance(tz);
+        cal.setLenient(false);
+        // year and era
+        if (sign == '-' || year == 0) {
+            // not CE, need to set era (BCE) and adjust year
+            cal.set(Calendar.YEAR, year + 1);
+            cal.set(Calendar.ERA, GregorianCalendar.BC);
+        } else {
+            cal.set(Calendar.YEAR, year);
+            cal.set(Calendar.ERA, GregorianCalendar.AD);
+        }
+        // month (0-based!)
+        cal.set(Calendar.MONTH, month - 1);
+        // day of month
+        cal.set(Calendar.DAY_OF_MONTH, day);
+        // hour
+        cal.set(Calendar.HOUR_OF_DAY, hour);
+        // minute
+        cal.set(Calendar.MINUTE, min);
+        // second
+        cal.set(Calendar.SECOND, sec);
+        // millisecond
+        cal.set(Calendar.MILLISECOND, ms);
+
+        try {
+            /**
+             * the following call will trigger an IllegalArgumentException
+             * if any of the set values are illegal or out of range
+             */
+            cal.getTime();
+            /**
+             * in addition check the validity of the year
+             */
+            getYear(cal);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+
+        return cal;
+    }
+
+    /**
+     * Formats a <code>Calendar</code> value into an ISO8601-compliant
+     * date/time string.
+     *
+     * @param cal the time value to be formatted into a date/time string.
+     * @return the formatted date/time string.
+     * @throws IllegalArgumentException if a <code>null</code> argument is passed
+     * or the calendar cannot be represented as defined by ISO 8601 (i.e. year
+     * with more than four digits).
+     */
+    private static String format(Calendar cal) throws IllegalArgumentException {
+        if (cal == null) {
+            throw ExceptionFactory.nullPointer();
+        }
+
+        /**
+         * the format of the date/time string is:
+         * YYYY-MM-DDThh:mm:ss.SSSTZD
+         *
+         * note that we cannot use java.text.SimpleDateFormat for
+         * formatting because it can't handle years <= 0 and TZD's
+         */
+        StringBuilder buff = new StringBuilder(24);
+        // year ([-]YYYY)
+        int year = getYear(cal);
+        if (year < 0) {
+            buff.append('-');
+            year = -year;
+        }
+        appendZeroPaddedInt(buff, year, 4);
+        buff.append('-');
+        // month (MM)
+        appendZeroPaddedInt(buff, cal.get(Calendar.MONTH) + 1, 2);
+        buff.append('-');
+        // day (DD)
+        appendZeroPaddedInt(buff, cal.get(Calendar.DAY_OF_MONTH), 2);
+        buff.append('T');
+        // hour (hh)
+        appendZeroPaddedInt(buff, cal.get(Calendar.HOUR_OF_DAY), 2);
+        buff.append(':');
+        // minute (mm)
+        appendZeroPaddedInt(buff, cal.get(Calendar.MINUTE), 2);
+        buff.append(':');
+        // second (ss)
+        appendZeroPaddedInt(buff, cal.get(Calendar.SECOND), 2);
+        buff.append('.');
+        // millisecond (SSS)
+        appendZeroPaddedInt(buff, cal.get(Calendar.MILLISECOND), 3);
+        // time zone designator (Z or +00:00 or -00:00)
+        TimeZone tz = cal.getTimeZone();
+        // determine offset of timezone from UTC (incl. daylight saving)
+        int offset = tz.getOffset(cal.getTimeInMillis());
+        if (offset != 0) {
+            int hours = Math.abs((offset / (60 * 1000)) / 60);
+            int minutes = Math.abs((offset / (60 * 1000)) % 60);
+            buff.append(offset < 0 ? '-' : '+');
+            appendZeroPaddedInt(buff, hours, 2);
+            buff.append(':');
+            appendZeroPaddedInt(buff, minutes, 2);
+        } else {
+            buff.append('Z');
+        }
+        return buff.toString();
+    }
+
+    /**
+     * Returns the astronomical year of the given calendar.
+     *
+     * @param cal a calendar instance.
+     * @return the astronomical year.
+     * @throws IllegalArgumentException if calendar cannot be represented as
+     *                                  defined by ISO 8601 (i.e. year with more
+     *                                  than four digits).
+     */
+    private static int getYear(Calendar cal) throws IllegalArgumentException {
+        // determine era and adjust year if necessary
+        int year = cal.get(Calendar.YEAR);
+        if (cal.isSet(Calendar.ERA)
+                && cal.get(Calendar.ERA) == GregorianCalendar.BC) {
+            /**
+             * calculate year using astronomical system:
+             * year n BCE => astronomical year -n + 1
+             */
+            year = 0 - year + 1;
+        }
+
+        if (year > 9999 || year < -9999) {
+            throw ExceptionFactory.illegalArgument("Calendar has more than four " +
+                    "year digits, cannot be formatted as ISO8601: {0}", year);
+        }
+        return year;
+    }
+
+    /**
+     * Appends a zero-padded number to the given string buffer.
+     * This is an internal helper method which doesn't perform any
+     * validation on the given arguments.
+     *
+     * @param buff the buffer to append to
+     * @param n number to append (positive)
+     * @param precision number of digits to append (only 2-4 are supported)
+     */
+    private static void appendZeroPaddedInt(StringBuilder buff, int n, int precision) {
+        if (n < 100) {
+            if (precision > 2) {
+                buff.append('0');
+                if (precision > 3 && n < 1000) {
+                    buff.append('0');
+                }
+            }
+            if (n < 10) {
+                buff.append('0');
+            }
+        }
+        buff.append(n);
+    }
+
+}

Copied: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/ExceptionFactory.java (from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ExceptionFactory.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/ExceptionFactory.java?p2=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/ExceptionFactory.java&p1=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ExceptionFactory.java&r1=928437&r2=932959&rev=932959&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ExceptionFactory.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/ExceptionFactory.java Sun Apr 11 17:52:52 2010
@@ -14,14 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.j3;
+package org.apache.jackrabbit.j3.util;
 
 import java.text.MessageFormat;
+import java.util.ConcurrentModificationException;
 import java.util.HashMap;
+import java.util.NoSuchElementException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceException;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
+import javax.jcr.security.AccessControlException;
+import org.apache.jackrabbit.j3.mc.McException;
 
 /**
- * A exception factory.
+ * An exception factory.
  */
 public class ExceptionFactory {
 
@@ -44,4 +54,103 @@ public class ExceptionFactory {
         message = MessageFormat.format(message, (Object[]) params);
         return message + " [" + errorCode + "-" + Constants.FULL_VERSION + "]";
     }
+
+    static String format(String message, Object... params) {
+        if (params != null) {
+            message = MessageFormat.format(message, params);
+        }
+        return message + " [" + Constants.FULL_VERSION + "]";
+    }
+
+    public static <E extends Exception> E exception(Class<E> e, Throwable cause, String message, Object... params) throws E {
+        String msg;
+        if (params != null && params.length > 0) {
+            msg = format(message, params);
+        } else {
+            msg = message;
+        }
+        E i;
+        try {
+            i = e.getConstructor(String.class).newInstance(msg);
+        } catch (Exception e1) {
+            throw new RuntimeException("Error building " + e + ": " + msg, cause);
+        }
+        if (cause != null) {
+            i.initCause(cause);
+        }
+        throw i;
+    }
+
+    public static RepositoryException repository(String message, Object... params) throws RepositoryException {
+        throw exception(RepositoryException.class, null, message, params);
+    }
+
+    public static RepositoryException repository(Throwable cause, String message, Object... params) throws RepositoryException {
+        throw exception(RepositoryException.class, cause, message, params);
+    }
+
+    public static AccessControlException accessControl(String message, Object... params) throws AccessControlException {
+        throw exception(AccessControlException.class, null, message, params);
+    }
+
+    public static UnsupportedOperationException unsupportedOperation() {
+        throw exception(UnsupportedOperationException.class, null, "");
+    }
+
+    public static RuntimeException runtime(Exception e) {
+        throw exception(RuntimeException.class, e, e.getMessage());
+    }
+
+    public static IllegalArgumentException illegalArgument(String message, Object... params) {
+        throw exception(IllegalArgumentException.class, null, message, params);
+    }
+
+    public static NamespaceException namespace(String message, Object... params) throws NamespaceException {
+        throw exception(NamespaceException.class, null, message, params);
+    }
+
+    public static ValueFormatException valueFormat(String message, Object... params) throws ValueFormatException {
+        throw exception(ValueFormatException.class, null, message, params);
+    }
+
+    public static IllegalStateException illegalState(String message, Object... params) {
+        throw exception(IllegalStateException.class, null, message, params);
+    }
+
+    public static NullPointerException nullPointer() {
+        throw exception(NullPointerException.class, null, "");
+    }
+
+    public static PathNotFoundException pathNotFound(String message, Object... params) throws PathNotFoundException {
+        throw exception(PathNotFoundException.class, null, message, params);
+    }
+
+    public static InvalidItemStateException invalidItemState(String message, Object... params) throws InvalidItemStateException {
+        throw exception(InvalidItemStateException.class, null, message, params);
+    }
+
+    public static LockException lock(String message, Object... params) throws LockException {
+        throw exception(LockException.class, null, message, params);
+    }
+
+    public static McException mcException(Exception e) {
+        throw exception(McException.class, e, e.getMessage());
+    }
+
+    public static McException mcException(String message, Object... params) throws McException {
+        throw exception(McException.class, null, message, params);
+    }
+
+    public static LoginException login() throws LoginException {
+        throw exception(LoginException.class, null, "");
+    }
+
+    public static ConcurrentModificationException concurrentModification() {
+        throw exception(ConcurrentModificationException.class, null, "");
+    }
+
+    public static NoSuchElementException noSuchElement() {
+        throw exception(NoSuchElementException.class, null, "");
+    }
+
 }

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LobStore.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.j3.RepositoryImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+/**
+ * A mechanism to store large objects.
+ */
+public class LobStore {
+
+    private final RepositoryImpl rep;
+
+    public LobStore(RepositoryImpl rep) {
+        this.rep = rep;
+    }
+
+    public InputStream getInputStream(String ref) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Val createValue(InputStream in) throws RepositoryException {
+        try {
+            int min = getMinRecordLength();
+            int maxMemorySize = min - 1;
+            byte[] buffer = new byte[maxMemorySize];
+            int pos = 0, len = maxMemorySize;
+            try {
+                while (pos < maxMemorySize) {
+                    int l = in.read(buffer, pos, len);
+                    if (l < 0) {
+                        break;
+                    }
+                    pos += l;
+                    len -= l;
+                }
+            } catch (IOException e) {
+                throw ExceptionFactory.repository(e, "Could not read from stream");
+            }
+            if (pos < maxMemorySize) {
+                // shrink the buffer
+                byte[] data = new byte[pos];
+                System.arraycopy(buffer, 0, data, 0, pos);
+                return Val.get(data);
+            } else {
+                // a few bytes are already read, need to re-build the input stream
+                InputStream seq = new SequenceInputStream(new ByteArrayInputStream(buffer, 0, pos), in);
+                String ref = create(seq);
+                return Val.get(Val.TYPE_BINARY_REFERENCE, ref);
+            }
+        } finally {
+            try {
+                in.close();
+            } catch (IOException e) {
+                throw ExceptionFactory.repository(e, "Could not close stream");
+            }
+        }
+    }
+
+    private int getMinRecordLength() {
+        return Integer.MAX_VALUE;
+    }
+
+    private String create(InputStream stream) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public boolean isStored(Val value) {
+        if (value.getType() == PropertyType.BINARY) {
+            return true;
+        } else if (value.getType() == Val.TYPE_BINARY_REFERENCE) {
+            // TODO check if stored
+            return true;
+        }
+        return false;
+    }
+
+    public long getLength(Val value) {
+        String s = value.getString();
+        try {
+            return Long.parseLong(s.substring(s.lastIndexOf(':')));
+        } catch (Exception e) {
+            throw ExceptionFactory.illegalArgument("Invalid binary reference: {0}", s);
+        }
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Log.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Log.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Log.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/Log.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.observation.EventListener;
+
+/**
+ * The method call logger utility.
+ */
+public class Log {
+
+    public static final Log DEFAULT = new Log();
+
+    private static final HashMap<Class<?>, String> PREFIX_MAP = new HashMap<Class<?>, String>();
+    private static final WeakIdentityHashMap<LogObject, String> OBJ_MAP = new WeakIdentityHashMap<LogObject, String>();
+    private static int nextId;
+    public boolean debug;
+
+    public Log() {
+    }
+
+    private void log(String message) {
+        if (message != null && debug) {
+            System.out.println(message);
+        }
+    }
+
+    public void code(LogObject obj, String method) {
+        if (debug) {
+            log(format(obj, method));
+        }
+    }
+
+    public void codeAssign(LogObject newObj, LogObject obj, String method) {
+        if (debug) {
+            logCodeAssign(newObj, obj, method, new Object[] { });
+        }
+    }
+
+    public void codeAssign(LogObject newObj, LogObject obj, String method, Object a1) {
+        if (debug) {
+            logCodeAssign(newObj, obj, method, new Object[] { a1 });
+        }
+    }
+
+    public void codeAssign(LogObject newObj, LogObject obj, String method, Object a1, Object a2) {
+        if (debug) {
+            logCodeAssign(newObj, obj, method, new Object[] { a1, a2 });
+        }
+    }
+
+    public void codeAssign(LogObject newObj, LogObject obj, String method, Object... args) {
+        if (debug) {
+            logCodeAssign(newObj, obj, method, args);
+        }
+    }
+
+    private void logCodeAssign(LogObject newObj, LogObject obj, String method, Object... args) {
+        if (!OBJ_MAP.containsKey(newObj)) {
+            String call = format(obj, method, args);
+            codeAssign(newObj, call);
+        }
+    }
+
+    public void code(LogObject obj, String method, Object a1) {
+        if (debug) {
+            logCode(obj, method, new Object[]{a1});
+        }
+    }
+
+    public void code(LogObject obj, String method, Object a1, Object a2) {
+        if (debug) {
+            logCode(obj, method, new Object[]{a1, a2});
+        }
+    }
+
+    public void code(LogObject obj, String method, Object... args) {
+        if (debug) {
+            logCode(obj, method, args);
+        }
+    }
+
+    private void logCode(LogObject obj, String method, Object... args) {
+        log(format(obj, method, args));
+    }
+
+
+    private String format(LogObject obj, String method) {
+        return getInstanceName(obj) + "." + method + "();";
+    }
+
+    private void codeAssign(LogObject obj, String call) {
+        log(formatAssign(obj, call));
+    }
+
+    private String formatAssign(LogObject obj, String call) {
+        return getClass(obj) + " " + getInstanceName(obj) + " = " + call;
+    }
+
+    private String getClass(LogObject obj) {
+        Class<?> clazz = obj.getClass();
+        for (Class<?> c : clazz.getInterfaces()) {
+            if (c.getName().startsWith("javax.jcr.")) {
+                return c.getSimpleName();
+            }
+        }
+        throw ExceptionFactory.illegalArgument("Not a javax.jcr class", obj);
+    }
+
+    private String format(LogObject obj, String method, Object... args) {
+        if (!debug) {
+            return null;
+        }
+        if (obj == null) {
+            return method + formatParameters(args);
+        }
+        return getInstanceName(obj) + "." + method + formatParameters(args);
+    }
+
+    private String formatParameters(Object... args) {
+        StringBuffer buff = new StringBuffer("(");
+        int i = 0;
+        for (Object a : args) {
+            if (i++ > 0) {
+                buff.append(", ");
+            }
+            buff.append(format(a));
+        }
+        return buff.append(");").toString();
+    }
+
+    private String format(Object a) {
+        if (a == null) {
+            return "null";
+        } else if (a instanceof LogObject) {
+            return getInstanceName((LogObject) a);
+        } else if (a instanceof String) {
+            return '\"' + StringUtils.javaEncode(a.toString()) + '\"';
+        } else if (a instanceof Integer) {
+            return a.toString();
+        } else if (a instanceof Long) {
+            return a + "L";
+        } else if (a instanceof Boolean) {
+            return a.toString();
+        } else if (a instanceof Double) {
+            return a + "d";
+        } else if (a instanceof Calendar) {
+            Calendar c = (Calendar) a;
+            return DateUtils.class.getName() + ".convertStringToCalendar(" + format(DateUtils.convertCalendarToString(c)) + ")";
+        } else if (a instanceof char[]) {
+            return format(new String((char[]) a)) + ".toCharArray()";
+        } else if (a instanceof Float) {
+            return a + "f";
+        } else if (a.getClass().isArray()) {
+            Class<?> c = a.getClass().getComponentType();
+            StringBuilder buff = new StringBuilder();
+            buff.append("new ").append(c.getName()).append("[] {");
+            int i = 0;
+            for (Object o : (Object[]) a) {
+                if (i++ > 0) {
+                    buff.append(", ");
+                }
+                buff.append(format(o));
+            }
+            return buff.append('}').toString();
+        } else if (a instanceof Map<?, ?>) {
+            StringBuilder buff = new StringBuilder("new HashMap() {{");
+            Map<?, ?> m = (Map<?, ?>) a;
+            for (Map.Entry<?, ?> e : m.entrySet()) {
+                buff.append("put(").append(format(e.getKey())).append(", ").append(format(e.getValue())).append(");");
+            }
+            buff.append("}}");
+            return buff.toString();
+        } else if (a instanceof EventListener) {
+            return "new " + a.getClass().getName() + "()";
+        } else if (a instanceof SimpleCredentials) {
+            SimpleCredentials sc = (SimpleCredentials) a;
+            return "new SimpleCredentials(" + format(sc.getUserID()) + ", " + format(sc.getPassword()) + ")";
+        } else {
+            throw ExceptionFactory.illegalArgument("Unsupported class {0}", a.getClass().getName());
+        }
+    }
+
+    private static synchronized String getInstanceName(LogObject obj) {
+        String n = OBJ_MAP.get(obj);
+        if (n != null) {
+            return n;
+        }
+        String prefix = PREFIX_MAP.get(obj.getClass());
+        if (prefix == null) {
+            prefix = obj.getClass().getSimpleName().toLowerCase();
+            for (int i = 1; i < prefix.length(); i++) {
+                String p = prefix.substring(0, i);
+                if (!PREFIX_MAP.containsValue(p)) {
+                    PREFIX_MAP.put(obj.getClass(), p);
+                    prefix = p;
+                    break;
+                }
+            }
+        }
+        n = prefix + nextId++;
+        OBJ_MAP.put(obj, n);
+        return n;
+    }
+
+/*
+
+Find & replace:
+
+,\R
+,
+
+\)\R
+\)
+
+public (.*) (.*)\((.*) (.*), (.*) (.*), (.*) (.*), (.*) (.*)\)(.*) \{(\R.*)(// TODO Auto-generated method stub)
+public $1 $2\($3 $4, $5 $6, $7 $8, $9 $10\)$11 \{$13log.code\(this, "$2", $4, $6, $8, $10\);// TODO
+
+public (.*) (.*)\((.*) (.*), (.*) (.*), (.*) (.*)\)(.*) \{(\R.*)(// TODO Auto-generated method stub)
+public $1 $2\($3 $4, $5 $6, $7 $8\)$9 \{$10log.code\(this, "$2", $4, $6, $8\);// TODO
+
+public (.*) (.*)\((.*) (.*), (.*) (.*)\)(.*) \{(\R.*)(// TODO Auto-generated method stub)
+public $1 $2\($3 $4, $5 $6\)$7 \{$8log.code\(this, "$2", $4, $6\);// TODO
+
+public (.*) (.*)\((.*) (.*)\)(.*) \{(\R.*)(// TODO Auto-generated method stub)
+public $1 $2\($3 $4\)$5 \{$6log.code\(this, "$2", $4\);// TODO
+
+public (.*) (.*)\(\)(.*) \{(\R.*)(// TODO Auto-generated method stub)
+public $1 $2\(\)$3 \{$4log.code\(this, "$2"\);// TODO
+
+;// TODO(\R)
+;$1// TODO$1
+
+*/
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LogObject.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LogObject.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LogObject.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/LogObject.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+/**
+ * A class that implements this interface can log method calls.
+ */
+public interface LogObject {
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/StringUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/StringUtils.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/StringUtils.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/StringUtils.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+/**
+ * Some string utility methods.
+ */
+public class StringUtils {
+
+    public static String javaEncode(String s) {
+        StringBuilder buff = new StringBuilder(s.length());
+        for (int i = 0; i < s.length(); i++) {
+            int ch = s.charAt(i);
+            int index = "\'\"\\\t\n\f\r".indexOf(ch);
+            if (index >= 0) {
+                buff.append('\\').append("\'\"\\tnfr".charAt(index));
+            } else if (ch >= ' ' && (ch < 0x80)) {
+                buff.append((char) ch);
+            } else {
+                buff.append("\\u");
+                buff.append(Integer.toHexString(0x10000 | ch).substring(1));
+            }
+        }
+        return buff.toString();
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/WeakIdentityHashMap.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/WeakIdentityHashMap.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/WeakIdentityHashMap.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/util/WeakIdentityHashMap.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.util;
+
+import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This hash map uses weak references, so that elements that are no longer
+ * referenced elsewhere can be garbage collected. It also uses object identity
+ * to compare keys.
+ *
+ * @param <K> the keys
+ * @param <V> the value
+ */
+public class WeakIdentityHashMap<K, V> implements Map<K, V> {
+
+    private static final int MAX_LOAD = 90;
+    private static final WeakReference<Object> DELETED_KEY =
+        new WeakReference<Object>(null);
+    private int mask, len, size, deletedCount, level;
+    private int maxSize, minSize, maxDeleted;
+    private WeakReference<K>[] keys;
+    private V[] values;
+
+    public WeakIdentityHashMap() {
+        reset(2);
+    }
+
+    public int size() {
+        return size;
+    }
+
+    private void checkSizePut() {
+        if (deletedCount > size) {
+            rehash(level);
+        }
+        if (size + deletedCount >= maxSize) {
+            rehash(level + 1);
+        }
+    }
+
+    private void checkSizeRemove() {
+        if (size < minSize && level > 0) {
+            rehash(level - 1);
+        } else if (deletedCount > maxDeleted) {
+            rehash(level);
+        }
+    }
+
+    private int getIndex(Object key) {
+        return System.identityHashCode(key) & mask;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void reset(int newLevel) {
+        minSize = size * 3 / 4;
+        size = 0;
+        level = newLevel;
+        len = 2 << level;
+        mask = len - 1;
+        maxSize = (int) (len * MAX_LOAD / 100L);
+        deletedCount = 0;
+        maxDeleted = 20 + len / 2;
+        keys = new WeakReference[len];
+        values = (V[]) new Object[len];
+    }
+
+    public V put(K key, V value) {
+        checkSizePut();
+        int index = getIndex(key);
+        int plus = 1;
+        int deleted = -1;
+        do {
+            WeakReference<K> k = keys[index];
+            if (k == null) {
+                // found an empty record
+                if (deleted >= 0) {
+                    index = deleted;
+                    deletedCount--;
+                }
+                size++;
+                keys[index] = new WeakReference<K>(key);
+                values[index] = value;
+                return null;
+            } else if (k == DELETED_KEY) {
+                if (deleted < 0) {
+                    // found the first deleted record
+                    deleted = index;
+                }
+            } else {
+                Object r = k.get();
+                if (r == null) {
+                    delete(index);
+                } else if (r == key) {
+                    // update existing
+                    V old = values[index];
+                    values[index] = value;
+                    return old;
+                }
+            }
+            index = (index + plus++) & mask;
+        } while(plus <= len);
+        throw new RuntimeException("Hashmap is full");
+    }
+
+    public V remove(Object key) {
+        checkSizeRemove();
+        int index = getIndex(key);
+        int plus = 1;
+        do {
+            WeakReference<K> k = keys[index];
+            if (k == null) {
+                // found an empty record
+                return null;
+            } else if (k == DELETED_KEY) {
+                // continue
+            } else {
+                Object r = k.get();
+                if (r == null) {
+                    delete(index);
+                } else if (r == key) {
+                    // found the record
+                    V old = values[index];
+                    delete(index);
+                    return old;
+                }
+            }
+            index = (index + plus++) & mask;
+            k = keys[index];
+        } while(plus <= len);
+        // not found
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void delete(int index) {
+        keys[index] = (WeakReference<K>) DELETED_KEY;
+        values[index] = null;
+        deletedCount++;
+        size--;
+    }
+
+    private void rehash(int newLevel) {
+        WeakReference<K>[] oldKeys = keys;
+        V[] oldValues = values;
+        reset(newLevel);
+        for (int i = 0; i < oldKeys.length; i++) {
+            WeakReference<K> k = oldKeys[i];
+            if (k != null && k != DELETED_KEY) {
+                K key = k.get();
+                if (key != null) {
+                    put(key, oldValues[i]);
+                }
+            }
+        }
+    }
+
+    public V get(Object key) {
+        int index = getIndex(key);
+        int plus = 1;
+        do {
+            WeakReference<K> k = keys[index];
+            if (k == null) {
+                return null;
+            } else if (k == DELETED_KEY) {
+                // continue
+            } else {
+                Object r = k.get();
+                if (r == null) {
+                    delete(index);
+                } else if (r == key) {
+                    return values[index];
+                }
+            }
+            index = (index + plus++) & mask;
+        } while(plus <= len);
+        return null;
+    }
+
+    public void clear() {
+        reset(2);
+    }
+
+    public boolean containsKey(Object key) {
+        return get(key) != null;
+    }
+
+    public boolean containsValue(Object value) {
+        if (value == null) {
+            return false;
+        }
+        for (V item: values) {
+            if (value.equals(item)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Set<java.util.Map.Entry<K, V>> entrySet() {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean isEmpty() {
+        return size == 0;
+    }
+
+    public Set<K> keySet() {
+        throw new UnsupportedOperationException();
+    }
+
+    public void putAll(Map< ? extends K, ? extends V> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Collection<V> values() {
+        throw new UnsupportedOperationException();
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionHistoryImpl.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionHistoryImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionHistoryImpl.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.version;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.NodeIterator;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.LabelExistsVersionException;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionException;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.NodeState;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class VersionHistoryImpl extends NodeImpl implements VersionHistory {
+
+    VersionHistoryImpl(NodeImpl parent, NodeState state) {
+        super(parent, state, null);
+    }
+
+    public void addVersionLabel(String versionName, String label, boolean moveLabel)
+            throws LabelExistsVersionException, VersionException, RepositoryException {
+        log.code(this, "addVersionLabel", versionName, label, moveLabel);
+        // TODO
+
+    }
+
+    public NodeIterator getAllFrozenNodes() throws RepositoryException {
+        log.code(this, "getAllFrozenNodes");
+        // TODO
+        return null;
+    }
+
+    public NodeIterator getAllLinearFrozenNodes() throws RepositoryException {
+        log.code(this, "getAllLinearFrozenNodes");
+        // TODO
+        return null;
+    }
+
+    public VersionIterator getAllLinearVersions() throws RepositoryException {
+        log.code(this, "getAllLinearVersions");
+        // TODO
+        return null;
+    }
+
+    public VersionIterator getAllVersions() throws RepositoryException {
+        log.code(this, "getAllVersions");
+        // TODO
+        return null;
+    }
+
+    public Version getRootVersion() throws RepositoryException {
+        log.code(this, "getRootVersion");
+        // TODO
+        return null;
+    }
+
+    public Version getVersion(String versionName) throws VersionException, RepositoryException {
+        log.code(this, "getVersion", versionName);
+        // TODO
+        return null;
+    }
+
+    public Version getVersionByLabel(String label) throws VersionException, RepositoryException {
+        log.code(this, "getVersionByLabel", label);
+        // TODO
+        return null;
+    }
+
+    public String[] getVersionLabels() throws RepositoryException {
+        log.code(this, "getVersionLabels");
+        // TODO
+        return null;
+    }
+
+    public String[] getVersionLabels(Version version) throws VersionException, RepositoryException {
+        log.code(this, "getVersionLabels", version);
+        // TODO
+        return null;
+    }
+
+    public String getVersionableIdentifier() throws RepositoryException {
+        log.code(this, "getVersionableIdentifier");
+        // TODO
+        return null;
+    }
+
+    public String getVersionableUUID() throws RepositoryException {
+        log.code(this, "getVersionableUUID");
+        // TODO
+        return null;
+    }
+
+    public boolean hasVersionLabel(String label) throws RepositoryException {
+        log.code(this, "hasVersionLabel", label);
+        // TODO
+        return false;
+    }
+
+    public boolean hasVersionLabel(Version version, String label) throws VersionException, RepositoryException {
+        log.code(this, "hasVersionLabel", version, label);
+        // TODO
+        return false;
+    }
+
+    public void removeVersion(String versionName) throws ReferentialIntegrityException, AccessDeniedException,
+            UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+        log.code(this, "removeVersion", versionName);
+        // TODO
+
+    }
+
+    public void removeVersionLabel(String label) throws VersionException, RepositoryException {
+        log.code(this, "removeVersionLabel", label);
+        // TODO
+
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionImpl.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionImpl.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.version;
+
+import java.util.Calendar;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.NodeState;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class VersionImpl extends NodeImpl implements Version {
+
+    protected VersionImpl(NodeImpl parent, NodeState state) {
+        super(parent, state, null);
+        // TODO Auto-generated constructor stub
+    }
+
+    public VersionHistory getContainingHistory() throws RepositoryException {
+        log.code(this, "getContainingHistory");
+        // TODO
+        return null;
+    }
+
+    public Calendar getCreated() throws RepositoryException {
+        log.code(this, "getCreated");
+        // TODO
+        return null;
+    }
+
+    public Node getFrozenNode() throws RepositoryException {
+        log.code(this, "getFrozenNode");
+        // TODO
+        return null;
+    }
+
+    public Version getLinearPredecessor() throws RepositoryException {
+        log.code(this, "getLinearPredecessor");
+        // TODO
+        return null;
+    }
+
+    public Version getLinearSuccessor() throws RepositoryException {
+        log.code(this, "getLinearSuccessor");
+        // TODO
+        return null;
+    }
+
+    public Version[] getPredecessors() throws RepositoryException {
+        log.code(this, "getPredecessors");
+        // TODO
+        return null;
+    }
+
+    public Version[] getSuccessors() throws RepositoryException {
+        log.code(this, "getSuccessors");
+        // TODO
+        return null;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionIteratorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionIteratorImpl.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionIteratorImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionIteratorImpl.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.version;
+
+import java.util.Collection;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionIterator;
+import org.apache.jackrabbit.j3.RangeIteratorImpl;
+import org.apache.jackrabbit.j3.util.Log;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class VersionIteratorImpl extends RangeIteratorImpl<Version> implements VersionIterator {
+
+    protected VersionIteratorImpl(Collection<Version> coll, long size, Log log) {
+        super(coll.iterator(), size, log);
+    }
+
+    public Version nextVersion() {
+        log.code(this, "nextVersion");
+        return goNext();
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionManagerImpl.java?rev=932959&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionManagerImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/version/VersionManagerImpl.java Sun Apr 11 17:52:52 2010
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j3.version;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.MergeException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionException;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionManager;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class VersionManagerImpl implements VersionManager, LogObject {
+
+    private final Log log;
+
+    public VersionManagerImpl(Log log) {
+        this.log = log;
+    }
+
+    public void cancelMerge(String absPath, Version version) throws VersionException, InvalidItemStateException,
+            UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "cancelMerge", absPath, version);
+        // TODO
+
+    }
+
+    public Version checkin(String absPath) throws VersionException, UnsupportedRepositoryOperationException,
+            InvalidItemStateException, LockException, RepositoryException {
+        log.code(this, "checkin", absPath);
+        // TODO
+        return null;
+    }
+
+    public void checkout(String absPath) throws UnsupportedRepositoryOperationException, LockException,
+            RepositoryException {
+        log.code(this, "checkout", absPath);
+        // TODO
+
+    }
+
+    public Version checkpoint(String absPath) throws VersionException, UnsupportedRepositoryOperationException,
+            InvalidItemStateException, LockException, RepositoryException {
+        log.code(this, "checkpoint", absPath);
+        // TODO
+        return null;
+    }
+
+    public Node createActivity(String title) throws UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "createActivity", title);
+        // TODO
+        return null;
+    }
+
+    public Node createConfiguration(String absPath) throws UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "createConfiguration", absPath);
+        // TODO
+        return null;
+    }
+
+    public void doneMerge(String absPath, Version version) throws VersionException, InvalidItemStateException,
+            UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "doneMerge", absPath, version);
+        // TODO
+
+    }
+
+    public Node getActivity() throws UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "getActivity");
+        // TODO
+        return null;
+    }
+
+    public Version getBaseVersion(String absPath) throws UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "getBaseVersion", absPath);
+        // TODO
+        return null;
+    }
+
+    public VersionHistory getVersionHistory(String absPath) throws UnsupportedRepositoryOperationException,
+            RepositoryException {
+        log.code(this, "getVersionHistory", absPath);
+        // TODO
+        return null;
+    }
+
+    public boolean isCheckedOut(String absPath) throws RepositoryException {
+        log.code(this, "isCheckedOut", absPath);
+        // TODO
+        return false;
+    }
+
+    public NodeIterator merge(Node activityNode) throws VersionException, AccessDeniedException, MergeException,
+            LockException, InvalidItemStateException, RepositoryException {
+        log.code(this, "merge", activityNode);
+        // TODO
+        return null;
+    }
+
+    public NodeIterator merge(String absPath, String srcWorkspace, boolean bestEffort) throws NoSuchWorkspaceException,
+            AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException {
+        log.code(this, "merge", absPath, srcWorkspace, bestEffort);
+        // TODO
+        return null;
+    }
+
+    public NodeIterator merge(String absPath, String srcWorkspace, boolean bestEffort, boolean isShallow)
+            throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException,
+            InvalidItemStateException, RepositoryException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void removeActivity(Node activityNode) throws UnsupportedRepositoryOperationException, VersionException,
+            RepositoryException {
+        log.code(this, "removeActivity", activityNode);
+        // TODO
+
+    }
+
+    public void restore(Version[] versions, boolean removeExisting) throws ItemExistsException,
+            UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException,
+            RepositoryException {
+        log.code(this, "restore", versions, removeExisting);
+        // TODO
+
+    }
+
+    public void restore(Version version, boolean removeExisting) throws VersionException, ItemExistsException,
+            InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
+        log.code(this, "restore", version, removeExisting);
+        // TODO
+
+    }
+
+    public void restore(String absPath, String versionName, boolean removeExisting) throws VersionException,
+            ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException,
+            RepositoryException {
+        log.code(this, "restore", absPath, versionName, removeExisting);
+        // TODO
+
+    }
+
+    public void restore(String absPath, Version version, boolean removeExisting) throws PathNotFoundException,
+            ItemExistsException, VersionException, ConstraintViolationException,
+            UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
+        log.code(this, "restore", absPath, version, removeExisting);
+        // TODO
+
+    }
+
+    public void restoreByLabel(String absPath, String versionLabel, boolean removeExisting) throws VersionException,
+            ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException,
+            RepositoryException {
+        log.code(this, "restoreByLabel", absPath, versionLabel, removeExisting);
+        // TODO
+
+    }
+
+    public Node setActivity(Node activity) throws UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "setActivity", activity);
+        // TODO
+        return null;
+    }
+
+}