jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r209089 [3/7] - in /incubator/jackrabbit/trunk: commons/ commons/src/java/org/apache/jackrabbit/ commons/src/java/org/apache/jackrabbit/core/ commons/src/java/org/apache/jackrabbit/name/ commons/src/java/org/apache/jackrabbit/util/ commons/...
Date Mon, 04 Jul 2005 14:52:27 GMT
Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ChildrenCollectorFilter.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ChildrenCollectorFilter.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ChildrenCollectorFilter.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ChildrenCollectorFilter.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.util;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.util.TraversingItemVisitor;
+import java.util.Collection;
+import java.util.StringTokenizer;
+
+/**
+ * <code>ChildrenCollectorFilter</code> is a utility class
+ * which can be used to 'collect' child items of a
+ * node whose names match a certain pattern. It implements the
+ * <code>ItemVisitor</code> interface.
+ */
+public class ChildrenCollectorFilter extends TraversingItemVisitor.Default {
+    static final char WILDCARD_CHAR = '*';
+    static final String OR = "|";
+
+    private final Collection children;
+    private final boolean collectNodes;
+    private final boolean collectProperties;
+    private final String namePattern;
+
+    /**
+     * Constructs a <code>ChildrenCollectorFilter</code>
+     *
+     * @param namePattern       the pattern which should be applied to the names
+     *                          of the children
+     * @param children          where the matching children should be added
+     * @param collectNodes      true, if child nodes should be collected; otherwise false
+     * @param collectProperties true, if child properties should be collected; otherwise false
+     * @param maxLevel          umber of hierarchy levels to traverse
+     *                          (e.g. 1 for direct children only, 2 for children and their children, and so on)
+     */
+    public ChildrenCollectorFilter(
+            String namePattern, Collection children,
+            boolean collectNodes, boolean collectProperties, int maxLevel) {
+        super(false, maxLevel);
+        this.namePattern = namePattern;
+        this.children = children;
+        this.collectNodes = collectNodes;
+        this.collectProperties = collectProperties;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void entering(Node node, int level)
+            throws RepositoryException {
+        if (level > 0 && collectNodes) {
+            if (matches(node.getName(), namePattern)) {
+                children.add(node);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void entering(Property property, int level)
+            throws RepositoryException {
+        if (level > 0 && collectProperties) {
+            if (matches(property.getName(), namePattern)) {
+                children.add(property);
+            }
+        }
+    }
+
+    /**
+     * Applies the name pattern against the specified name.
+     * <p/>
+     * The pattern may be a full name or a partial name with one or more
+     * wildcard characters ("*"), or a disjunction (using the "|" character
+     * to represent logical <i>OR</i>) of these. For example,
+     * <p/>
+     * <code>"jcr:*|foo:bar"</code>
+     * <p/>
+     * would match
+     * <p/>
+     * <code>"foo:bar"</code>, but also <code>"jcr:whatever"</code>.
+     *
+     * @param name the name to test the pattern with
+     * @return true if the specified name matches the pattern
+     */
+    static boolean matches(String name, String pattern) {
+        // @todo check if pattern matching conforms with spec
+        // split pattern
+        StringTokenizer st = new StringTokenizer(pattern, OR, false);
+        while (st.hasMoreTokens()) {
+            // remove leading & trailing whitespace from token
+            String token = st.nextToken().trim();
+            if (internalMatches(name, token, 0, 0)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Internal helper used to recursively match the pattern
+     *
+     * @param s       The string to be tested
+     * @param pattern The pattern
+     * @param sOff    offset within <code>s</code>
+     * @param pOff    offset within <code>pattern</code>.
+     * @return true if <code>s</code> matched pattern, else false.
+     */
+    private static boolean internalMatches(String s, String pattern, int sOff, int pOff) {
+        int pLen = pattern.length();
+        int sLen = s.length();
+
+        while (true) {
+            if (pOff >= pLen) {
+                if (sOff >= sLen) {
+                    return true;
+                } else if (s.charAt(sOff) == '[') {
+                    // check for subscript notation (e.g. "whatever[1]")
+
+                    // the entire pattern matched up to the subscript:
+                    // -> ignore the subscript
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+            if (sOff >= sLen && pattern.charAt(pOff) != WILDCARD_CHAR) {
+                return false;
+            }
+
+            // check for a '*' as the next pattern char;
+            // this is handled by a recursive call for
+            // each postfix of the name.
+            if (pattern.charAt(pOff) == WILDCARD_CHAR) {
+                if (++pOff >= pLen) {
+                    return true;
+                }
+
+                while (true) {
+                    if (internalMatches(s, pattern, sOff, pOff)) {
+                        return true;
+                    }
+                    if (sOff >= sLen) {
+                        return false;
+                    }
+                    sOff++;
+                }
+            }
+
+            if (pOff < pLen && sOff < sLen) {
+                if (pattern.charAt(pOff) != s.charAt(sOff)) {
+                    return false;
+                }
+            }
+            pOff++;
+            sOff++;
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ChildrenCollectorFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ISO8601.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ISO8601.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ISO8601.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ISO8601.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.util;
+
+import java.text.DecimalFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * The <code>ISO8601</code> 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 ISO8601 {
+    /**
+     * misc. numeric formats used in formatting
+     */
+    private static final DecimalFormat XX_FORMAT = new DecimalFormat("00");
+    private static final DecimalFormat XXX_FORMAT = new DecimalFormat("000");
+    private static final DecimalFormat XXXX_FORMAT = new DecimalFormat("0000");
+
+    /**
+     * 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
+     */
+    public static Calendar parse(String text) {
+        if (text == null) {
+            throw new IllegalArgumentException("argument can not be null");
+        }
+
+        // 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;
+        }
+
+        TimeZone tz = TimeZone.getTimeZone(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();
+        } 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
+     */
+    public static String format(Calendar cal) {
+        if (cal == null) {
+            throw new IllegalArgumentException("argument can not be null");
+        }
+
+        // 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;
+        }
+
+        /**
+         * 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
+         */
+        StringBuffer buf = new StringBuffer();
+        // year ([-]YYYY)
+        buf.append(XXXX_FORMAT.format(year));
+        buf.append('-');
+        // month (MM)
+        buf.append(XX_FORMAT.format(cal.get(Calendar.MONTH) + 1));
+        buf.append('-');
+        // day (DD)
+        buf.append(XX_FORMAT.format(cal.get(Calendar.DAY_OF_MONTH)));
+        buf.append('T');
+        // hour (hh)
+        buf.append(XX_FORMAT.format(cal.get(Calendar.HOUR_OF_DAY)));
+        buf.append(':');
+        // minute (mm)
+        buf.append(XX_FORMAT.format(cal.get(Calendar.MINUTE)));
+        buf.append(':');
+        // second (ss)
+        buf.append(XX_FORMAT.format(cal.get(Calendar.SECOND)));
+        buf.append('.');
+        // millisecond (SSS)
+        buf.append(XXX_FORMAT.format(cal.get(Calendar.MILLISECOND)));
+        // 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);
+            buf.append(offset < 0 ? '-' : '+');
+            buf.append(XX_FORMAT.format(hours));
+            buf.append(':');
+            buf.append(XX_FORMAT.format(minutes));
+        } else {
+            buf.append('Z');
+        }
+        return buf.toString();
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/ISO8601.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/IteratorHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/IteratorHelper.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/IteratorHelper.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/IteratorHelper.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.util;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeIterator;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * <code>IteratorHelper</code> is a utility class which
+ * wraps an iterator and implements the various typed iterator
+ * interfaces.
+ */
+public class IteratorHelper
+        implements NodeIterator, PropertyIterator, NodeTypeIterator {
+
+    static final long UNDETERMINED_SIZE = -1;
+
+    private final Iterator iter;
+    private long size;
+    private long pos;
+
+    /**
+     * Constructs an <code>IteratorHelper</code> which is backed
+     * by a <code>java.util.Collection</code>.
+     *
+     * @param c collection which should be iterated over.
+     */
+    public IteratorHelper(Collection c) {
+        this(c.iterator());
+        size = c.size();
+    }
+
+    /**
+     * Constructs an <code>IteratorHelper</code> which is wrapping
+     * a <code>java.util.Iterator</code>.
+     *
+     * @param iter iterator which should be wrapped.
+     */
+    public IteratorHelper(Iterator iter) {
+        this.iter = iter;
+        pos = 0;
+        size = UNDETERMINED_SIZE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void skip(long skipNum) {
+        while (skipNum-- > 0) {
+            next();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getSize() {
+        return size;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getPosition() {
+        return pos;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasNext() {
+        return iter.hasNext();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object next() {
+        // all typed nextXXX methods should
+        // delegate to this method
+        Object obj = iter.next();
+        // increment position
+        pos++;
+        return obj;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void remove() {
+        iter.remove();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Node nextNode() {
+        return (Node) next();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property nextProperty() {
+        return (Property) next();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NodeType nextNodeType() {
+        return (NodeType) next();
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/IteratorHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/LazyFileInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/LazyFileInputStream.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/LazyFileInputStream.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/LazyFileInputStream.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.util;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This Class implements an InputStream that provides the same functionality
+ * as a <code>FileInputStream</code> but opens the file by the first file access.
+ */
+public class LazyFileInputStream extends InputStream {
+
+    /**
+     * the underlying input stream
+     */
+    private FileInputStream in;
+
+    /**
+     * FileDescriptor to use
+     */
+    private FileDescriptor fd;
+
+    /**
+     * File to use
+     */
+    private File file;
+
+    /**
+     * Creates a new <code>LazyFileInputStream</code> for the given file. If the
+     * file is unreadably, a FileNotFoundException is thrown.
+     *
+     * @param file
+     * @throws java.io.FileNotFoundException
+     */
+    public LazyFileInputStream(File file)
+            throws FileNotFoundException {
+        // check if we can read from the file
+        if (!file.canRead()) {
+            throw new FileNotFoundException(file.getPath());
+        }
+        this.file = file;
+    }
+
+    /**
+     * Creates a new <code>LazyFileInputStream</code> for the given file
+     * desciptor.
+     *
+     * @param fdObj
+     */
+    public LazyFileInputStream(FileDescriptor fdObj) {
+        this.fd = fdObj;
+    }
+
+    /**
+     * Creates a new <code>LazyFileInputStream</code> for the given file. If the
+     * file is unreadably, a FileNotFoundException is thrown.
+     *
+     * @param name
+     * @throws java.io.FileNotFoundException
+     */
+    public LazyFileInputStream(String name) throws FileNotFoundException {
+        this(new File(name));
+    }
+
+    /**
+     * Opens the underlying file input stream in neccessairy.
+     * @throws java.io.IOException
+     */
+    public void open() throws IOException {
+        if (in == null) {
+            if (file != null) {
+                in = new FileInputStream(file);
+            } else if (fd != null) {
+                in = new FileInputStream(fd);
+            } else {
+                throw new IOException("Stream already closed.");
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int read() throws IOException {
+        open();
+        return in.read();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int available() throws IOException {
+        open();
+        return in.available();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void close() throws IOException {
+        if (in != null) {
+            in.close();
+        }
+        in = null;
+        file = null;
+        fd = null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void reset() throws IOException {
+        open();
+        in.reset();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean markSupported() {
+        try {
+            open();
+            return in.markSupported();
+        } catch (IOException e) {
+            throw new IllegalStateException(e.toString());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void mark(int readlimit) {
+        try {
+            open();
+            in.mark(readlimit);
+        } catch (IOException e) {
+            throw new IllegalStateException(e.toString());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long skip(long n) throws IOException {
+       open();
+       return in.skip(n);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int read(byte[] b) throws IOException {
+        open();
+        return in.read(b);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int read(byte[] b, int off, int len) throws IOException {
+        open();
+        return in.read(b, off, len);
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/LazyFileInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/Text.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/Text.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/Text.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/Text.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.util;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+
+/**
+ * This Class provides some text related utilities
+ */
+public class Text {
+
+    /**
+     * Hidden constructor.
+     */
+    private Text() {
+    }
+
+    /**
+     * used for the md5
+     */
+    public static final char[] hexTable = "0123456789abcdef".toCharArray();
+
+    /**
+     * Calculate an MD5 hash of the string given.
+     *
+     * @param data the data to encode
+     * @param enc  the character encoding to use
+     * @return a hex encoded string of the md5 digested input
+     */
+    public static String md5(String data, String enc)
+            throws UnsupportedEncodingException {
+        try {
+            return digest("MD5", data.getBytes(enc));
+        } catch (NoSuchAlgorithmException e) {
+            throw new InternalError("MD5 digest not available???");
+        }
+    }
+
+    /**
+     * Calculate an MD5 hash of the string given using 'utf-8' encoding.
+     *
+     * @param data the data to encode
+     * @return a hex encoded string of the md5 digested input
+     */
+    public static String md5(String data) {
+        try {
+            return md5(data, "utf-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new InternalError("UTF8 digest not available???");
+        }
+    }
+
+    /**
+     * Digest the plain string using the given algorithm.
+     *
+     * @param algorithm The alogrithm for the digest. This algorithm must be
+     *                  supported by the MessageDigest class.
+     * @param data      The plain text String to be digested.
+     * @param enc       The character encoding to use
+     * @return The digested plain text String represented as Hex digits.
+     * @throws java.security.NoSuchAlgorithmException     if the desired algorithm is not supported by
+     *                                      the MessageDigest class.
+     * @throws java.io.UnsupportedEncodingException if the encoding is not supported
+     */
+    public static String digest(String algorithm, String data, String enc)
+            throws NoSuchAlgorithmException, UnsupportedEncodingException {
+
+        return digest(algorithm, data.getBytes(enc));
+    }
+
+    /**
+     * Digest the plain string using the given algorithm.
+     *
+     * @param algorithm The alogrithm for the digest. This algorithm must be
+     *                  supported by the MessageDigest class.
+     * @param data      the data to digest with the given algorithm
+     * @return The digested plain text String represented as Hex digits.
+     * @throws java.security.NoSuchAlgorithmException if the desired algorithm is not supported by
+     *                                  the MessageDigest class.
+     */
+    public static String digest(String algorithm, byte[] data)
+            throws NoSuchAlgorithmException {
+
+        MessageDigest md = MessageDigest.getInstance(algorithm);
+        byte[] digest = md.digest(data);
+        StringBuffer res = new StringBuffer(digest.length * 2);
+        for (int i = 0; i < digest.length; i++) {
+            byte b = digest[i];
+            res.append(hexTable[(b >> 4) & 15]);
+            res.append(hexTable[b & 15]);
+        }
+        return res.toString();
+    }
+
+    /**
+     * returns an array of strings decomposed of the original string, split at
+     * every occurance of 'ch'. if 2 'ch' follow each other with no intermediate
+     * characters, empty "" entries are avoided.
+     *
+     * @param str the string to decompose
+     * @param ch  the character to use a split pattern
+     * @return an array of strings
+     */
+    public static String[] explode(String str, int ch) {
+        return explode(str, ch, false);
+    }
+
+    /**
+     * returns an array of strings decomposed of the original string, split at
+     * every occurance of 'ch'.
+     *
+     * @param str          the string to decompose
+     * @param ch           the character to use a split pattern
+     * @param respectEmpty if <code>true</code>, empty elements are generated
+     * @return an array of strings
+     */
+    public static String[] explode(String str, int ch, boolean respectEmpty) {
+        if (str == null || str.length() == 0) {
+            return new String[0];
+        }
+
+        ArrayList strings = new ArrayList();
+        int pos;
+        int lastpos = 0;
+
+        // add snipples
+        while ((pos = str.indexOf(ch, lastpos)) >= 0) {
+            if (pos - lastpos > 0 || respectEmpty) {
+                strings.add(str.substring(lastpos, pos));
+            }
+            lastpos = pos + 1;
+        }
+        // add rest
+        if (lastpos < str.length()) {
+            strings.add(str.substring(lastpos));
+        } else if (respectEmpty && lastpos == str.length()) {
+            strings.add("");
+        }
+
+        // return stringarray
+        return (String[]) strings.toArray(new String[strings.size()]);
+    }
+
+    /**
+     * Replaces all occurences of <code>oldString</code> in <code>text</code>
+     * with <code>newString</code>.
+     *
+     * @param text
+     * @param oldString old substring to be replaced with <code>newString</code>
+     * @param newString new substring to replace occurences of <code>oldString</code>
+     * @return a string
+     */
+    public static String replace(String text, String oldString, String newString) {
+        if (text == null || oldString == null || newString == null) {
+            throw new IllegalArgumentException("null argument");
+        }
+        int pos = text.indexOf(oldString);
+        if (pos == -1) {
+            return text;
+        }
+        int lastPos = 0;
+        StringBuffer sb = new StringBuffer(text.length());
+        while (pos != -1) {
+            sb.append(text.substring(lastPos, pos));
+            sb.append(newString);
+            lastPos = pos + oldString.length();
+            pos = text.indexOf(oldString, lastPos);
+        }
+        if (lastPos < text.length()) {
+            sb.append(text.substring(lastPos));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Replaces illegal XML characters in the given string by their corresponding
+     * predefined entity references.
+     *
+     * @param text text to be escaped
+     * @return a string
+     */
+    public static String encodeIllegalXMLCharacters(String text) {
+        if (text == null) {
+            throw new IllegalArgumentException("null argument");
+        }
+        StringBuffer buf = null;
+        int length = text.length();
+        int pos = 0;
+        for (int i = 0; i < length; i++) {
+            int ch = text.charAt(i);
+            switch (ch) {
+                case '<':
+                case '>':
+                case '&':
+                case '"':
+                case '\'':
+                    if (buf == null) {
+                        buf = new StringBuffer();
+                    }
+                    if (i > 0) {
+                        buf.append(text.substring(pos, i));
+                    }
+                    pos = i + 1;
+                    break;
+                default:
+                    continue;
+            }
+            if (ch == '<') {
+                buf.append("&lt;");
+            } else if (ch == '>') {
+                buf.append("&gt;");
+            } else if (ch == '&') {
+                buf.append("&amp;");
+            } else if (ch == '"') {
+                buf.append("&quot;");
+            } else if (ch == '\'') {
+                buf.append("&apos;");
+            }
+        }
+        if (buf == null) {
+            return text;
+        } else {
+            if (pos < length) {
+                buf.append(text.substring(pos));
+            }
+            return buf.toString();
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/util/Text.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Bytes.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Bytes.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Bytes.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Bytes.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2003-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.uuid;
+
+/**
+ * <p>Static methods for managing byte arrays (all methods follow Big
+ * Endian order where most significant bits are in front).</p>
+ * <p/>
+ * <p>Copied from the Jakarta Commons-Id project</p>
+ * <p/>
+ * todo remove and use official commons-id release as soon as it is available
+ * <p/>
+ * {@link http://jakarta.apache.org/turbine/turbine-2.3/}
+ */
+public final class Bytes {
+
+    /**
+     * <p>Hide constructor in utility class.</p>
+     */
+    private Bytes() {
+    }
+
+    /**
+     * Appends two bytes array into one.
+     *
+     * @param a A byte[].
+     * @param b A byte[].
+     * @return A byte[].
+     */
+    public static byte[] append(byte[] a, byte[] b) {
+        byte[] z = new byte[a.length + b.length];
+        System.arraycopy(a, 0, z, 0, a.length);
+        System.arraycopy(b, 0, z, a.length, b.length);
+        return z;
+    }
+
+    /**
+     * Returns a 8-byte array built from a long.
+     *
+     * @param n The number to convert.
+     * @return A byte[].
+     */
+    public static byte[] toBytes(long n) {
+        return toBytes(n, new byte[8]);
+    }
+
+    /**
+     * Build a 8-byte array from a long.  No check is performed on the
+     * array length.
+     *
+     * @param n The number to convert.
+     * @param b The array to fill.
+     * @return A byte[].
+     */
+    public static byte[] toBytes(long n, byte[] b) {
+        b[7] = (byte) (n);
+        n >>>= 8;
+        b[6] = (byte) (n);
+        n >>>= 8;
+        b[5] = (byte) (n);
+        n >>>= 8;
+        b[4] = (byte) (n);
+        n >>>= 8;
+        b[3] = (byte) (n);
+        n >>>= 8;
+        b[2] = (byte) (n);
+        n >>>= 8;
+        b[1] = (byte) (n);
+        n >>>= 8;
+        b[0] = (byte) (n);
+
+        return b;
+    }
+
+    /**
+     * Build a long from first 8 bytes of the array.
+     *
+     * @param b The byte[] to convert.
+     * @return A long.
+     */
+    public static long toLong(byte[] b) {
+        return ((((long) b[7]) & 0xFF)
+                + ((((long) b[6]) & 0xFF) << 8)
+                + ((((long) b[5]) & 0xFF) << 16)
+                + ((((long) b[4]) & 0xFF) << 24)
+                + ((((long) b[3]) & 0xFF) << 32)
+                + ((((long) b[2]) & 0xFF) << 40)
+                + ((((long) b[1]) & 0xFF) << 48)
+                + ((((long) b[0]) & 0xFF) << 56));
+    }
+
+    /**
+     * Compares two byte arrays for equality.
+     *
+     * @param a A byte[].
+     * @param b A byte[].
+     * @return True if the arrays have identical contents.
+     */
+    public static boolean areEqual(byte[] a, byte[] b) {
+        int aLength = a.length;
+        if (aLength != b.length) {
+            return false;
+        }
+
+        for (int i = 0; i < aLength; i++) {
+            if (a[i] != b[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * <p>Compares two byte arrays as specified by <code>Comparable</code>.
+     *
+     * @param lhs - left hand value in the comparison operation.
+     * @param rhs - right hand value in the comparison operation.
+     * @return a negative integer, zero, or a positive integer as <code>lhs</code>
+     *         is less than, equal to, or greater than <code>rhs</code>.
+     */
+    public static int compareTo(byte[] lhs, byte[] rhs) {
+        if (lhs == rhs) {
+            return 0;
+        }
+        if (lhs == null) {
+            return -1;
+        }
+        if (rhs == null) {
+            return +1;
+        }
+        if (lhs.length < rhs.length) {
+            return -1;
+        }
+        if (lhs.length > rhs.length) {
+            return +1;
+        }
+        for (int i = 0; i < lhs.length; i++) {
+            if (lhs[i] < rhs[i]) {
+                return -1;
+            } else if (lhs[i] > rhs[i]) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Build a short from first 2 bytes of the array.
+     *
+     * @param b The byte[] to convert.
+     * @return A short.
+     */
+    public static short toShort(byte[] b) {
+        return (short) ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Bytes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Constants.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Constants.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Constants.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Constants.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.uuid;
+
+/**
+ * <p>Constant values commonly needed in the uuid classes.</p>
+ * <p/>
+ * <p>Copied from the Jakarta Commons-Id project</p>
+ * <p/>
+ * todo remove and use official commons-id release as soon as it is available
+ */
+public interface Constants {
+
+    //** Magic number constants
+    /**
+     * Bits in a UUID.
+     */
+    int UUID_BIT_LENGTH = 128;
+
+    /**
+     * Number of bytes in a UUID.
+     */
+    int UUID_BYTE_LENGTH = 16;
+
+
+    //** Formatting and validation constants
+    /**
+     * Chars in a UUID String.
+     */
+    int UUID_UNFORMATTED_LENGTH = 32;
+
+    /**
+     * Chars in a UUID String.
+     */
+    int UUID_FORMATTED_LENGTH = 36;
+
+    /**
+     * Token length of '-' separated tokens.
+     */
+    int TOKENS_IN_UUID = 5;
+
+    /**
+     * Array to check tokenized UUID's segment lengths
+     */
+    int[] TOKEN_LENGTHS = {8, 4, 4, 4, 12};
+
+    /**
+     * Insertion point 1 for dashes in the string format
+     */
+    int FORMAT_POSITION1 = 8;
+
+    /**
+     * Insertion point 2 for dashes in the string format
+     */
+    int FORMAT_POSITION2 = 13;
+
+    /**
+     * Insertion point 3 for dashes in the string format
+     */
+    int FORMAT_POSITION3 = 18;
+
+    /**
+     * Insertion point 4 for dashes in the string format
+     */
+    int FORMAT_POSITION4 = 23;
+
+    /**
+     * The string prefix for a urn UUID identifier.
+     */
+    String URN_PREFIX = "urn:uuid:";
+
+
+    //** UUID Variant QueryConstants
+    /**
+     * UUID variant bits described in the IETF Draft MSB order,
+     * this is the "Reserved, NCS backward compatibility field" 0 x x with unknown bits as 0
+     */
+    int VARIANT_NCS_COMPAT = 0;
+
+    /**
+     * UUID variant bits described in the IETF Draft MSB order,
+     * this is the IETF Draft memo variant field 1 0 x with unknown bits as 0
+     */
+    int VARIANT_IETF_DRAFT = 2;
+
+    /**
+     * UUID variant bits described in the IETF Draft MSB order,
+     * this is the IETF Draft "Microsoft Corporation" field variant 1 1 0 x with unknown bits as 0
+     */
+    int VARIANT_MS = (byte) 6;
+
+    /**
+     * UUID variant bits described in the IETF Draft MSB order,
+     * this is the "Future Reserved variant 1 1 1 x with unknown bits as 0
+     */
+    int VARIANT_FUTURE = 7;
+
+
+    //** UUID Version QueryConstants
+    /**
+     * Version one constant for UUID version one of four
+     */
+    int VERSION_ONE = 1;
+
+    /**
+     * Version two constant for UUID version two of four
+     */
+    int VERSION_TWO = 2;
+
+    /**
+     * Version three constant for UUID version three of four
+     */
+    int VERSION_THREE = 3;
+
+    /**
+     * Version four constant for UUID version four of four
+     */
+    int VERSION_FOUR = 4;
+
+    //** Exception message constants
+    /**
+     * Message indicating this is not a version one UUID
+     */
+    String WRONG_VAR_VER_MSG = "Not a ietf variant 2 or version 1 (time-based UUID)";
+
+    // ** Array positions and lengths of UUID fields ** //
+    /**
+     * Byte length of time low field
+     */
+    int TIME_LOW_BYTE_LEN = 4;
+    /**
+     * Byte length of time low field
+     */
+    int TIME_MID_BYTE_LEN = 2;
+    /**
+     * Byte length of time low field
+     */
+    int TIME_HI_BYTE_LEN = 2;
+    /**
+     * Timestamp byte[] position of time low field
+     */
+    int TIME_LOW_TS_POS = 4;
+    /**
+     * Timestamp byte[]  position mid field
+     */
+    int TIME_MID_TS_POS = 2;
+    /**
+     * Timestamp byte[]  position hi field
+     */
+    int TIME_HI_TS_POS = 0;
+    /**
+     * uuid array position start of time low field
+     */
+    int TIME_LOW_START_POS = 0;
+    /**
+     * uuid array position start of mid field
+     */
+    int TIME_MID_START_POS = 4;
+    /**
+     * uuid array position start of hi field
+     */
+    int TIME_HI_START_POS = 6;
+    /**
+     * Byte position of the clock sequence and reserved field
+     */
+    short TIME_HI_AND_VERSION_BYTE_6 = 6;
+    /**
+     * Byte position of the clock sequence and reserved field
+     */
+    short CLOCK_SEQ_HI_AND_RESERVED_BYTE_8 = 8;
+
+    /**
+     * XXX added by stefan@apache.org:
+     * hexdigits for converting numerics to hex
+     */
+    char[] hexDigits = "0123456789abcdef".toCharArray();
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/Constants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/UUID.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/UUID.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/UUID.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/UUID.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,511 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.uuid;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.StringTokenizer;
+
+/** XXX begin modification by stefan@apache.org */
+/*import org.apache.commons.id.IdentifierUtils;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.digest.DigestUtils;*/
+/** XXX end modification by stefan@apache.org */
+
+/**
+ * <p><code>UUID</code> represents a Universally Unique Identifier per IETF
+ * Draft specification. For more information regarding the IETF Draft UUID
+ * specification</p>
+ * <p/>
+ * <p>See: http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-01.txt</p>
+ * <p/>
+ * <p>Copied from the Jakarta Commons-Id project</p>
+ * <p/>
+ * todo remove and use official commons-id release as soon as it is available
+ */
+
+public class UUID implements Constants, Serializable, Comparable {
+
+    /**
+     * byte array to store 128-bits composing this UUID
+     */
+    private byte[] rawBytes = new byte[UUID_BYTE_LENGTH];
+
+    /**
+     * Holds node identifier for this UUID
+     */
+    private Long node = null;
+
+    /**
+     * Holds timestamp for this UUID
+     */
+    private long timestamp = -1;
+
+    /**
+     * Holds the clock sequence field
+     */
+    private Short clockSq = null;
+
+    /**
+     * Holds the version field of this UUID
+     */
+    private int version = -1;
+
+    /**
+     * Holds the variant field of this UUID
+     */
+    private int variant = -1;
+
+    /**
+     * Holds the internal string value of the UUID
+     */
+    private String stringValue = null;
+
+    /**
+     * XXX begin modification by stefan@apache.org
+     */
+    private static VersionFourGenerator versionFourGenereator = new VersionFourGenerator();
+    /** XXX end modification by stefan@apache.org */
+
+    /**
+     * Constructs a nil UUID
+     */
+    public UUID() {
+        super();
+    }
+
+    /**
+     * <p>Constructs a UUID from a 128 bit java.math.BigInteger.</p>
+     * <p>Method is protected as their is no standard as to the internal representation of a UUID.
+     * In this case a BigInteger is used with signum always positive.</p>
+     *
+     *  @param bigIntValue the 128 bit BigInteger to construct this UUID from.
+     *  @throws IllegalArgumentException argument must be 128 bit
+     */
+    /* protected UUID(BigInteger bigIntValue) throws IllegalArgumentException {
+         super();
+         if (bigIntValue.bitLength() > UUID.UUID_BIT_LENGTH) {
+             throw new IllegalArgumentException("UUID must be contructed using a 128 bit BigInteger");
+         }
+         numberValue = bigIntValue;
+     } */
+
+    /**
+     * <p>Copy constructor.</p>
+     *
+     * @param copyFrom the UUID to copy to create this UUID.
+     */
+    public UUID(UUID copyFrom) {
+        super();
+        rawBytes = copyFrom.getRawBytes();
+    }
+
+    /**
+     * <p>Constructs a UUID from a 16 byte array.</p>
+     *
+     * @param byteArray the 16 byte array to construct this UUID from.
+     * @throws IllegalArgumentException argument must be 16 bytes
+     */
+    public UUID(byte[] byteArray) throws IllegalArgumentException {
+        super();
+        if (byteArray.length != UUID_BYTE_LENGTH) {
+            throw new IllegalArgumentException("UUID must be contructed using a 16 byte array.");
+        }
+        // UUID must be immutable so a copy is used.
+        System.arraycopy(byteArray, 0, rawBytes, 0, UUID_BYTE_LENGTH);
+    }
+
+    /**
+     * <p>Constructs a UUID from a DataInput. Note if 16 bytes are not available this method will block.</p>
+     *
+     * @param input the datainput with 16 bytes to read in from.
+     * @throws java.io.IOException exception if there is an IO problem also argument must contain 16 bytes.
+     */
+    public UUID(DataInput input) throws IOException {
+        super();
+        input.readFully(rawBytes, 0, UUID_BYTE_LENGTH);
+    }
+
+    /**
+     * <p>Constructs a UUID from two long values in most significant byte, and least significant bytes order.</p>
+     *
+     * @param mostSignificant  - the most significant 8 bytes of the uuid to be constructed.
+     * @param leastSignificant - the least significant 8 bytes of the uuid to be constructed.
+     */
+    public UUID(long mostSignificant, long leastSignificant) {
+        rawBytes = Bytes.append(Bytes.toBytes(mostSignificant), Bytes.toBytes(leastSignificant));
+    }
+
+    /** XXX begin modification by stefan@apache.org */
+    /**
+     * <p>Constructs a UUID from a UUID formatted String.</p>
+     *
+     * @param uuidString the String representing a UUID to construct this UUID
+     * @throws UUIDFormatException String must be a properly formatted UUID string
+     */
+    //public UUID(String uuidString) throws UUIDFormatException {
+    public UUID(String uuidString) {
+        //Calls the copy constructor
+        this(UUID.fromString(uuidString));
+    }
+    /** XXX end modification by stefan@apache.org */
+
+    /** XXX begin modification by stefan@apache.org */
+    /**
+     * <p>Parses a string for a UUID.</p>
+     *
+     * @param uuidString the UUID formatted String to parse.
+     *                   XXX begin modification by stefan@apache.org
+     * @return Returns a UUID or null if the formatted string could not be parsed.
+     * @throws IllegalArgumentException the String must be a properly formatted UUID String.
+     *                             XXX end modification by stefan@apache.org
+     */
+    //public static UUID fromString(String uuidString) throws UUIDFormatException {
+    public static UUID fromString(String uuidString) throws IllegalArgumentException {
+        String leanString = uuidString.toLowerCase();
+        UUID tmpUUID = null;
+
+        //Handle prefixed UUIDs
+        // e.g. urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
+        int pos = uuidString.lastIndexOf(":");
+        if (pos > 1) {
+            leanString = uuidString.substring(++pos, uuidString.length());
+        }
+
+        //Check for 36 char length
+        if (leanString.length() != UUID_FORMATTED_LENGTH) {
+            //throw new UUIDFormatException();
+            throw new IllegalArgumentException();
+        }
+
+        //Check for 5 fields
+        StringTokenizer tok = new StringTokenizer(leanString, "-");
+        if (tok.countTokens() != TOKENS_IN_UUID) {
+            //throw new UUIDFormatException();
+            throw new IllegalArgumentException();
+        }
+
+        //Remove the "-" from the formatted string and test token sizes
+        StringBuffer buf = new StringBuffer(UUID_UNFORMATTED_LENGTH);
+        String token = null;
+        int count = 0;
+        while (tok.hasMoreTokens()) {
+            token = tok.nextToken();
+            if (token.length() != TOKEN_LENGTHS[count++]) {
+                //throw new UUIDFormatException();
+                throw new IllegalArgumentException();
+            }
+            buf.append(token);
+        }
+
+        //Create from the hex value
+        /** XXX begin modification by stefan@apache.org */
+/*
+        try {
+            char[] chars = buf.toString().toCharArray();
+            tmpUUID = new UUID(Hex.decodeHex(chars));
+        } catch (DecoderException de) {
+              throw new UUIDFormatException(de.getMessage());
+       }
+*/
+        String s = buf.toString();
+        byte[] bytes = new byte[UUID_BYTE_LENGTH];
+        for (int i = 0, j = 0; i < (UUID_BYTE_LENGTH * 2); i += 2) {
+            bytes[j++] = (byte) Integer.parseInt(s.substring(i, i + 2), 16);
+        }
+        tmpUUID = new UUID(bytes);
+        /** XXX end modification by stefan@apache.org */
+
+        return tmpUUID;
+    }
+    /** XXX end modification by stefan@apache.org */
+
+    /**
+     * <p>Returns a string representation of the UUID.</p>
+     *
+     * @return a string representation of the UUID formatted according to the specification.
+     */
+    public String toString() {
+        //set string value if not set
+        if (stringValue == null) {
+            /** XXX begin modification by stefan@apache.org */
+/*
+            StringBuffer buf = new StringBuffer(new String(Hex.encodeHex(rawBytes)));
+            while (buf.length() != UUID_UNFORMATTED_LENGTH) {
+                buf.insert(0, "0");
+            }
+            buf.ensureCapacity(UUID_FORMATTED_LENGTH);
+            buf.insert(FORMAT_POSITION1, '-');
+            buf.insert(FORMAT_POSITION2, '-');
+            buf.insert(FORMAT_POSITION3, '-');
+            buf.insert(FORMAT_POSITION4, '-');
+            stringValue = buf.toString();
+*/
+            char[] chars = new char[UUID_FORMATTED_LENGTH];
+            for (int i = 0, j = 0; i < 16; i++) {
+                chars[j++] = hexDigits[(rawBytes[i] >> 4) & 0x0f];
+                chars[j++] = hexDigits[rawBytes[i] & 0x0f];
+                if (i == 3 || i == 5 || i == 7 || i == 9) {
+                    chars[j++] = '-';
+                }
+            }
+            stringValue = new String(chars);
+            /** XXX end modification by stefan@apache.org */
+        }
+        return stringValue;
+    }
+
+    /**
+     * <p>Returns a urn representation of the UUID. This is same as the
+     * toString() value prefixed with <code>urn:uuid:</code></p>
+     *
+     * @return Returns the urn string representation of the UUID
+     */
+    public String toUrn() {
+        return URN_PREFIX + this.toString();
+    }
+
+    /**
+     * <p>Compares two UUID for equality.</p>
+     *
+     * @see Object#equals(Object)
+     */
+
+    public boolean equals(Object obj) {
+        if (!(obj instanceof UUID)) {
+            return false;
+        }
+        return Bytes.areEqual(((UUID) obj).getRawBytes(), rawBytes);
+    }
+
+    /**
+     * <p>Returns a hash code value for the object.</p>
+     *
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        int iConstant = 37;
+        int iTotal = 17;
+        for (int i = 0; i < rawBytes.length; i++) {
+            iTotal = iTotal * iConstant + rawBytes[i];
+        }
+        return iTotal;
+    }
+
+    /**
+     * <p>Compares two UUID's for equality</p>
+     *
+     * @see Comparable#compareTo(Object)
+     */
+    public int compareTo(Object compareTo) throws ClassCastException {
+        if (!(compareTo instanceof UUID)) {
+            throw new ClassCastException();
+        }
+        return (Bytes.compareTo(rawBytes, ((UUID) compareTo).getRawBytes()));
+    }
+
+    /**
+     * <p>Returns the clock sequence value in the UUID. The clock sequence is a random assigned to a particular clock instance that
+     * generated the time in the timestamp of a time based UUID.</p>
+     *
+     * @return the clock sequence value in the UUID.
+     * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID.
+     */
+    public int clockSequence() throws UnsupportedOperationException {
+        //if variant is not mealling leach salz throw unsupported operation exception
+        if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) {
+            throw new UnsupportedOperationException(WRONG_VAR_VER_MSG);
+        }
+        if (clockSq == null) {
+            byte[] b = {((byte) (rawBytes[8] & 0x3F)), rawBytes[9]};
+            clockSq = new Short(Bytes.toShort(b));
+        }
+        return clockSq.intValue();
+    }
+
+    /**
+     * <p>Returns the version of the UUID.
+     * <ul>
+     * <li>VERSION_ONE - The time-based version</li>
+     * <li>VERSION_TWO - DCE Security version, with embedded POSIX UIDs.</li>
+     * <li>VERSION_THREE - Name based UUID.</li>
+     * <li>VERSION_FOUR - Random based UUID.</li>
+     * </ul>
+     * </p>
+     *
+     * @return the version of the UUID.
+     */
+    public int version() {
+        if (version == -1) {
+            version = ((rawBytes[6] >>> 4) & 0x0F);
+        }
+        return version;
+    }
+
+    /**
+     * <p>Returns the variant field of the UUID.</p>
+     *
+     * @return Returns the variant field of the UUID.
+     * @see UUID#VARIANT_NCS_COMPAT
+     * @see UUID#VARIANT_IETF_DRAFT
+     * @see UUID#VARIANT_MS
+     * @see UUID#VARIANT_FUTURE
+     */
+    public int variant() {
+        if (variant == -1) {
+            if ((rawBytes[8] & 0x80) == 0x0) {
+                variant = VARIANT_NCS_COMPAT;
+            } else if ((rawBytes[8] & 0x40) == 0x0) {
+                variant = VARIANT_IETF_DRAFT;
+            } else if ((rawBytes[8] & 0x20) == 0x0) {
+                variant = VARIANT_MS;
+            } else {
+                variant = VARIANT_FUTURE;
+            }
+        }
+        return variant;
+    }
+
+    /**
+     * <p>Returns the node identifier found in this UUID. The specification was written such that this value holds the IEEE 802 MAC
+     * address. The specification permits this value to be calculated from other sources other than the MAC.</p>
+     *
+     * @return the node identifier found in this UUID.
+     * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID.
+     */
+    public long node() throws UnsupportedOperationException {
+        //if variant is not mealling leach salz throw unsupported operation exception
+        if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) {
+            throw new UnsupportedOperationException(WRONG_VAR_VER_MSG);
+        }
+        if (node == null) {
+            byte[] b = new byte[8];
+            System.arraycopy(rawBytes, 10, b, 2, 6);
+            node = new Long((Bytes.toLong(b) & 0xFFFFFFFFFFFFL));
+        }
+        return node.longValue();
+    }
+
+    /**
+     * <p>Returns the timestamp value of the UUID as 100-nano second intervals since the Gregorian change offset (00:00:00.00, 15
+     * October 1582 ).</p>
+     *
+     * @return the timestamp value of the UUID as 100-nano second intervals since the Gregorian change offset.
+     * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID.
+     */
+    public long timestamp() throws UnsupportedOperationException {
+        //if variant is not mealling leach salz throw unsupported operation exception
+        if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) {
+            throw new UnsupportedOperationException(WRONG_VAR_VER_MSG);
+        }
+        if (timestamp == -1) {
+            byte[] longVal = new byte[8];
+            System.arraycopy(rawBytes, TIME_HI_START_POS, longVal, TIME_HI_TS_POS, TIME_HI_BYTE_LEN);
+            System.arraycopy(rawBytes, TIME_MID_START_POS, longVal, TIME_MID_TS_POS, TIME_MID_BYTE_LEN);
+            System.arraycopy(rawBytes, TIME_LOW_START_POS, longVal, TIME_LOW_TS_POS, TIME_LOW_BYTE_LEN);
+            longVal[TIME_HI_TS_POS] &= 0x0F;
+            timestamp = Bytes.toLong(longVal);
+        }
+        return timestamp;
+    }
+
+    /**
+     * <p>Returns the least significant bits stored in the uuid's internal structure.</p>
+     *
+     * @return the least significant bits stored in the uuid's internal structure.
+     */
+    long getLeastSignificantBits() {
+        byte[] lsb = new byte[8];
+        System.arraycopy(rawBytes, 8, lsb, 0, 8);
+        return Bytes.toLong(lsb);
+    }
+
+    /**
+     * <p>Returns the least significant bits stored in the uuid's internal structure.</p>
+     *
+     * @return the least significant bits stored in the uuid's internal structure.
+     */
+    long getMostSignificantBits() {
+        byte[] msb = new byte[8];
+        System.arraycopy(rawBytes, 0, msb, 0, 8);
+        return Bytes.toLong(msb);
+    }
+
+    /**
+     * <p>Returns a copy of the byte values contained in this UUID.
+     *
+     * @return a copy of the byte values contained in this UUID.
+     */
+    public byte[] getRawBytes() {
+        byte[] ret = new byte[UUID_BYTE_LENGTH];
+        System.arraycopy(rawBytes, 0, ret, 0, UUID_BYTE_LENGTH);
+        return ret;
+    }
+
+    /**
+     * <p>Returns a new version 4 UUID, based upon Random bits.</p>
+     *
+     * @return a new version 4 UUID, based upon Random bits.
+     */
+    /**
+     * XXX begin modification by stefan@apache.org
+     */
+    //static UUID randomUUID() {
+    public static UUID randomUUID() {
+        //return (UUID) IdentifierUtils.UUID_VERSION_FOUR_GENERATOR.nextIdentifier();
+        return (UUID) versionFourGenereator.nextIdentifier();
+    }
+    /** XXX end modification by stefan@apache.org */
+
+    /** XXX begin modification by stefan@apache.org */
+    /**
+     * <p>Returns a new version 1 UUID, based upon node identifier and time stamp.</p>
+     *
+     * @return a new version 1 UUID, based upon node identifier and time stamp.
+     */
+/*    static UUID timeUUID() {
+        return (UUID) IdentifierUtils.UUID_VERSION_ONE_GENERATOR.nextIdentifier();
+    }*/
+    /** XXX end modification by stefan@apache.org */
+
+    /** XXX begin modification by stefan@apache.org */
+    /**
+     * <p>Returns a new version three UUID given a name and the namespace's UUID.</p>
+     *
+     * @param name String the name to calculate the UUID for.
+     * @param namespace UUID assigned to this namespace.
+     * @return a new version three UUID given a name and the namespace's UUID.
+     */
+/*    static UUID nameUUIDFromString(String name, UUID namespace) {
+        byte[] nameAsBytes = name.getBytes();
+        byte[] concat = new byte[UUID_BYTE_LENGTH + nameAsBytes.length];
+        System.arraycopy(namespace.getRawBytes(), 0, concat, 0, UUID_BYTE_LENGTH);
+        System.arraycopy(nameAsBytes, 0, concat, UUID_BYTE_LENGTH, nameAsBytes.length);
+        byte[] raw = DigestUtils.md5(concat);
+        //Set version
+        raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F;
+        raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_THREE << 4);
+        //Set variant
+        raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111
+        raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000
+
+        return new UUID(raw);
+    }*/
+    /** XXX end modification by stefan@apache.org */
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/UUID.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/VersionFourGenerator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/VersionFourGenerator.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/VersionFourGenerator.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/VersionFourGenerator.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.uuid;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.util.Random;
+
+/** XXX begin modification by stefan@apache.org */
+//import org.apache.commons.id.IdentifierGenerator;
+/** XXX end modification by stefan@apache.org */
+
+/**
+ * <p>Class is responsible for generating version 4 UUID's per the IETF draft
+ * specification. This class attempts to use a java.security.SecureRandom with
+ * the following instantiation
+ * <code>SecureRandom.getInstance("SHA1PRNG", "SUN")</code>. If neither secure
+ * random implementation is avialable or an Exception is raised a java.util.Random
+ * is used.</p>
+ * <p>Note: Instantiation of SecureRandom is an expensive operation. The
+ * constructor therefore creates a static member to hold the SecureRandom.
+ * The first call to getInstance may take time; subsequent calls should return
+ * quickly.</p>
+ *
+ * <p>Copied from the Jakarta Commons-Id project</p>
+ * <p/>
+ * todo remove and use official commons-id release as soon as it is available
+ *
+ *
+ */
+
+/**
+ * XXX begin modification by stefan@apache.org
+ */
+//public final class VersionFourGenerator implements IdentifierGenerator, QueryConstants {
+public final class VersionFourGenerator implements Constants {
+    /** XXX end modification by stefan@apache.org */
+
+    /**
+     * Random used to generate UUID's
+     */
+    private static final Random regularRandom = new Random();
+
+    /**
+     * SecureRandom used to generate UUID's
+     */
+    private static Random secureRandom;
+
+    /**
+     * The pseudo-random number generator to use
+     */
+    private static String usePRNG = "SHA1PRNG";
+
+    /**
+     * The pseudo-random number generator package name to use
+     */
+    private static String usePRNGPackage = "SUN";
+
+    /**
+     * <p>Constructs a new VersionFourGenerator.</p>
+     */
+    public VersionFourGenerator() {
+        super();
+    }
+
+    /**
+     * <p>Returns a new version four UUID.</p>
+     *
+     * @return Object a new version 4 UUID.
+     */
+    public Object nextIdentifier() {
+        return nextUUID(false);
+    }
+
+    /**
+     * <p>Returns a new version four UUID.</p>
+     * <p>This overloaded method may produce both UUID's using a <code>SecureRandom</code> as well as using normal
+     * <code>Random</code>
+     * </p>
+     *
+     * @param secure indicates whether or not to use <code>SecureRandom</code> in generating the random bits.
+     * @return a new version four UUID that was generated by either a <code>Random</code> or <code>SecureRandom</code>.
+     */
+    public Object nextIdentifier(boolean secure) {
+        if (secure) {
+            return nextUUID(true);
+        }
+        return nextUUID(false);
+    }
+
+    /**
+     * <p>Returns a new version four UUID.</p>
+     *
+     * @return Object a new version 4 UUID.
+     */
+    private UUID nextUUID() {
+        //Call nextUUID with secure = false
+        return nextUUID(false);
+    }
+
+    /**
+     * <p>Returns a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>.</p>
+     *
+     * @param secure boolean flag indicating whether to use <code>SecureRandom</code> or <code>Random</code>.
+     * @return a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>.
+     */
+    private UUID nextUUID(boolean secure) {
+        byte[] raw = new byte[UUID_BYTE_LENGTH];
+        if (secure) {
+            //Initialize the secure random if null.
+            if (secureRandom == null) {
+                try {
+                    if (usePRNGPackage != null) {
+                        secureRandom = SecureRandom.getInstance(usePRNG, usePRNGPackage);
+                    } else {
+                        secureRandom = SecureRandom.getInstance(usePRNG);
+                    }
+                } catch (NoSuchAlgorithmException nsae) {
+                    secure = false; //Fail back to default PRNG/Random
+                } catch (NoSuchProviderException nspe) {
+                    secure = false; //Fail back to default PRNG/Random
+                }
+                secureRandom.nextBytes(raw);
+            }
+        }
+
+        if (!secure) {
+            regularRandom.nextBytes(raw);
+        }
+
+        raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F;
+        raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_FOUR << 4);
+
+        raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111
+        raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000
+
+        return new UUID(raw);
+    }
+
+    /**
+     * <p>Allows clients to set the pseudo-random number generator implementation used when generating a version four uuid with
+     * the secure option. The secure option uses a <code>SecureRandom</code>. The packageName string may be null to specify
+     * no preferred package.</p>
+     *
+     * @param prngName    the pseudo-random number generator implementation name. For example "SHA1PRNG".
+     * @param packageName the package name for the PRNG provider. For example "SUN".
+     */
+    public static void setPRNGProvider(String prngName, String packageName) {
+        VersionFourGenerator.usePRNG = prngName;
+        VersionFourGenerator.usePRNGPackage = packageName;
+        VersionFourGenerator.secureRandom = null;
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/VersionFourGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/package.html
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/package.html?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/package.html (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/package.html Mon Jul  4 07:52:19 2005
@@ -0,0 +1,14 @@
+<body>
+  <p>
+    <p>
+      This package contains a UUID (Universally Unique Identifier) version 4
+      generator implementation copied from from the
+      <a href="http://jakarta.apache.org/commons/sandbox/id/">
+      Jakarta Commons-Id project</a>.
+    </p>
+  <p>
+     <b>TODO:</b> Replace with commons-id.jar as soon as official release is
+     available. 
+  </p>
+ </p>
+</body>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/uuid/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/value/BaseValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/value/BaseValue.java?rev=209089&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/value/BaseValue.java (added)
+++ incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/value/BaseValue.java Mon Jul  4 07:52:19 2005
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.value;
+
+import org.apache.jackrabbit.util.ISO8601;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Calendar;
+
+/**
+ * This class is the superclass of the type-specific
+ * classes implementing the <code>Value</code> interfaces.
+ *
+ * @see javax.jcr.Value
+ * @see StringValue
+ * @see LongValue
+ * @see DoubleValue
+ * @see BooleanValue
+ * @see DateValue
+ * @see BinaryValue
+ * @see NameValue
+ * @see PathValue
+ * @see ReferenceValue
+ */
+public abstract class BaseValue implements Value {
+
+    protected static final String DEFAULT_ENCODING = "UTF-8";
+
+    private static final short STATE_UNDEFINED = 0;
+    private static final short STATE_VALUE_CONSUMED = 1;
+    private static final short STATE_STREAM_CONSUMED = 2;
+
+    private short state = STATE_UNDEFINED;
+
+    protected final int type;
+
+    protected InputStream stream = null;
+
+    /**
+     * Package-private default constructor.
+     *
+     * @param type The type of this value.
+     */
+    BaseValue(int type) {
+        this.type = type;
+    }
+
+    /**
+     * Checks if the non-stream value of this instance has already been
+     * consumed (if any getter methods except <code>{@link #getStream()}</code> and
+     * <code>{@link #getType()}</code> have been previously called at least once) and
+     * sets the state to <code>STATE_STREAM_CONSUMED</code>.
+     *
+     * @throws IllegalStateException if any getter methods other than
+     *                               <code>getStream()</code> and
+     *                               <code>getType()</code> have been
+     *                               previously called at least once.
+     */
+    protected void setStreamConsumed() throws IllegalStateException {
+        if (state == STATE_VALUE_CONSUMED) {
+            throw new IllegalStateException("non-stream value has already been consumed");
+        }
+        state = STATE_STREAM_CONSUMED;
+    }
+
+    /**
+     * Checks if the stream value of this instance has already been
+     * consumed (if {@link #getStream()} has been previously called
+     * at least once) and sets the state to <code>STATE_VALUE_CONSUMED</code>.
+     *
+     * @throws IllegalStateException if <code>getStream()</code> has been
+     *                               previously called at least once.
+     */
+    protected void setValueConsumed() throws IllegalStateException {
+        if (state == STATE_STREAM_CONSUMED) {
+            throw new IllegalStateException("stream value has already been consumed");
+        }
+        state = STATE_VALUE_CONSUMED;
+    }
+
+    /**
+     * Returns the internal string representation of this value without modifying
+     * the value state.
+     *
+     * @return the internal string representation
+     * @throws javax.jcr.ValueFormatException if the value can not be represented as a
+     *                              <code>String</code> or if the value is
+     *                              <code>null</code>.
+     * @throws javax.jcr.RepositoryException  if another error occurs.
+     */
+    protected abstract String getInternalString()
+            throws ValueFormatException, RepositoryException;
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        Calendar cal = ISO8601.parse(getInternalString());
+        if (cal == null) {
+            throw new ValueFormatException("not a valid date format");
+        } else {
+            return cal;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        try {
+            return Long.parseLong(getInternalString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to long failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        return Boolean.valueOf(getInternalString()).booleanValue();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        try {
+            return Double.parseDouble(getInternalString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to double failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream()
+            throws IllegalStateException, RepositoryException {
+        setStreamConsumed();
+
+        if (stream != null) {
+            return stream;
+        }
+
+        try {
+            // convert via string
+            stream = new ByteArrayInputStream(getInternalString().getBytes(DEFAULT_ENCODING));
+            return stream;
+        } catch (UnsupportedEncodingException e) {
+            throw new RepositoryException(DEFAULT_ENCODING
+                    + " not supported on this platform", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        return getInternalString();
+    }
+}

Propchange: incubator/jackrabbit/trunk/commons/src/java/org/apache/jackrabbit/value/BaseValue.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message