You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/05/14 05:26:02 UTC
svn commit: r406215 [7/10] - in /incubator/openjpa/trunk/openjpa-lib: ./
java/ java/org/ java/org/apache/ java/org/apache/openjpa/
java/org/apache/openjpa/lib/ java/org/apache/openjpa/lib/conf/
java/org/apache/openjpa/lib/jdbc/ java/org/apache/openjpa/...
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RandomAccessResultList.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RandomAccessResultList.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RandomAccessResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RandomAccessResultList.java Sat May 13 20:25:56 2006
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.io.*;
+import java.util.*;
+
+import serp.util.*;
+
+
+/**
+ * <p>Random-access result list implementation. It maintains a map
+ * of the items that we have already instantiated.</p>
+ *
+ * @author Marc Prud'hommeaux
+ * @author Abe White
+ * @nojavadoc
+ */
+public class RandomAccessResultList
+ extends AbstractNonSequentialResultList
+{
+ private static final int OPEN = 0;
+ private static final int FREED = 1;
+ private static final int CLOSED = 2;
+
+ // data provider
+ private ResultObjectProvider _rop = null;
+
+ // holds all the row values that have been instantiated so far
+ private Map _rows = null;
+ private Object[] _full = null;
+
+ // bookkeeping
+ private long _requests = 0;
+ private int _state = OPEN;
+ private int _size = -1;
+
+
+ public RandomAccessResultList (ResultObjectProvider rop)
+ {
+ _rop = rop;
+ _rows = newRowMap ();
+
+ try
+ {
+ _rop.open ();
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ }
+ }
+
+
+ /**
+ * Override this method to control what kind of map is used for
+ * the instantiated rows.
+ */
+ protected Map newRowMap ()
+ {
+ return new HashMap ();
+ }
+
+
+ public boolean isProviderOpen ()
+ {
+ return _state == OPEN;
+ }
+
+
+ public boolean isClosed ()
+ {
+ return _state == CLOSED;
+ }
+
+
+ public void close ()
+ {
+ if (_state != CLOSED)
+ {
+ free ();
+ _state = CLOSED;
+ }
+ }
+
+
+ protected Object getInternal (int index)
+ {
+ if (_full != null)
+ {
+ if (index >= _full.length)
+ return PAST_END;
+ return _full[index];
+ }
+
+ Integer i = Numbers.valueOf (index);
+ Object ret = _rows.get (i);
+ if (ret != null)
+ {
+ if (ret instanceof Null)
+ return null;
+ return ret;
+ }
+
+ ret = instantiateRow (i);
+ return (ret == null) ? PAST_END : ret;
+ }
+
+
+ /**
+ * Instantiate the row object at the specified index.
+ */
+ private Object instantiateRow (Integer i)
+ {
+ _requests++;
+ try
+ {
+ if (!_rop.absolute (i.intValue ()))
+ return PAST_END;
+
+ Object ob = _rop.getResultObject ();
+ if (ob == null)
+ ob = new Null ();
+
+ // cache the result
+ _rows.put (i, ob);
+
+ // check to see if our map is full
+ checkComplete ();
+ return ob;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return null;
+ }
+ }
+
+
+ /**
+ * Check to see if the soft map is the same size as all the
+ * rows in the Result: if so, we copy over the values to a
+ * hard reference HashSet and close the Result object associated with
+ * this endeavour.
+ */
+ private void checkComplete ()
+ {
+ // only check if we've actually gotten the size for some reason already
+ if (_size == -1 || _rows.size () != _size)
+ return;
+
+ Object[] full = new Object[_size];
+ int count = 0;
+ Integer key;
+ for (Iterator itr = _rows.keySet ().iterator (); itr.hasNext(); count++)
+ {
+ key = (Integer) itr.next ();
+ full[key.intValue ()] = _rows.get (key);
+ }
+
+ // double-check, in case any of the soft references were
+ // cleaned up between the time we checked the size and the
+ // time we completed the copy to the hard reference map
+ if (count == _size)
+ {
+ _full = full;
+ free ();
+ }
+ }
+
+
+ public int size ()
+ {
+ assertOpen ();
+ if (_size != -1)
+ return _size;
+ if (_full != null)
+ return _full.length;
+ try
+ {
+ _size = _rop.size ();
+ return _size;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return -1;
+ }
+ }
+
+
+ private void free ()
+ {
+ if (_state == OPEN)
+ {
+ try { _rop.close (); } catch (Exception e) {}
+ _rows = null;
+ _state = FREED;
+ }
+ }
+
+
+ public Object writeReplace ()
+ throws ObjectStreamException
+ {
+ if (_full != null)
+ return new ListResultList (Arrays.asList (_full));
+ ArrayList list = new ArrayList ();
+ for (Iterator itr = iterator (); itr.hasNext ();)
+ list.add (itr.next ());
+ return list;
+ }
+
+
+ public String toString ()
+ {
+ return getClass ().getName ()
+ + "; identity: " + System.identityHashCode (this)
+ + "; cached: " + _rows.size ()
+ + "; requests: " + _requests;
+ }
+
+
+ public int hashCode ()
+ {
+ // superclass tries to traverses entire list for hashcode
+ return System.identityHashCode (this);
+ }
+
+
+ public boolean equals (Object other)
+ {
+ // superclass tries to traverse entire list for equality
+ return other == this;
+ }
+
+
+ /**
+ * Used to represent nulls in the result list. Can't use a singleton
+ * pattern, because then there will always be a hard ref to all the
+ * nulls, and they'll never get GC'd; this is bad in the unlikely
+ * event of a huge result set with lots of nulls.
+ */
+ private static class Null
+ {
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RandomAccessResultList.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RangeResultObjectProvider.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RangeResultObjectProvider.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RangeResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RangeResultObjectProvider.java Sat May 13 20:25:56 2006
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.util.*;
+
+import org.apache.openjpa.lib.util.*;
+
+
+/**
+ * <p>Prevents a view of a given range of indices from the delegate
+ * result object provider.</p>
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class RangeResultObjectProvider
+ implements ResultObjectProvider
+{
+ private static final Localizer _loc = Localizer.forPackage
+ (RangeResultObjectProvider.class);
+
+ private final ResultObjectProvider _delegate;
+ private final int _startIdx;
+ private final int _endIdx;
+ private int _idx = -1;
+
+
+ /**
+ * Constructor. Because this is a wrapper around some delegate,
+ * and result object providers work with int indexes, neither the start
+ * or end index can be greater than Integer.MAX_VALUE (with the exception
+ * of Long.MAX_VALUE, which is used to indicate no limit).
+ *
+ * @param delegate the result object provider to delegate to
+ * @param startIdx 0-based inclusive start index of the range
+ * to present; must be < Integer.MAX_VALUE
+ * @param endIdx 0-based exclusive end index of the range to
+ * present; must be < Integer.MAX_VALUE, or
+ * Long.MAX_VALUE for no limit
+ */
+ public RangeResultObjectProvider (ResultObjectProvider delegate,
+ long startIdx, long endIdx)
+ {
+ // use Integer.MAX_VALUE for no limit internally
+ if (endIdx == Long.MAX_VALUE)
+ endIdx = Integer.MAX_VALUE;
+
+ _delegate = delegate;
+ if (startIdx > Integer.MAX_VALUE || endIdx > Integer.MAX_VALUE)
+ throw new IllegalArgumentException (_loc.get ("range-too-high",
+ String.valueOf (startIdx), String.valueOf (endIdx)));
+
+ _startIdx = (int) startIdx;
+ _endIdx = (int) endIdx;
+ }
+
+
+ public boolean supportsRandomAccess ()
+ {
+ return _delegate.supportsRandomAccess ();
+ }
+
+
+ public void open ()
+ throws Exception
+ {
+ _delegate.open ();
+ }
+
+
+ public Object getResultObject ()
+ throws Exception
+ {
+ if (_idx < _startIdx || _idx >= _endIdx)
+ throw new NoSuchElementException (String.valueOf (_idx));
+ return _delegate.getResultObject ();
+ }
+
+
+ public boolean next ()
+ throws Exception
+ {
+ // advance up to just behind _startIdx if we haven't already
+ while (_idx < _startIdx - 1)
+ {
+ if (_delegate.supportsRandomAccess ())
+ {
+ _idx = _startIdx - 1;
+ if (!_delegate.absolute (_startIdx - 1))
+ return false;
+ }
+ else
+ {
+ _idx++;
+ if (!_delegate.next ())
+ return false;
+ }
+ }
+
+ // make sure we're not falling off the end of the range
+ if (_idx >= _endIdx - 1)
+ return false;
+
+ _idx++;
+ return _delegate.next ();
+ }
+
+
+ public boolean absolute (int pos)
+ throws Exception
+ {
+ _idx = pos + _startIdx;
+ if (_idx >= _endIdx)
+ return false;
+ return _delegate.absolute (_idx);
+ }
+
+
+ public int size ()
+ throws Exception
+ {
+ int size = _delegate.size ();
+ if (size == Integer.MAX_VALUE)
+ return size;
+ size = Math.min (_endIdx, size) - _startIdx;
+ return (size < 0) ? 0 : size;
+ }
+
+
+ public void reset ()
+ throws Exception
+ {
+ _idx = -1;
+ _delegate.reset ();
+ }
+
+
+ public void close ()
+ throws Exception
+ {
+ _delegate.close ();
+ }
+
+
+ public void handleCheckedException (Exception e)
+ {
+ _delegate.handleCheckedException (e);
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/RangeResultObjectProvider.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultList.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultList.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultList.java Sat May 13 20:25:56 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.NoSuchElementException; // for javadoc; bug #4330419
+
+import org.apache.openjpa.lib.util.*;
+import org.apache.openjpa.lib.util.Closeable;
+
+
+/**
+ * <p>List interface that represents a potentially lazy ResultList
+ * instantiation.</p>
+ *
+ * <p>A ResultList will typically be instantiated from a factory, and
+ * will use a ResultObjectProvider for obtaining individual object
+ * data representations.</p>
+ *
+ * <p>Depending on the support for scrolling inputs,
+ * the list that is returned may use lazy instantiation of the
+ * objects, and thus allow very large result sets to be obtained and
+ * manipulated.</p>
+ *
+ * <p>Note that wrapping a ResultList in another Collection will
+ * always instantiate the entire set of elements contained in the
+ * ResultList. This may not always be desireable, since the list may
+ * be very large.</p>
+ *
+ * @author Marc Prud'hommeaux
+ */
+public interface ResultList
+ extends List, Serializable, Closeable
+{
+ /**
+ * Returns true if the provider backing this list is open.
+ */
+ public boolean isProviderOpen ();
+
+
+ /**
+ * Close the list.
+ */
+ public void close ();
+
+
+ /**
+ * Returns true if the list has been closed.
+ */
+ public boolean isClosed ();
+}
+
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultList.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultListIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultListIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultListIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultListIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+import java.util.*;
+
+import org.apache.openjpa.lib.util.*;
+
+/**
+ * Wrapper iterator that will return false for <code>hasNext()</code> if
+ * the owning ResultList has been closed.
+ *
+ * @author Marc Prud'hommeaux
+ * @nojavadoc
+ */
+public class ResultListIterator
+ extends AbstractListIterator
+{
+ private static final Localizer _loc = Localizer.forPackage (
+ ResultListIterator.class);
+
+ private final ListIterator _li;
+ private final ResultList _rl;
+
+
+ public ResultListIterator (ListIterator li, ResultList rl)
+ {
+ _li = li;
+ _rl = rl;
+ }
+
+
+ public ResultList getResultList ()
+ {
+ return _rl;
+ }
+
+
+ public boolean hasNext ()
+ {
+ if (_rl.isClosed ())
+ return false;
+ return _li.hasNext ();
+ }
+
+
+ public boolean hasPrevious ()
+ {
+ return _li.hasPrevious ();
+ }
+
+
+ public Object next ()
+ {
+ if (_rl.isClosed ())
+ throw new NoSuchElementException (_loc.get ("closed"));
+ return _li.next ();
+ }
+
+
+ public int nextIndex ()
+ {
+ return _li.nextIndex ();
+ }
+
+
+ public Object previous ()
+ {
+ return _li.previous ();
+ }
+
+
+ public int previousIndex ()
+ {
+ return _li.previousIndex ();
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultListIterator.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProvider.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProvider.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProvider.java Sat May 13 20:25:56 2006
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import org.apache.openjpa.lib.util.*;
+
+
+/**
+ * <p>Interface that allows lazy/custom instantiation of input
+ * objects.</p>
+ *
+ * <p>{@link ResultList} objects do not necessarily load in data all
+ * at once. Instead, they may lazily load objects as necessary. So,
+ * the lifespan of a {@link ResultObjectProvider} instance is
+ * related to how the application deals with processing the
+ * {@link ResultList} created with a given
+ * {@link ResultObjectProvider} instance.</p>
+ *
+ * @author Marc Prud'hommeaux
+ * @author Patrick Linskey
+ * @author Abe White
+ */
+public interface ResultObjectProvider
+ extends Closeable
+{
+ /**
+ * Return true if this provider supports random access.
+ */
+ public boolean supportsRandomAccess ();
+
+
+ /**
+ * Open the result. This will be called before
+ * {@link #next}, {@link #absolute}, or {@link #size}.
+ */
+ public void open ()
+ throws Exception;
+
+
+ /**
+ * Instantiate the current result object. This method will only be
+ * called after {@link #next} or {@link #absolute}.
+ */
+ public Object getResultObject ()
+ throws Exception;
+
+
+ /**
+ * Advance the input to the next position. Return <code>true</code> if
+ * there is more data; otherwise <code>false</code>.
+ */
+ public boolean next ()
+ throws Exception;
+
+
+ /**
+ * Move to the given 0-based position. This method is
+ * only called for providers that support random access.
+ * Return <code>true</code> if there is data at this position;
+ * otherwise <code>false</code>. This may be invoked in place of
+ * {@link #next}.
+ */
+ public boolean absolute (int pos)
+ throws Exception;
+
+
+ /**
+ * Return the number of items in the input, or {@link Integer#MAX_VALUE}
+ * if the size in unknown.
+ */
+ public int size ()
+ throws Exception;
+
+
+ /**
+ * Reset this provider. This is an optional operation. If supported,
+ * it should move the position of the provider to before the first
+ * element. Non-random-access providers may be able to support this
+ * method by re-acquiring all resources as if the result were
+ * just opened.
+ */
+ public void reset ()
+ throws Exception;
+
+
+ /**
+ * Free the resources associated with this provider.
+ */
+ public void close ()
+ throws Exception;
+
+
+ /**
+ * Any checked exceptions that are thrown will be passed to this method.
+ * The provider should re-throw the exception as an appropriate unchecked
+ * exception.
+ */
+ public void handleCheckedException (Exception e);
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProvider.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProviderIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProviderIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProviderIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProviderIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.util.*;
+
+import org.apache.openjpa.lib.util.*;
+
+
+/**
+ * <p>Iterator wrapped around a {@link ResultObjectProvider}.</p>
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class ResultObjectProviderIterator
+ implements Iterator, Closeable
+{
+ private final ResultObjectProvider _rop;
+ private Boolean _hasNext = null;
+ private Boolean _open = null;
+
+
+ /**
+ * Constructor. Supply object provider.
+ */
+ public ResultObjectProviderIterator (ResultObjectProvider rop)
+ {
+ _rop = rop;
+ }
+
+
+ /**
+ * Close the underlying result object provider.
+ */
+ public void close ()
+ {
+ if (_open == Boolean.TRUE)
+ {
+ try { _rop.close (); } catch (Exception e) {}
+ _open = Boolean.FALSE;
+ }
+ }
+
+
+ public void remove ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+
+ public boolean hasNext ()
+ {
+ if (_open == Boolean.FALSE)
+ return false;
+
+ if (_hasNext == null)
+ {
+ try
+ {
+ if (_open == null)
+ {
+ _rop.open ();
+ _open = Boolean.TRUE;
+ }
+ _hasNext = (_rop.next ()) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return false;
+ }
+ }
+
+ // close if we reach the end of the list
+ if (!_hasNext.booleanValue ())
+ {
+ close ();
+ return false;
+ }
+ return true;
+ }
+
+
+ public Object next ()
+ {
+ if (!hasNext ())
+ throw new NoSuchElementException ();
+ try
+ {
+ Object ret = _rop.getResultObject ();
+ _hasNext = null;
+ return ret;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return null;
+ }
+ }
+
+
+ protected void finalize ()
+ {
+ close ();
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/ResultObjectProviderIterator.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SimpleResultList.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SimpleResultList.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SimpleResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SimpleResultList.java Sat May 13 20:25:56 2006
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * <p>An almost stateless {@link ResultList} designed for use with result
+ * object providers backed by efficient random-access data structures, such
+ * as the {@link ListResultObjectProvider}. This result list does not
+ * perform any caching.</p>
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class SimpleResultList
+ extends AbstractNonSequentialResultList
+{
+ private final transient ResultObjectProvider _rop;
+ private boolean _closed = false;
+ private int _size = -1;
+
+
+ public SimpleResultList (ResultObjectProvider rop)
+ {
+ _rop = rop;
+ try
+ {
+ _rop.open ();
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ }
+ }
+
+
+ public boolean isProviderOpen ()
+ {
+ return !_closed;
+ }
+
+
+ public boolean isClosed ()
+ {
+ return _closed;
+ }
+
+
+ public void close ()
+ {
+ if (!_closed)
+ {
+ _closed = true;
+ try { _rop.close (); } catch (Exception e) {}
+ }
+ }
+
+
+ public Object getInternal (int index)
+ {
+ try
+ {
+ if (!_rop.absolute (index))
+ return PAST_END;
+ return _rop.getResultObject ();
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return PAST_END;
+ }
+ }
+
+
+ public int size ()
+ {
+ assertOpen ();
+ if (_size != -1)
+ return _size;
+ try
+ {
+ _size = _rop.size ();
+ return _size;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return -1;
+ }
+ }
+
+
+ public Object writeReplace ()
+ throws ObjectStreamException
+ {
+ if (_closed)
+ return this;
+
+ // load results into list
+ List list = new ArrayList ();
+ for (Iterator itr = iterator (); itr.hasNext ();)
+ list.add (itr.next ());
+ return list;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SimpleResultList.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SoftRandomAccessResultList.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SoftRandomAccessResultList.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SoftRandomAccessResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SoftRandomAccessResultList.java Sat May 13 20:25:56 2006
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.util.*;
+
+import org.apache.commons.collections.*;
+
+
+/**
+ * <p>Specialization of the {@link RandomAccessResultList} that only maintains
+ * soft references to instantiated objects.</p>
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class SoftRandomAccessResultList
+ extends RandomAccessResultList
+{
+ public SoftRandomAccessResultList (ResultObjectProvider rop)
+ {
+ super (rop);
+ }
+
+
+ protected Map newRowMap ()
+ {
+ return new ReferenceMap ();
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/SoftRandomAccessResultList.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/WindowResultList.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/WindowResultList.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/WindowResultList.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/WindowResultList.java Sat May 13 20:25:56 2006
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2006 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.openjpa.lib.rop;
+
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * <p>ResultList implementation that uses a forward-scrolling window of
+ * results.</p>
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class WindowResultList
+ extends AbstractNonSequentialResultList
+{
+ private static final int OPEN = 0;
+ private static final int FREED = 1;
+ private static final int CLOSED = 2;
+
+ private final Object[] _window;
+ private int _pos = -1;
+ private ResultObjectProvider _rop = null;
+ private boolean _random = false;
+ private int _state = OPEN;
+ private int _size = -1;
+
+
+ public WindowResultList (ResultObjectProvider rop)
+ {
+ this (rop, 10);
+ }
+
+
+ public WindowResultList (ResultObjectProvider rop, int windowSize)
+ {
+ _rop = rop;
+
+ if (windowSize <= 0)
+ windowSize = 10;
+ _window = new Object[windowSize];
+
+ try
+ {
+ _rop.open ();
+ _random = _rop.supportsRandomAccess ();
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ }
+ }
+
+
+ public boolean isProviderOpen ()
+ {
+ return _state == OPEN;
+ }
+
+
+ public boolean isClosed ()
+ {
+ return _state == CLOSED;
+ }
+
+
+ public void close ()
+ {
+ if (_state != CLOSED)
+ {
+ free ();
+ _state = CLOSED;
+ }
+ }
+
+
+ public int size ()
+ {
+ assertOpen ();
+ if (_size != -1)
+ return _size;
+ try
+ {
+ _size = _rop.size ();
+ return _size;
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return -1;
+ }
+ }
+
+
+ public Object getInternal (int index)
+ {
+ // out of range?
+ if (index < 0 || (_size != -1 && index >= _size))
+ return PAST_END;
+
+ try
+ {
+ // if this is before window range, move window back
+ if (index < _pos)
+ {
+ if (!_random || index == 0)
+ _rop.reset ();
+ _pos = -1;
+ }
+
+ // if this is the first get or past window range, move window
+ if (_pos == -1 || index >= _pos + _window.length)
+ {
+ // position result provider just before requested index
+ if (_random && index != 0)
+ {
+ if (!_rop.absolute (index - 1))
+ return PAST_END;
+ }
+ else
+ {
+ int begin = (_pos == -1) ? 0 : _pos + _window.length;
+ for (int i = begin; i < index; i++)
+ if (!_rop.next ())
+ return PAST_END;
+ }
+
+ // create window starting at requested index
+ int end = -1;
+ for (int i = 0; i < _window.length; i++)
+ {
+ if (end == -1 && !_rop.next ())
+ end = i;
+ _window[i] = (end == -1) ? _rop.getResultObject ()
+ : PAST_END;
+ }
+ _pos = index;
+
+ // if the window spans the entire result list, free
+ if (end != -1 && _pos == 0)
+ {
+ _size = end;
+ free ();
+ }
+ }
+
+ // grab result from window
+ return _window[index - _pos];
+ }
+ catch (RuntimeException re)
+ {
+ close ();
+ throw re;
+ }
+ catch (Exception e)
+ {
+ close ();
+ _rop.handleCheckedException (e);
+ return null;
+ }
+ }
+
+
+ private void free ()
+ {
+ if (_state == OPEN)
+ {
+ try { _rop.close (); } catch (Exception e) {}
+ _state = FREED;
+ }
+ }
+
+
+ public Object writeReplace ()
+ throws ObjectStreamException
+ {
+ if (_state != OPEN)
+ return this;
+
+ // load results into list
+ List list = new ArrayList ();
+ for (Iterator itr = iterator (); itr.hasNext ();)
+ list.add (itr.next ());
+ return list;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/WindowResultList.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/package.html
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/package.html?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/package.html (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/package.html Sat May 13 20:25:56 2006
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2006 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.
+ */
+<html>
+<body>
+ <p><strong>Result Object Provider Framework</strong></p>
+ <p>
+ This package provides a framework for the lazy loading of potentially
+ large lists of data.
+ </p>
+</body>
+</html>
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/rop/package.html
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/AbstractEventManager.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/AbstractEventManager.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/AbstractEventManager.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/AbstractEventManager.java Sat May 13 20:25:56 2006
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+
+import java.util.*;
+
+
+/**
+ * <p>Base event manager that handles adding/removing listeners
+ * and firing events. This class is reentrant-safe; listeners can be added
+ * and removed by other listeners when they receive events. The changes will
+ * not be visible until the event fire that initiated the recursive sequence
+ * of calls completes, however.</p>
+ *
+ * @author Abe White
+ */
+public abstract class AbstractEventManager
+{
+ private static Exception[] EMPTY_EXCEPTIONS = new Exception[0];
+
+ private boolean _firing = false;
+ private Collection _listeners = null;
+ private Collection _newListeners = null;
+
+
+ /**
+ * Register an event listener.
+ */
+ public synchronized void addListener (Object listener)
+ {
+ if (listener == null)
+ return;
+ if (_firing)
+ {
+ if (_newListeners == null)
+ _newListeners = newListenerCollection ();
+ _newListeners.addAll (_listeners);
+ _newListeners.add (listener);
+ }
+ else
+ {
+ if (_listeners == null)
+ _listeners = newListenerCollection ();
+ _listeners.add (listener);
+ }
+ }
+
+
+ /**
+ * Remove an event listener.
+ */
+ public synchronized boolean removeListener (Object listener)
+ {
+ if (listener == null)
+ return false;
+ if (_firing && _listeners.contains (listener))
+ {
+ if (_newListeners == null)
+ _newListeners = newListenerCollection ();
+ _newListeners.addAll (_listeners);
+ return _newListeners.remove (listener);
+ }
+ return _listeners != null && _listeners.remove (listener);
+ }
+
+
+ /**
+ * Return whether the given instance is in the list of listeners.
+ */
+ public synchronized boolean hasListener (Object listener)
+ {
+ return _listeners != null && _listeners.contains (listener);
+ }
+
+
+ /**
+ * Return true if there are any registered listeners.
+ */
+ public synchronized boolean hasListeners ()
+ {
+ return _listeners != null && !_listeners.isEmpty ();
+ }
+
+
+ /**
+ * Return a read-only list of listeners.
+ */
+ public synchronized Collection getListeners ()
+ {
+ return (_listeners == null) ? Collections.EMPTY_LIST
+ : Collections.unmodifiableCollection (_listeners);
+ }
+
+
+ /**
+ * Fire the given event to all listeners.
+ */
+ public synchronized Exception[] fireEvent (Object event)
+ {
+ if (_listeners == null || _listeners.isEmpty ())
+ return EMPTY_EXCEPTIONS;
+
+ boolean reentrant = _firing;
+ _firing = true;
+ List exceptions = null;
+ for (Iterator itr = _listeners.iterator (); itr.hasNext ();)
+ {
+ try
+ {
+ fireEvent (event, itr.next ());
+ }
+ catch (Exception e)
+ {
+ if (exceptions == null)
+ exceptions = new LinkedList ();
+ exceptions.add (e);
+ }
+ }
+
+ // if this wasn't a reentrant call, record that we're no longer
+ // in the process of firing events and replace our initial listener
+ // list with the set of new listeners
+ if (!reentrant)
+ {
+ _firing = false;
+ if (_newListeners != null)
+ _listeners = _newListeners;
+ _newListeners = null;
+ }
+
+ if (exceptions == null)
+ return EMPTY_EXCEPTIONS;
+ return (Exception[]) exceptions.toArray
+ (new Exception[exceptions.size ()]);
+ }
+
+
+ /**
+ * Implement this method to fire the given event to the given listener.
+ */
+ protected abstract void fireEvent (Object event, Object listener)
+ throws Exception;
+
+
+ /**
+ * Return a new container for listeners. Uses a linked list by default.
+ */
+ protected Collection newListenerCollection ()
+ {
+ return new LinkedList ();
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/AbstractEventManager.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Base16Encoder.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Base16Encoder.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Base16Encoder.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Base16Encoder.java Sat May 13 20:25:56 2006
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+
+/**
+ * <p>Base 16 encoder.</p>
+ *
+ * @author Marc Prud'hommeaux
+ * @nojavadoc
+ */
+public class Base16Encoder
+{
+ private final static char[] HEX = new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+
+ /**
+ * Convert bytes to a base16 string.
+ */
+ public static String encode (byte[] byteArray)
+ {
+ StringBuffer hexBuffer = new StringBuffer (byteArray.length * 2);
+ for (int i = 0; i < byteArray.length; i++)
+ for (int j = 1; j >= 0; j--)
+ hexBuffer.append (HEX[(byteArray[i] >> (j * 4)) & 0xF]);
+ return hexBuffer.toString ();
+ }
+
+
+ /**
+ * Convert a base16 string into a byte array.
+ */
+ public static byte[] decode (String s)
+ {
+ int len = s.length ();
+ byte[] r = new byte[len / 2];
+ for (int i = 0; i < r.length; i++)
+ {
+ int digit1 = s.charAt (i * 2), digit2 = s.charAt (i * 2 + 1);
+ if (digit1 >= '0' && digit1 <= '9')
+ digit1 -= '0';
+ else if (digit1 >= 'A' && digit1 <= 'F')
+ digit1 -= 'A' - 10;
+ if (digit2 >= '0' && digit2 <= '9')
+ digit2 -= '0';
+ else if (digit2 >= 'A' && digit2 <= 'F')
+ digit2 -= 'A' - 10;
+
+ r[i] = (byte) ((digit1 << 4) + digit2);
+ }
+ return r;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Base16Encoder.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/BytecodeWriter.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/BytecodeWriter.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/BytecodeWriter.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/BytecodeWriter.java Sat May 13 20:25:56 2006
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+import java.io.*;
+
+import serp.bytecode.*;
+
+
+/**
+ * Control how enhanced bytecode is written.
+ *
+ * @author Steve Kim
+ */
+public interface BytecodeWriter
+{
+ public void write (BCClass type)
+ throws IOException;
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/BytecodeWriter.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Closeable.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Closeable.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Closeable.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Closeable.java Sat May 13 20:25:56 2006
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+
+/**
+ * <p>Generic interface for components that can be closed so that helpers
+ * can treate them in a generic way.</p>
+ *
+ * @author Abe White
+ * @published
+ */
+public interface Closeable
+{
+ public void close ()
+ throws Exception;
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/Closeable.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/CodeFormat.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/CodeFormat.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/CodeFormat.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/CodeFormat.java Sat May 13 20:25:56 2006
@@ -0,0 +1,700 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+
+/**
+ * <p>Encapsulates some common Java source code formatting options. The
+ * class can also be used as a buffer for formatted Java code.</p>
+ *
+ * @author Abe White
+ */
+public final class CodeFormat
+ implements Cloneable
+{
+ private static final String _sep = System.getProperty ("line.separator");
+
+ private String _tab = "\t";
+ private boolean _spaceBeforeParen = false;
+ private boolean _spaceInParen = false;
+ private boolean _braceOnSameLine = true;
+ private boolean _braceAtSameTabLevel = false;
+ private boolean _scoreBeforeFieldName = false;
+ private int _linesBetweenSections = 2;
+
+ private StringBuffer _buf = new StringBuffer ();
+
+
+ /**
+ * The number of spaces to use for tabs; 0 means to use actual tab
+ * characters. Defaults to 0.
+ */
+ public int getTabSpaces ()
+ {
+ return (_tab.equals ("\t")) ? 0 : _tab.length ();
+ }
+
+
+ /**
+ * The number of spaces to use for tabs; 0 means to use actual tab
+ * characters. Defaults to 0.
+ */
+ public void setTabSpaces (int tab)
+ {
+ if (tab == 0)
+ _tab = "\t";
+ else
+ {
+ StringBuffer tabs = new StringBuffer (tab);
+ for (int i = 0; i < tab; i++)
+ tabs.append (" ");
+ _tab = tabs.toString ();
+ }
+ }
+
+
+ /**
+ * Whether to place a space before parentheses. Defaults to false.
+ */
+ public boolean getSpaceBeforeParen ()
+ {
+ return _spaceBeforeParen;
+ }
+
+
+ /**
+ * Whether to place a space before parentheses. Defaults to false.
+ */
+ public void setSpaceBeforeParen (boolean spaceBeforeParen)
+ {
+ _spaceBeforeParen = spaceBeforeParen;
+ }
+
+
+ /**
+ * Whether to place a space within parentheses. Defaults to false.
+ */
+ public boolean getSpaceInParen ()
+ {
+ return _spaceInParen;
+ }
+
+
+ /**
+ * Whether to place a space within parentheses. Defaults to false.
+ */
+ public void setSpaceInParen (boolean spaceInParen)
+ {
+ _spaceInParen = spaceInParen;
+ }
+
+
+ /**
+ * Whether to place opening braces on the same line as the
+ * block declaration, or on the next line. Defaults to same line.
+ */
+ public boolean getBraceOnSameLine ()
+ {
+ return _braceOnSameLine;
+ }
+
+
+ /**
+ * Whether to place opening braces on the same line as the
+ * block declaration, or on the next line. Defaults to same line.
+ */
+ public void setBraceOnSameLine (boolean braceOnSameLine)
+ {
+ _braceOnSameLine = braceOnSameLine;
+ }
+
+
+ /**
+ * Whether to place braces at the same tab level as the code within
+ * the block. Defaults to false.
+ */
+ public boolean getBraceAtSameTabLevel ()
+ {
+ return _braceAtSameTabLevel;
+ }
+
+
+ /**
+ * Whether to place braces at the same tab level as the code within
+ * the block. Defaults to false.
+ */
+ public void setBraceAtSameTabLevel (boolean braceAtSameTabLevel)
+ {
+ _braceAtSameTabLevel = braceAtSameTabLevel;
+ }
+
+
+ /**
+ * Whether to place an underscore before private field names. Defaults
+ * to false.
+ */
+ public boolean getScoreBeforeFieldName ()
+ {
+ return _scoreBeforeFieldName;
+ }
+
+
+ /**
+ * Whether to place an underscore before private field names. Defaults
+ * to false.
+ */
+ public void setScoreBeforeFieldName (boolean scoreBeforeFieldName)
+ {
+ _scoreBeforeFieldName = scoreBeforeFieldName;
+ }
+
+
+ /**
+ * The number of empty lines between code sections. Defaults to 2.
+ */
+ public int getLinesBetweenSections ()
+ {
+ return _linesBetweenSections;
+ }
+
+
+ /**
+ * The number of empty lines between sections. Defaults to 2.
+ */
+ public void setLinesBetweenSections (int linesBetweenSections)
+ {
+ _linesBetweenSections = linesBetweenSections;
+ }
+
+
+ /**
+ * Return a new line character.
+ */
+ public String getEndl ()
+ {
+ return getEndl (1);
+ }
+
+
+ /**
+ * Return the given number of new line characters.
+ */
+ public String getEndl (int num)
+ {
+ if (num == 0)
+ return "";
+ if (num == 1)
+ return _sep;
+
+ StringBuffer buf = new StringBuffer (_sep.length () * num);
+ for (int i = 0; i < num; i++)
+ buf.append (_sep);
+ return buf.toString ();
+ }
+
+
+ /**
+ * Return the given number of new line characters, followed by
+ * the given tab level indentation.
+ */
+ public String getEndl (int num, int tabs)
+ {
+ return getEndl (num) + getTab (tabs);
+ }
+
+
+ /**
+ * Return {#getLinesBetweenSections} + 1 new line characters.
+ */
+ public String getAfterSection ()
+ {
+ return getEndl (getLinesBetweenSections () + 1);
+ }
+
+
+ /**
+ * Open parentheses string. Users can choose to place spaces before
+ * and within parentheses.
+ */
+ public String getOpenParen (boolean methodOrIf)
+ {
+ if ((_spaceBeforeParen && methodOrIf) && _spaceInParen)
+ return " ( ";
+ if (_spaceBeforeParen && methodOrIf)
+ return " (";
+ if (_spaceInParen)
+ return "( ";
+ return "(";
+ }
+
+
+ /**
+ * Close parentheses string. Users can choose to place spaces within
+ * parentheses.
+ */
+ public String getCloseParen ()
+ {
+ if (_spaceInParen)
+ return " )";
+ return ")";
+ }
+
+
+ /**
+ * Paired parentheses for empty method parameters. Users can choose
+ * to place spaces before parentheses.
+ */
+ public String getParens ()
+ {
+ if (_spaceBeforeParen)
+ return " ()";
+ return "()";
+ }
+
+
+ /**
+ * Open brace string. Users can choose to place braces on the same
+ * line, or on a new line, and can choose the indenting level.
+ *
+ * @param tabLevel the tab level of code within the brace
+ */
+ public String getOpenBrace (int tabLevel)
+ {
+ if (_braceOnSameLine)
+ return " {";
+ if (_braceAtSameTabLevel)
+ return getEndl () + getTab (tabLevel) + "{";
+ return getEndl () + getTab (tabLevel - 1) + "{";
+ }
+
+
+ /**
+ * Close brace string. Users can choose to place braces on the same
+ * line, or on a new line, and can choose the indenting level.
+ *
+ * @param tabLevel the tab level of code within the brace
+ */
+ public String getCloseBrace (int tabLevel)
+ {
+ if (_braceAtSameTabLevel)
+ return getTab (tabLevel) + "}";
+ return getTab (tabLevel - 1) + "}";
+ }
+
+
+ /**
+ * Extends declaration. Uses configuration of {@link #openBrace},
+ * but prints "extends" instead of a brace.
+ */
+ public String getExtendsDec (int tabLevel)
+ {
+ if (_braceOnSameLine)
+ return " extends";
+ if (_braceAtSameTabLevel)
+ return getEndl () + getTab (tabLevel) + "extends";
+ return getEndl () + getTab (tabLevel) + "extends";
+ }
+
+
+ /**
+ * Implements declaration. Uses configuration of {@link #openBrace},
+ * but prints "implements" instead of a brace.
+ */
+ public String getImplementsDec (int tabLevel)
+ {
+ if (_braceOnSameLine)
+ return " implements";
+ if (_braceAtSameTabLevel)
+ return getEndl () + getTab (tabLevel) + "implements";
+ return getEndl () + getTab (tabLevel) + "implements";
+ }
+
+
+ /**
+ * Throws declaration. Uses configuration of {@link #openBrace},
+ * but prints "throws" instead of a brace.
+ */
+ public String getThrowsDec (int tabLevel)
+ {
+ if (_braceOnSameLine)
+ return " throws";
+ if (_braceAtSameTabLevel)
+ return getEndl () + getTab (tabLevel) + "throws";
+ return getEndl () + getTab (tabLevel) + "throws";
+ }
+
+
+ /**
+ * Tab string. Users can choose to use spaces or tab characters.
+ */
+ public String getTab ()
+ {
+ return getTab (1);
+ }
+
+
+ /**
+ * Tab string. Users can choose to use spaces or tab characters.
+ *
+ * @param tabLevel the number of tabs
+ */
+ public String getTab (int tabLevel)
+ {
+ if (tabLevel == 0)
+ return "";
+ if (tabLevel == 1)
+ return _tab;
+
+ StringBuffer tabs = new StringBuffer (_tab.length () * tabLevel);
+ for (int i = 0; i < tabLevel; i++)
+ tabs.append (_tab);
+ return tabs.toString ();
+ }
+
+
+ /**
+ * Return the field name for given suggested name, possibly adding
+ * leading underscore.
+ */
+ public String getFieldName (String fieldName)
+ {
+ return (_scoreBeforeFieldName) ? "_" + fieldName : fieldName;
+ }
+
+
+ /**
+ * Return the internal code buffer.
+ */
+ public StringBuffer getBuffer ()
+ {
+ return _buf;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (boolean val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (byte val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (char val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (double val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (float val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (int val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (long val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (short val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ */
+ public CodeFormat append (Object val)
+ {
+ _buf.append (val);
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getEndl()
+ */
+ public CodeFormat endl ()
+ {
+ _buf.append (getEndl ());
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getEndl(int)
+ */
+ public CodeFormat endl (int num)
+ {
+ _buf.append (getEndl (num));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getEndl(int, int)
+ */
+ public CodeFormat endl (int num, int tabs)
+ {
+ _buf.append (getEndl (num, tabs));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getAfterSection
+ */
+ public CodeFormat afterSection ()
+ {
+ _buf.append (getAfterSection ());
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getOpenParen
+ */
+ public CodeFormat openParen (boolean methodOrIf)
+ {
+ _buf.append (getOpenParen (methodOrIf));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getCloseParen
+ */
+ public CodeFormat closeParen ()
+ {
+ _buf.append (getCloseParen ());
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getParens
+ */
+ public CodeFormat parens ()
+ {
+ _buf.append (getParens ());
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getOpenBrace
+ */
+ public CodeFormat openBrace (int tabLevel)
+ {
+ _buf.append (getOpenBrace (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getCloseBrace
+ */
+ public CodeFormat closeBrace (int tabLevel)
+ {
+ _buf.append (getCloseBrace (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getExtendsDec
+ */
+ public CodeFormat extendsDec (int tabLevel)
+ {
+ _buf.append (getExtendsDec (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getImplementsDec
+ */
+ public CodeFormat implementsDec (int tabLevel)
+ {
+ _buf.append (getImplementsDec (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getThrowsDec
+ */
+ public CodeFormat throwsDec (int tabLevel)
+ {
+ _buf.append (getThrowsDec (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getTab
+ */
+ public CodeFormat tab ()
+ {
+ _buf.append (getTab ());
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getTab
+ */
+ public CodeFormat tab (int tabLevel)
+ {
+ _buf.append (getTab (tabLevel));
+ return this;
+ }
+
+
+ /**
+ * Append the given value to the internal buffer.
+ *
+ * @see #getFieldName
+ */
+ public CodeFormat fieldName (String name)
+ {
+ _buf.append (getFieldName (name));
+ return this;
+ }
+
+
+ /**
+ * Clear the internal code buffer.
+ */
+ public void clear ()
+ {
+ _buf = new StringBuffer ();
+ }
+
+
+ /**
+ * Return the internal buffer as a string.
+ */
+ public String toString ()
+ {
+ return _buf.toString ();
+ }
+
+
+ /**
+ * Return the length of the internal buffer.
+ */
+ public int length ()
+ {
+ return _buf.length ();
+ }
+
+
+ /**
+ * Make a copy of this code format object with all the same formatting
+ * settings.
+ */
+ public Object clone ()
+ {
+ CodeFormat format = new CodeFormat ();
+ format._tab = _tab;
+ format._spaceBeforeParen = _spaceBeforeParen;
+ format._spaceInParen = _spaceInParen;
+ format._braceOnSameLine = _braceOnSameLine;
+ format._braceAtSameTabLevel = _braceAtSameTabLevel;
+ format._scoreBeforeFieldName = _scoreBeforeFieldName;
+ format._linesBetweenSections = _linesBetweenSections;
+ return format;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/CodeFormat.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/ConcurrentHashMap.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/ConcurrentHashMap.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/ConcurrentHashMap.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/ConcurrentHashMap.java Sat May 13 20:25:56 2006
@@ -0,0 +1,965 @@
+/*
+ * Copyright 2006 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.openjpa.lib.util;
+
+
+/*
+ * @author Copyright (c) 1997 by WebLogic, Inc. All Rights Reserved.
+ */
+import java.io.*;
+import java.util.*;
+
+
+/** This class implements a HashMap which has limited synchronization.
+ * In particular mutators are generally synchronized while accessors
+ * are generally not. Additionally the Iterators returned by this
+ * class are not "fail-fast", but instead try to continue to iterate
+ * over the data structure after changes have been made.
+ *
+ * The synchronization semantics are built right in to the
+ * implementation rather than using a delegating wrapper like the
+ * other collection classes do because it wasn't clear to me that the
+ * how the two should be seperated or that it would be useful to do
+ * so. This can probably be a topic for further debate in the
+ * future.
+ *
+ * This class is based heavily on the HashMap class in the Java
+ * collections package. */
+public class ConcurrentHashMap extends AbstractMap
+ implements Map, Cloneable, Serializable
+{
+ private static Localizer _loc = Localizer.forPackage
+ (ConcurrentHashMap.class);
+
+ /**
+ * The default initial capacity - MUST be a power of two.
+ */
+ private static final int DEFAULT_INITIAL_CAPACITY = 16;
+
+ /**
+ * The maximum capacity, used if a higher value is implicitly specified
+ * by either of the constructors with arguments.
+ * MUST be a power of two <= 1<<30.
+ */
+ private static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /**
+ * The load fast used when none specified in constructor.
+ **/
+ private static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * Value representing null keys inside tables.
+ */
+ private static final Object NULL_KEY = new Object ();
+
+ /**
+ * The table, resized as necessary. Length MUST Always be a power of two.
+ */
+ private transient Entry[] table;
+
+ /**
+ * The number of key-value mappings contained in this identity hash map.
+ */
+ private transient int size;
+
+ /**
+ * The next size value at which to resize (capacity * load factor).
+ * @serial
+ */
+ private int threshold;
+
+ /**
+ * The load factor for the hash table.
+ *
+ * @serial
+ */
+ private final float loadFactor;
+
+ /**
+ * Constructs an empty <tt>ConcurrentHashMap</tt> with the specified initial
+ * capacity and load factor.
+ *
+ * @param initialCapacity The initial capacity.
+ * @param loadFactor The load factor.
+ * @throws IllegalArgumentException if the initial capacity is negative
+ * or the load factor is nonpositive.
+ */
+ public ConcurrentHashMap (int initialCapacity, float loadFactor)
+ {
+ if (initialCapacity < 0)
+ {
+ throw new IllegalArgumentException (_loc.get ("concurrent-initial",
+ initialCapacity + ""));
+ }
+ if (initialCapacity > MAXIMUM_CAPACITY)
+ initialCapacity = MAXIMUM_CAPACITY;
+ if (loadFactor <= 0 || loadFactor > 1)
+ {
+ throw new IllegalArgumentException (_loc.get ("concurrent-load",
+ loadFactor + ""));
+ }
+
+ // Find a power of 2 >= initialCapacity
+ int capacity = 1;
+ while (capacity < initialCapacity) capacity <<= 1;
+
+ this.loadFactor = loadFactor;
+ threshold = (int) (capacity * loadFactor);
+ table = new Entry[capacity];
+ }
+
+
+ /**
+ * Constructs an empty <tt>ConcurrentHashMap</tt> with the specified initial
+ * capacity and the default load factor (0.75).
+ *
+ * @param initialCapacity the initial capacity.
+ * @throws IllegalArgumentException if the initial capacity is negative.
+ */
+ public ConcurrentHashMap (int initialCapacity)
+ {
+ this (initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+
+ /**
+ * Constructs an empty <tt>ConcurrentHashMap</tt> with the default initial
+ * capacity (16) and the default load factor (0.75).
+ */
+ public ConcurrentHashMap ()
+ {
+ this (DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
+ }
+
+
+ /**
+ * Constructs a new <tt>ConcurrentHashMap</tt> with the same mappings as the
+ * specified <tt>Map</tt>. The <tt>ConcurrentHashMap</tt> is created with
+ * default load factor (0.75) and an initial capacity sufficient to
+ * hold the mappings in the specified <tt>Map</tt>.
+ *
+ * @param m the map whose mappings are to be placed in this map.
+ * @throws NullPointerException if the specified map is null.
+ */
+ public ConcurrentHashMap (Map m)
+ {
+ this (Math.max ( (int) (m.size () / DEFAULT_LOAD_FACTOR) + 1,
+ DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
+ putAll (m);
+ }
+
+
+ // internal utilities
+
+
+ /**
+ * Returns internal representation for key. Use NULL_KEY if key is null.
+ */
+ private static Object maskNull (Object key)
+ {
+ return (key == null ? NULL_KEY : key);
+ }
+
+
+ /**
+ * Returns key represented by specified internal representation.
+ */
+ private static Object unmaskNull (Object key)
+ {
+ return (key == NULL_KEY ? null : key);
+ }
+
+
+ /**
+ * Returns a hash code for non-null Object x.
+ */
+ private static int hash (Object x)
+ {
+ int h = x.hashCode ();
+ return h - (h << 7); // i.e., -127 * h
+ }
+
+
+ /**
+ * Check for equality of non-null reference x and possibly-null y.
+ */
+ private static boolean eq (Object x, Object y)
+ {
+ return x == y || x.equals (y);
+ }
+
+
+ /**
+ * Returns the current capacity of backing table in this map.
+ *
+ * @return the current capacity of backing table in this map.
+ */
+ public final int capacity ()
+ {
+ return table.length;
+ }
+
+ /**
+ * Returns the load factor for this map.
+ *
+ * @return the load factor for this map.
+ */
+ public final float loadFactor ()
+ {
+ return loadFactor;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map.
+ *
+ * @return the number of key-value mappings in this map.
+ */
+ public final int size ()
+ {
+ return size;
+ }
+
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ *
+ * @return <tt>true</tt> if this map contains no key-value mappings.
+ */
+ public final boolean isEmpty ()
+ {
+ return size == 0;
+ }
+
+
+ /**
+ * Returns the value to which the specified key is mapped in this identity
+ * hash map, or <tt>null</tt> if the map contains no mapping for this key.
+ * A return value of <tt>null</tt> does not <i>necessarily</i> indicate
+ * that the map contains no mapping for the key; it is also possible that
+ * the map explicitly maps the key to <tt>null</tt>. The
+ * <tt>containsKey</tt> method may be used to distinguish these two cases.
+ *
+ * @param key the key whose associated value is to be returned.
+ * @return the value to which this map maps the specified key, or
+ * <tt>null</tt> if the map contains no mapping for this
+ key.
+ * @see #put (Object, Object)
+ */
+ public Object get (Object key)
+ {
+ Entry e = getEntry (key);
+ return e == null? null: e.value;
+ }
+
+
+ /**
+ * Returns <tt>true</tt> if this map contains a mapping for the
+ * specified key.
+ *
+ * @param key The key whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map contains a mapping for the specified
+ * key.
+ */
+ public final boolean containsKey (Object key)
+ {
+ return getEntry (key) != null;
+ }
+
+
+ /**
+ * Returns the entry associated with the specified key in the
+ * ConcurrentHashMap. Returns null if the ConcurrentHashMap contains no
+ * mapping for this key.
+ */
+ protected Entry getEntry (Object key)
+ {
+ Object k = maskNull (key);
+ int hash = hash (k);
+ Entry[] tab = table;
+ for (Entry e = tab[hash & (tab.length-1)]; e != null; e = e.next)
+ {
+ if (e.hash == hash && eq (k, e.key)) return e;
+ }
+ return null;
+ }
+
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ * If the map previously contained a mapping for this key, the old
+ * value is replaced.
+ *
+ * @param key key with which the specified value is to be associated.
+ * @param value value to be associated with the specified key.
+ * @return previous value associated with specified key, or <tt>null</tt>
+ * if there was no mapping for key. A <tt>null</tt> return
+ * can also indicate that the ConcurrentHashMap previously
+ * associated
+ * <tt>null</tt> with the specified key.
+ */
+ public Object put (Object key, Object value)
+ {
+ Object k = maskNull (key);
+ int hash = hash (k);
+ synchronized (this)
+ {
+ int i = hash & (table.length - 1);
+
+ for (Entry e = table[i]; e != null; e = e.next)
+ {
+ if (e.hash == hash && eq (k, e.key))
+ {
+ Object oldValue = e.value;
+ e.value = value;
+ return oldValue;
+ }
+ }
+
+ table[i] = createEntry (hash, k, value, table[i]);
+ if (size++ >= threshold) resize (2 * table.length);
+ }
+ return null;
+ }
+
+
+ public Object putIfAbsent (Object key, Object value)
+ {
+ Object k = maskNull (key);
+ int hash = hash (k);
+ synchronized (this)
+ {
+ int i = hash & (table.length - 1);
+
+ for (Entry e = table[i]; e != null; e = e.next)
+ {
+ if (e.hash == hash && eq (k, e.key))
+ {
+ return e.value;
+ }
+ }
+
+ table[i] = createEntry (hash, k, value, table[i]);
+ if (size++ >= threshold) resize (2 * table.length);
+ }
+ return null;
+ }
+
+
+ /**
+ * Rehashes the contents of this map into a new <tt>ConcurrentHashMap</tt>
+ * instance with a larger capacity. This method is called automatically when
+ * the number of keys in this map exceeds its capacity and load factor.
+ *
+ * @param newCapacity the new capacity, MUST be a power of two.
+ */
+ private void resize (int newCapacity)
+ {
+ // assert (newCapacity & -newCapacity) == newCapacity; // power of 2
+ Entry[] oldTable = table;
+ int oldCapacity = oldTable.length;
+
+ // check if needed
+ if (size < threshold || oldCapacity > newCapacity) return;
+
+ Entry[] newTable = new Entry[newCapacity];
+ int mask = newCapacity-1;
+ for (int i = oldCapacity; i-- > 0; )
+ {
+ for (Entry e = oldTable[i]; e != null; e = e.next)
+ {
+ Entry clone = (Entry) e.clone ();
+ int j = clone.hash & mask;
+ clone.next = newTable[j];
+ newTable[j] = clone;
+ }
+ }
+ table = newTable;
+ threshold = (int) (newCapacity * loadFactor);
+ }
+
+
+ /**
+ * Copies all of the mappings from the specified map to this map
+ * These mappings will replace any mappings that
+ * this map had for any of the keys currently in the specified map.
+ *
+ * @param t mappings to be stored in this map.
+ * @throws NullPointerException if the specified map is null.
+ */
+ public final synchronized void putAll (Map t)
+ {
+ // Expand enough to hold t's elements without resizing.
+ int n = t.size ();
+ if (n == 0) return;
+ if (n >= threshold)
+ {
+ n = (int) (n / loadFactor + 1);
+ if (n > MAXIMUM_CAPACITY) n = MAXIMUM_CAPACITY;
+ int capacity = table.length;
+ while (capacity < n) capacity <<= 1;
+ resize (capacity);
+ }
+
+ for (Iterator i = t.entrySet ().iterator (); i.hasNext (); )
+ {
+ Map.Entry e = (Map.Entry) i.next ();
+ put (e.getKey (), e.getValue ());
+ }
+ }
+
+
+ /**
+ * Removes the mapping for this key from this map if present.
+ *
+ * @param key key whose mapping is to be removed from the map.
+ * @return previous value associated with specified key, or <tt>null</tt>
+ * if there was no mapping for key. A <tt>null</tt> return
+ * can also indicate that the map previously associated
+ * <tt>null</tt> with the specified key.
+ */
+ public Object remove (Object key)
+ {
+ Entry e = removeEntryForKey (key, null);
+ return (e == null ? e : e.value);
+ }
+
+
+ /**
+ * Removes the mapping for this key from this map if present and value
+ * equals the parameter value. If parameter value is null, behaves
+ * exactly like <code>remove (Object key)</code>.
+ *
+ * @param key key whose mapping is to be removed from the map.
+ * @param value value that is mapped to this key.
+ * @return <tt>true</tt> if the entry was removed, or <tt>false</tt>
+ * if there was no mapping for key or the key is not mapped to
+ * the parameter value.
+ */
+ public boolean remove (Object key, Object value)
+ {
+ Entry e = removeEntryForKey (key, value);
+ return (e == null ? false : true);
+ }
+
+
+ /**
+ * Removes and returns the entry associated with the specified key and value
+ * in the ConcurrentHashMap. If value is null, only matches the key.
+ * Returns null if the ConcurrentHashMap contains no mapping for this key or
+ * key is not mapped to the input value.
+ */
+ private Entry removeEntryForKey (Object key, Object v)
+ {
+ Object k = maskNull (key);
+ int hash = hash (k);
+ synchronized (this)
+ {
+ int i = hash & (table.length - 1);
+ Entry e = table[i];
+
+ if (e == null) return null;
+ if (e.hash == hash && eq (k, e.key) &&
+ (v == null || eq (v, e.value)))
+ {
+ size--;
+ table[i] = e.next;
+ return e;
+ }
+
+ Entry prev = e;
+ for (e = e.next; e != null; prev = e, e = e.next)
+ {
+ if (e.hash == hash && eq (k, e.key) &&
+ (v == null || eq (v, e.value)))
+ {
+ size--;
+ prev.next = e.next;
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Special version of remove for EntrySet.
+ */
+ private Entry removeMapping (Object o)
+ {
+ if (! (o instanceof Map.Entry)) return null;
+
+ Map.Entry entry = (Map.Entry) o;
+ Object k = maskNull (entry.getKey ());
+ int hash = hash (k);
+ synchronized (this)
+ {
+ int i = hash & (table.length - 1);
+ Entry e = table[i];
+
+ if (e == null) return null;
+ if (e.hash == hash && e.equals (entry))
+ {
+ size--;
+ table[i] = e.next;
+ return e;
+ }
+
+ Entry prev = e;
+ for (e = e.next; e != null; prev = e, e = e.next)
+ {
+ if (e.hash == hash && e.equals (entry))
+ {
+ size--;
+ prev.next = e.next;
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Removes all mappings from this map.
+ */
+ public synchronized void clear ()
+ {
+ table = new Entry[table.length];
+ size = 0;
+ }
+
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value.
+ *
+ * @param value value whose presence in this map is to be tested.
+ * @return <tt>true</tt> if this map maps one or more keys to the
+ * specified value.
+ */
+ public final boolean containsValue (Object value)
+ {
+ if (value == null) return containsNullValue ();
+
+ Entry tab[] = table;
+ for (int i = 0; i < tab.length ; i++)
+ {
+ for (Entry e = tab[i] ; e != null ; e = e.next)
+ {
+ if (value.equals (e.value)) return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Special-case code for containsValue with null argument
+ **/
+ private boolean containsNullValue ()
+ {
+ Entry tab[] = table;
+ for (int i = 0; i < tab.length ; i++)
+ {
+ for (Entry e = tab[i] ; e != null ; e = e.next)
+ {
+ if (e.value == null) return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns a shallow copy of this <tt>ConcurrentHashMap</tt> instance: the
+ * keys and values themselves are not cloned.
+ *
+ * @return a shallow copy of this map.
+ */
+ public final Object clone ()
+ {
+ return new ConcurrentHashMap (this);
+ }
+
+
+ protected Entry createEntry (int h, Object k, Object v, Entry n)
+ {
+ return new Entry (h, k, v, n);
+ }
+
+
+ protected static class Entry implements Map.Entry
+ {
+
+ final Object key;
+ Object value;
+ final int hash;
+ Entry next;
+
+ /**
+ * Create new entry.
+ */
+ protected Entry (int h, Object k, Object v, Entry n)
+ {
+ value = v;
+ next = n;
+ key = k;
+ hash = h;
+ }
+
+
+ public Object getKey ()
+ {
+ return unmaskNull (key);
+ }
+
+
+ public Object getValue ()
+ {
+ return value;
+ }
+
+
+ public Object setValue (Object newValue)
+ {
+ Object oldValue = value;
+ value = newValue;
+ return oldValue;
+ }
+
+
+ public boolean equals (Object o)
+ {
+ if (! (o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry) o;
+ Object k1 = getKey ();
+ Object k2 = e.getKey ();
+ if (k1 == k2 || (k1 != null && k1.equals (k2)))
+ {
+ Object v1 = getValue ();
+ Object v2 = e.getValue ();
+ if (v1 == v2 || (v1 != null && v1.equals (v2)))
+ return true;
+ }
+ return false;
+ }
+
+
+ public int hashCode ()
+ {
+ return (key==NULL_KEY ? 0 : key.hashCode ()) ^
+ (value==null ? 0 : value.hashCode ());
+ }
+
+
+ protected Object clone ()
+ {
+ // It is the callers responsibility to set the next field
+ // correctly.
+ return new Entry (hash, key, value, null);
+ }
+ }
+
+
+ private abstract class HashIterator implements Iterator
+ {
+ final Entry[] table = ConcurrentHashMap.this.table;
+ Entry next; // next entry to return
+ int index; // current slot
+ Entry current; // current entry
+
+ HashIterator ()
+ {
+ if (size == 0) return;
+ Entry[] t = table;
+ int i = t.length-1;
+ Entry n = t[i];
+ while (n == null && i > 0) n = t[--i];
+ index = i;
+ next = n;
+ }
+
+
+ public final boolean hasNext ()
+ {
+ return next != null;
+ }
+
+
+ final Entry nextEntry ()
+ {
+ Entry e = next;
+ if (e == null) throw new NoSuchElementException ();
+
+ Entry n = e.next;
+ Entry[] t = table;
+ int i = index;
+ while (n == null && i > 0) n = t[--i];
+ index = i;
+ next = n;
+ return current = e;
+ }
+
+
+ public final void remove ()
+ {
+ if (current == null) throw new IllegalStateException ();
+ Object k = current.key;
+ current = null;
+ ConcurrentHashMap.this.removeEntryForKey (k, null);
+ }
+ }
+
+
+ private final class ValueIterator extends HashIterator
+ {
+ public Object next ()
+ {
+ return nextEntry ().value;
+ }
+ }
+
+
+ private final class KeyIterator extends HashIterator
+ {
+ public Object next ()
+ {
+ return nextEntry ().getKey ();
+ }
+ }
+
+
+ private final class EntryIterator extends HashIterator
+ {
+ public Object next ()
+ {
+ return nextEntry ();
+ }
+ }
+
+
+ // Views
+
+ private transient Set entrySet = null;
+ private transient Set keySet = null;
+ private transient Collection values = null;
+
+ /**
+ * Returns a set view of the keys contained in this map. The set is
+ * backed by the map, so changes to the map are reflected in the set, and
+ * vice-versa. The set supports element removal, which removes the
+ * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
+ * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
+ * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * @return a set view of the keys contained in this map.
+ */
+ public final Set keySet ()
+ {
+ Set ks = keySet;
+ return (ks != null ? ks : (keySet = new KeySet ()));
+ }
+
+
+ private final class KeySet extends AbstractSet
+ {
+ public Iterator iterator ()
+ {
+ return new KeyIterator ();
+ }
+
+
+ public int size ()
+ {
+ return size;
+ }
+
+
+ public boolean contains (Object o)
+ {
+ return containsKey (o);
+ }
+
+
+ public boolean remove (Object o)
+ {
+ return ConcurrentHashMap.this.removeEntryForKey (o, null) != null;
+ }
+
+
+ public void clear ()
+ {
+ ConcurrentHashMap.this.clear ();
+ }
+ }
+
+
+ /**
+ * Returns a collection view of the values contained in this map. The
+ * collection is backed by the map, so changes to the map are reflected in
+ * the collection, and vice-versa. The collection supports element
+ * removal, which removes the corresponding mapping from this map, via the
+ * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
+ * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * @return a collection view of the values contained in this map.
+ */
+ public final Collection values ()
+ {
+ Collection vs = values;
+ return (vs != null ? vs : (values = new Values ()));
+ }
+
+
+ private final class Values extends AbstractCollection
+ {
+ public Iterator iterator ()
+ {
+ return new ValueIterator ();
+ }
+ public int size ()
+ {
+ return size;
+ }
+ public boolean contains (Object o)
+ {
+ return containsValue (o);
+ }
+ public void clear ()
+ {
+ ConcurrentHashMap.this.clear ();
+ }
+ }
+
+
+ /**
+ * Returns a collection view of the mappings contained in this map. Each
+ * element in the returned collection is a <tt>Map.Entry</tt>. The
+ * collection is backed by the map, so changes to the map are reflected in
+ * the collection, and vice-versa. The collection supports element
+ * removal, which removes the corresponding mapping from the map, via the
+ * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
+ * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * @return a collection view of the mappings contained in this map.
+ * @see Map.Entry
+ */
+ public final Set entrySet ()
+ {
+ Set es = entrySet;
+ return (es != null ? es : (entrySet = new EntrySet ()));
+ }
+
+
+ private final class EntrySet extends AbstractSet
+ {
+ public Iterator iterator ()
+ {
+ return new EntryIterator ();
+ }
+ public boolean contains (Object o)
+ {
+ if (! (o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry) o;
+ Entry candidate = getEntry (e.getKey ());
+ return candidate != null && candidate.equals (e);
+ }
+ public boolean remove (Object o)
+ {
+ return removeMapping (o) != null;
+ }
+ public int size ()
+ {
+ return size;
+ }
+ public void clear ()
+ {
+ ConcurrentHashMap.this.clear ();
+ }
+ }
+
+
+ /**
+ * Save the state of the <tt>ConcurrentHashMap</tt> instance to a stream
+ * (i.e., serialize it).
+ *
+ * @serialData The <i>capacity</i> of the ConcurrentHashMap (the length of
+ * the bucket array) is emitted (int), followed by the <i>size</i> of the
+ * ConcurrentHashMap (the number of key-value mappings), followed by the key
+ * (Object) and value (Object) for each key-value mapping represented by the
+ * ConcurrentHashMap The key-value mappings are emitted in the order that
+ * they are returned by <tt>entrySet ().iterator ()</tt>.
+ *
+ */
+ private void writeObject (ObjectOutputStream s)
+ throws IOException
+
+ {
+ // Write out the threshold, loadfactor, and any hidden stuff
+ s.defaultWriteObject ();
+
+ // Write out number of buckets
+ s.writeInt (table.length);
+
+ // Write out size (number of Mappings)
+ s.writeInt (size);
+
+ // Write out keys and values (alternating)
+ for (Iterator i = entrySet ().iterator (); i.hasNext (); )
+ {
+ Map.Entry e = (Map.Entry) i.next ();
+ s.writeObject (e.getKey ());
+ s.writeObject (e.getValue ());
+ }
+ }
+
+
+ private static final long serialVersionUID = -6452706556724125778L;
+
+ /**
+ * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a stream (i.e.,
+ * deserialize it).
+ */
+ private void readObject (ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+
+ {
+ // Read in the threshold, loadfactor, and any hidden stuff
+ s.defaultReadObject ();
+
+ // Read in number of buckets and allocate the bucket array;
+ int numBuckets = s.readInt ();
+ table = new Entry[numBuckets];
+
+ // Read in size (number of Mappings)
+ int size = s.readInt ();
+
+ // Read the keys and values, and put the mappings in the
+ // ConcurrentHashMap
+ for (int i=0; i<size; i++)
+ {
+ Object key = s.readObject ();
+ Object value = s.readObject ();
+ put (key, value);
+ }
+ }
+
+
+}
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/util/ConcurrentHashMap.java
------------------------------------------------------------------------------
svn:executable = *