Move to dynamically-created bytecode proxies for second class objects, rather

than checked-in proxy classes.  This allows us to proxy custom collection,
map, and bean types.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@484693 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-12-08 18:32:07 +00:00
parent db25f08565
commit e54b0c1908
41 changed files with 3148 additions and 2683 deletions

View File

@ -19,7 +19,6 @@ import java.sql.SQLException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@ -50,10 +49,9 @@ public class LRSProxyCollection
private final LRSCollectionFieldStrategy _strat;
public LRSProxyCollection(LRSCollectionFieldStrategy strat,
OpenJPAConfiguration conf) {
public LRSProxyCollection(LRSCollectionFieldStrategy strat) {
super(strat.getFieldMapping().getElement().getDeclaredType(),
strat.getFieldMapping().getOrderColumn() != null, conf);
strat.getFieldMapping().getOrderColumn() != null);
_strat = strat;
}

View File

@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@ -53,9 +52,9 @@ class LRSProxyMap
private final LRSMapFieldStrategy _strat;
public LRSProxyMap(LRSMapFieldStrategy strat, OpenJPAConfiguration conf) {
public LRSProxyMap(LRSMapFieldStrategy strat) {
super(strat.getFieldMapping().getKey().getDeclaredType(),
strat.getFieldMapping().getElement().getDeclaredType(), conf);
strat.getFieldMapping().getElement().getDeclaredType());
_strat = strat;
}

View File

@ -116,8 +116,7 @@ public abstract class MapTableFieldStrategy
JDBCFetchConfiguration fetch)
throws SQLException {
if (field.isLRS()) {
sm.storeObjectField(field.getIndex(), new LRSProxyMap(this,
store.getConfiguration()));
sm.storeObjectField(field.getIndex(), new LRSProxyMap(this));
return;
}

View File

@ -81,8 +81,8 @@ public class RelationCollectionInverseKeyFieldStrategy
return super.joinElementRelation(joins, elem);
}
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
return new LRSProxyCollection(this, conf);
protected Proxy newLRSProxy() {
return new LRSProxyCollection(this);
}
public void map(boolean adapt) {

View File

@ -80,8 +80,8 @@ public class RelationCollectionTableFieldStrategy
return super.joinElementRelation(joins, elem);
}
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
return new LRSProxyCollection(this, conf);
protected Proxy newLRSProxy() {
return new LRSProxyCollection(this);
}
public void map(boolean adapt) {

View File

@ -140,8 +140,8 @@ public class RelationMapInverseKeyFieldStrategy
return joinElementRelation(joins, val);
}
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
return new LRSProxyMap(this, conf);
protected Proxy newLRSProxy() {
return new LRSProxyMap(this);
}
protected void add(JDBCStore store, Object coll, Object obj) {

View File

@ -140,8 +140,8 @@ public class RelationMapTableFieldStrategy
return joinElementRelation(joins, val);
}
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
return new LRSProxyMap(this, conf);
protected Proxy newLRSProxy() {
return new LRSProxyMap(this);
}
protected void add(JDBCStore store, Object coll, Object obj) {

View File

@ -96,7 +96,7 @@ public abstract class StoreCollectionFieldStrategy
/**
* Return a large result set proxy for this field.
*/
protected abstract Proxy newLRSProxy(OpenJPAConfiguration conf);
protected abstract Proxy newLRSProxy();
/**
* Convert the field value to a collection. Handles collections and
@ -409,7 +409,7 @@ public abstract class StoreCollectionFieldStrategy
final JDBCFetchConfiguration fetch)
throws SQLException {
if (field.isLRS()) {
Proxy coll = newLRSProxy(store.getConfiguration());
Proxy coll = newLRSProxy();
// if this is ordered we need to know the next seq to use in case
// objects are added to the collection

View File

@ -123,6 +123,7 @@ class SingleFieldManager
proxy = getProxyManager().newCustomProxy(objval);
ret = proxy != null;
}
break;
}
if (proxy != null) {

View File

@ -18,9 +18,9 @@ package org.apache.openjpa.util;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import org.apache.commons.collections.map.IdentityMap;
import org.apache.commons.collections.set.MapBackedSet;
/**
@ -184,7 +184,7 @@ public abstract class AbstractChangeTracker
*/
protected Set newSet() {
if (_identity == Boolean.TRUE)
return MapBackedSet.decorate(new IdentityMap());
return MapBackedSet.decorate(new IdentityHashMap());
return new HashSet();
}
@ -218,14 +218,14 @@ public abstract class AbstractChangeTracker
if (identity && cur instanceof HashSet) {
if (cur.isEmpty())
return null;
Set replace = MapBackedSet.decorate(new IdentityMap());
Set replace = MapBackedSet.decorate(new IdentityHashMap());
replace.addAll(cur);
return replace;
}
if (!identity && !(cur instanceof HashSet) && cur instanceof Set) {
if (cur.isEmpty())
return null;
return new HashSet (cur);
return new HashSet(cur);
}
return cur;
}

View File

@ -26,7 +26,6 @@ import java.util.Set;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.iterators.FilterIterator;
import org.apache.commons.collections.iterators.IteratorChain;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.lib.util.Localizer;
@ -65,10 +64,9 @@ public abstract class AbstractLRSProxyCollection
* restrictions
* @param ordered true if this collection is ordered
*/
public AbstractLRSProxyCollection(Class elementType, boolean ordered,
OpenJPAConfiguration conf) {
public AbstractLRSProxyCollection(Class elementType, boolean ordered) {
_elementType = elementType;
_ct = new CollectionChangeTrackerImpl(this, false, ordered, conf);
_ct = new CollectionChangeTrackerImpl(this, false, ordered);
_ct.setAutoOff(false);
}
@ -109,13 +107,13 @@ public abstract class AbstractLRSProxyCollection
public boolean add(Object o) {
Proxies.assertAllowedType(o, _elementType);
Proxies.dirty(this);
Proxies.dirty(this, false);
_ct.added(o);
return true;
}
public boolean addAll(Collection all) {
Proxies.dirty(this);
Proxies.dirty(this, false);
boolean added = false;
Object add;
for (Iterator itr = all.iterator(); itr.hasNext();) {
@ -130,14 +128,14 @@ public abstract class AbstractLRSProxyCollection
public boolean remove(Object o) {
if (!contains(o))
return false;
Proxies.dirty(this);
Proxies.dirty(this, false);
Proxies.removed(this, o, false);
_ct.removed(o);
return true;
}
public boolean removeAll(Collection all) {
Proxies.dirty(this);
Proxies.dirty(this, false);
boolean removed = false;
Object rem;
for (Iterator itr = all.iterator(); itr.hasNext();) {
@ -157,7 +155,7 @@ public abstract class AbstractLRSProxyCollection
return true;
}
Proxies.dirty(this);
Proxies.dirty(this, false);
Itr itr = (Itr) iterator();
try {
boolean removed = false;
@ -177,7 +175,7 @@ public abstract class AbstractLRSProxyCollection
}
public void clear() {
Proxies.dirty(this);
Proxies.dirty(this, false);
Itr itr = (Itr) iterator();
try {
Object rem;
@ -394,7 +392,7 @@ public abstract class AbstractLRSProxyCollection
public void remove() {
if (_state == CLOSED || _last == null)
throw new NoSuchElementException();
Proxies.dirty(AbstractLRSProxyCollection.this);
Proxies.dirty(AbstractLRSProxyCollection.this, false);
_ct.removed(_last);
Proxies.removed(AbstractLRSProxyCollection.this, _last, false);
_last = null;

View File

@ -68,11 +68,10 @@ public abstract class AbstractLRSProxyMap
private int _count = -1;
private boolean _iterated = false;
public AbstractLRSProxyMap(Class keyType, Class valueType,
OpenJPAConfiguration conf) {
public AbstractLRSProxyMap(Class keyType, Class valueType) {
_keyType = keyType;
_valueType = valueType;
_ct = new MapChangeTrackerImpl(this, conf);
_ct = new MapChangeTrackerImpl(this);
_ct.setAutoOff(false);
}
@ -196,7 +195,7 @@ public abstract class AbstractLRSProxyMap
public Object put(Object key, Object value) {
Proxies.assertAllowedType(key, _keyType);
Proxies.assertAllowedType(value, _valueType);
Proxies.dirty(this);
Proxies.dirty(this, false);
if (_map == null)
_map = new HashMap();
Object old = _map.put(key, value);
@ -220,7 +219,7 @@ public abstract class AbstractLRSProxyMap
}
public Object remove(Object key) {
Proxies.dirty(this);
Proxies.dirty(this, false);
Object old = (_map == null) ? null : _map.remove(key);
if (old == null && (!_ct.getTrackKeys()
|| !_ct.getRemoved().contains(key)))
@ -234,7 +233,7 @@ public abstract class AbstractLRSProxyMap
}
public void clear() {
Proxies.dirty(this);
Proxies.dirty(this, false);
Itr itr = iterator(MODE_ENTRY);
try {
Map.Entry entry;
@ -482,7 +481,7 @@ public abstract class AbstractLRSProxyMap
if (_state == CLOSED || _last == null)
throw new NoSuchElementException();
Proxies.dirty(AbstractLRSProxyMap.this);
Proxies.dirty(AbstractLRSProxyMap.this, false);
Proxies.removed(AbstractLRSProxyMap.this, _last.getKey(), true);
Proxies.removed(AbstractLRSProxyMap.this, _last.getValue(), false);

View File

@ -18,8 +18,6 @@ package org.apache.openjpa.util;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.openjpa.conf.OpenJPAConfiguration;
/**
* Default {@link CollectionChangeTracker}.
*
@ -42,12 +40,26 @@ public class CollectionChangeTrackerImpl
* @param order true if the collection is ordered, false otherwise
*/
public CollectionChangeTrackerImpl(Collection coll, boolean dups,
boolean order, OpenJPAConfiguration conf) {
boolean order) {
_coll = coll;
_dups = dups;
_order = order;
}
/**
* Whether the underlying collection allows duplicates.
*/
public boolean allowsDuplicates() {
return _dups;
}
/**
* Whether the underlying collection is ordered.
*/
public boolean isOrdered() {
return _order;
}
public void added(Object elem) {
super.added(elem);
}

View File

@ -17,8 +17,6 @@ package org.apache.openjpa.util;
import java.util.Map;
import org.apache.openjpa.conf.OpenJPAConfiguration;
/**
* Default {@link MapChangeTracker}.
*
@ -35,7 +33,7 @@ public class MapChangeTrackerImpl
/**
* Constructor; supply delegate map.
*/
public MapChangeTrackerImpl(Map map, OpenJPAConfiguration conf) {
public MapChangeTrackerImpl(Map map) {
_map = map;
}

View File

@ -32,10 +32,6 @@ import org.apache.openjpa.lib.util.Localizer;
*/
public class Proxies {
public static final int MODE_ENTRY = 0;
public static final int MODE_KEY = 1;
public static final int MODE_VALUE = 2;
private static final Localizer _loc = Localizer.forPackage(Proxies.class);
/**
@ -64,14 +60,15 @@ public class Proxies {
/**
* Used by proxy types to dirty their owner.
*/
public static void dirty(Proxy proxy) {
public static void dirty(Proxy proxy, boolean stopTracking) {
if (proxy.getOwner() != null)
proxy.getOwner().dirty(proxy.getOwnerField());
if (stopTracking && proxy.getChangeTracker() != null)
proxy.getChangeTracker().stopTracking();
}
/**
* Used by proxy types to notify their owner that an element has been
* removed.
* Used by proxy types to notify collection owner on element removal.
*/
public static void removed(Proxy proxy, Object removed, boolean key) {
if (proxy.getOwner() != null && removed != null)
@ -79,172 +76,13 @@ public class Proxies {
}
/**
* Return an iterator that dirties its owner on calls to remove. This
* iterator assumes that the given proxy collection uses a
* {@link CollectionChangeTracker}.
* Used by proxy types to serialize non-proxy versions.
*/
public static Iterator iterator(final ProxyCollection proxy,
final Iterator itr) {
return new Iterator() {
private Object _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public Object next() {
_last = itr.next();
return _last;
}
public void remove() {
dirty(proxy);
itr.remove();
if (proxy.getChangeTracker() != null)
((CollectionChangeTracker) proxy.getChangeTracker()).
removed(_last);
removed(proxy, _last, false);
}
};
}
/**
* Return a proxy iterator that dirties its owner on remove, set, and
* add. This iterator assumes that the given proxy collection uses a
* {@link CollectionChangeTracker}.
*/
public static ListIterator listIterator(final ProxyCollection proxy,
final ListIterator itr, final Class allowed) {
return new ListIterator() {
private Object _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public int nextIndex() {
return itr.nextIndex();
}
public Object next() {
_last = itr.next();
return _last;
}
public boolean hasPrevious() {
return itr.hasPrevious();
}
public int previousIndex() {
return itr.previousIndex();
}
public Object previous() {
_last = itr.previous();
return _last;
}
public void set(Object o) {
assertAllowedType(o, allowed);
dirty(proxy);
itr.set(o);
if (proxy.getChangeTracker() != null)
proxy.getChangeTracker().stopTracking();
removed(proxy, _last, false);
_last = o;
}
public void add(Object o) {
assertAllowedType(o, allowed);
dirty(proxy);
itr.add(o);
if (proxy.getChangeTracker() != null) {
if (hasNext())
proxy.getChangeTracker().stopTracking();
else
((CollectionChangeTracker) proxy.getChangeTracker()).
added(o);
}
_last = o;
}
public void remove() {
dirty(proxy);
itr.remove();
if (proxy.getChangeTracker() != null)
((CollectionChangeTracker) proxy.getChangeTracker()).
removed(_last);
removed(proxy, _last, false);
}
};
}
/**
* Return a proxy for the given map key or entry set.
*/
public static Set entrySet(final ProxyMap proxy, final Set set,
final int mode) {
return new AbstractSet() {
public int size() {
return set.size();
}
public boolean remove(Object o) {
if (mode != MODE_KEY)
throw new UnsupportedOperationException();
Map map = (Map) proxy;
if (!map.containsKey(o))
return false;
map.remove(o);
return true;
}
public Iterator iterator() {
final Iterator itr = set.iterator();
return new Iterator() {
private Map.Entry _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public Object next() {
_last = (Map.Entry) itr.next();
switch (mode) {
case MODE_KEY:
return _last.getKey();
case MODE_VALUE:
return _last.getValue();
default:
return _last;
}
}
public void remove() {
dirty(proxy);
itr.remove();
if (proxy.getChangeTracker() != null)
((MapChangeTracker) proxy.getChangeTracker()).
removed(_last.getKey(), _last.getValue());
removed(proxy, _last.getKey(), true);
removed(proxy, _last.getValue(), false);
}
};
}
protected Object writeReplace()
throws ObjectStreamException {
switch (mode) {
case MODE_KEY:
return ((Map) proxy).keySet();
case MODE_VALUE:
return ((Map) proxy).values();
default:
return ((Map) proxy).entrySet();
}
}
};
public static Object writeReplace(Proxy proxy) {
if (proxy == null || proxy.getOwner() == null
|| proxy.getOwner().isDetached())
return proxy;
return proxy.copy(proxy);
}
}

View File

@ -1,192 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.ListIterator;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link ArrayList} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyArrayList
extends ArrayList
implements ProxyCollection {
private transient Class _elementType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient CollectionChangeTracker _ct = null;
public ProxyArrayList() {
}
public ProxyArrayList(Class elementType, boolean trackChanges,
OpenJPAConfiguration conf) {
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new ArrayList((Collection) orig);
}
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyArrayList(elementType, trackChanges, conf);
}
public void add(int index, Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
super.add(index, value);
}
public boolean add(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (super.add(value)) {
if (_ct != null)
_ct.added(value);
return true;
}
return false;
}
public boolean addAll(int index, Collection values) {
ensureCapacity(size() + values.size());
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
add(index, itr.next());
return values.size() > 0;
}
public boolean addAll(Collection values) {
ensureCapacity(size() + values.size());
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
return added;
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (int i = 0; i < size(); i++)
Proxies.removed(this, get(i), false);
super.clear();
}
public Iterator iterator() {
return Proxies.iterator(this, super.iterator());
}
public ListIterator listIterator() {
return Proxies.listIterator(this, super.listIterator(), _elementType);
}
public ListIterator listIterator(int index) {
return Proxies.listIterator(this, super.listIterator(index),
_elementType);
}
public Object remove(int index) {
Proxies.dirty(this);
Object rem = super.remove(index);
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
return rem;
}
public boolean remove(Object o) {
Proxies.dirty(this);
if (super.remove(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public boolean removeAll(Collection c) {
boolean removed = false;
for (Iterator itr = c.iterator(); itr.hasNext();)
removed = remove(itr.next()) || removed;
return removed;
}
public boolean retainAll(Collection c) {
int size = size();
for (Iterator itr = iterator(); itr.hasNext();)
if (!c.contains(itr.next()))
itr.remove();
return size() < size;
}
public Object set(int index, Object element) {
Proxies.assertAllowedType(element, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Object rem = super.set(index, element);
if (rem != element)
Proxies.removed(this, rem, false);
return rem;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -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.util;
/**
* Interface implemented by all generated custom types, which use JavaBean
* conventions for copying state.
*
* @author Abe White
*/
public interface ProxyBean
extends Proxy {
/**
* Create a new instance of this proxy type with the same state as the
* given instance.
*/
public ProxyBean newInstance(Object orig);
}

View File

@ -18,8 +18,8 @@ package org.apache.openjpa.util;
import java.util.TimeZone;
/**
* Interface implemented by all built-in proxies on
* {@link java.util.Calendar} types.
* Interface implemented by all generated proxies on {@link java.util.Calendar}
* types.
*
* @author Marc Prud'hommeaux
*/
@ -29,6 +29,5 @@ public interface ProxyCalendar
/**
* Return a new instance of this calendar type.
*/
public ProxyCalendar newInstance(TimeZone timeZone);
public ProxyCalendar newInstance();
}

View File

@ -18,23 +18,22 @@ package org.apache.openjpa.util;
import java.util.Collection;
import java.util.Comparator;
import org.apache.openjpa.conf.OpenJPAConfiguration;
/**
* Interface implemented by all built-in proxies on {@link Collection} types.
* Interface implemented by all proxy collection types.
*
* @author Abe White
*/
public interface ProxyCollection
extends Proxy {
extends Proxy, Collection {
/**
* This method should return a new proxy of the same concrete type as the
* implementing class. Used by the {@link ProxyManager} factories: one
* template instance of each type is created for the purpose of producing
* new instances via this method. Overcomes the performance penalties of
* reflection.
* The collection element type.
*/
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf);
public Class getElementType();
/**
* Create a new instance of this proxy type.
*/
public ProxyCollection newInstance(Class elementType, Comparator comp,
boolean trackChanges);
}

View File

@ -0,0 +1,468 @@
/*
* 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.util;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* Utility methods used by collection proxies.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyCollections
extends Proxies {
/**
* Call before invoking {@link List#add(int,Object)} on super.
*/
public static void beforeAdd(ProxyCollection coll, int index, Object value){
assertAllowedType(value, coll.getElementType());
dirty(coll, true);
}
/**
* Call before invoking {@link Vector#insertElementAt(Object,int)} on super.
*/
public static void beforeInsertElementAt(ProxyCollection coll, Object value,
int index) {
beforeAdd(coll, index, value);
}
/**
* Call before invoking {@link Collection#add(Object)} on super.
*/
public static void beforeAdd(ProxyCollection coll, Object value) {
assertAllowedType(value, coll.getElementType());
dirty(coll, false);
}
/**
* Call after invoking {@link Collection#add(Object)} on super.
*
* @param added whether the object was added
* @return <code>added</code>, for convenience
*/
public static boolean afterAdd(ProxyCollection coll, Object value,
boolean added) {
if (added && coll.getChangeTracker() != null)
((CollectionChangeTracker) coll.getChangeTracker()).added(value);
return added;
}
/**
* Call before invoking {@link Vector#addElement(Object)} on super.
*/
public static void beforeAddElement(ProxyCollection coll, Object value) {
beforeAdd(coll, value);
}
/**
* Call after invoking {@link Vector#addElement(Object)} on super.
*/
public static void afterAddElement(ProxyCollection coll, Object value) {
afterAdd(coll, value, true);
}
/**
* Call before invoking {@link LinkedList#addFirst(Object)} on super.
*/
public static void beforeAddFirst(ProxyCollection coll, Object value) {
beforeAdd(coll, 0, value);
}
/**
* Call before invoking {@link LinkedList#addLast(Object)} on super.
*/
public static void beforeAddLast(ProxyCollection coll, Object value) {
beforeAdd(coll, value);
}
/**
* Call after invoking {@link LinkedList#addLast(Object)} on super.
*/
public static void afterAddLast(ProxyCollection coll, Object value) {
afterAdd(coll, value, true);
}
/**
* Call before invoking {@link Queue#offer(Object)} on super.
*/
public static void beforeOffer(ProxyCollection coll, Object value) {
beforeAdd(coll, value);
}
/**
* Call after invoking {@link Queue#offer(Object)} on super.
*
* @param added whether the object was added
* @return <code>added</code>, for convenience
*/
public static boolean afterOffer(ProxyCollection coll, Object value,
boolean added) {
return afterAdd(coll, value, added);
}
/**
* Override for {@link List#addAll(int, Collection)}.
*/
public static boolean addAll(ProxyCollection coll, int index,
Collection values) {
List list = (List) coll;
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
list.add(index, itr.next());
return values.size() > 0;
}
/**
* Override for {@link Collection#addAll}.
*/
public static boolean addAll(ProxyCollection coll, Collection values) {
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added |= coll.add(itr.next());
return added;
}
/**
* Call before clearing collection.
*/
public static void beforeClear(ProxyCollection coll) {
dirty(coll, true);
for (Iterator itr = coll.iterator(); itr.hasNext();)
removed(coll, itr.next(), false);
}
/**
* Call before clearing vector.
*/
public static void beforeRemoveAllElements(ProxyCollection coll) {
beforeClear(coll);
}
/**
* Wrap given iterator in a proxy.
*/
public static Iterator afterIterator(final ProxyCollection coll,
final Iterator itr) {
// check for proxied; some coll impls delegate iterator methods
if (itr instanceof ProxyIterator)
return itr;
return new ProxyIterator() {
private Object _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public Object next() {
_last = itr.next();
return _last;
}
public void remove() {
dirty(coll, false);
itr.remove();
if (coll.getChangeTracker() != null)
((CollectionChangeTracker) coll.getChangeTracker()).
removed(_last);
Proxies.removed(coll, _last, false);
}
};
}
/**
* Wrap given iterator in a proxy.
*/
public static ListIterator afterListIterator(final ProxyCollection coll,
int idx, final ListIterator itr) {
return afterListIterator(coll, itr);
}
/**
* Wrap given iterator in a proxy.
*/
public static ListIterator afterListIterator(final ProxyCollection coll,
final ListIterator itr) {
// check for proxied; some coll impls delegate iterator methods
if (itr instanceof ProxyListIterator)
return itr;
return new ProxyListIterator() {
private Object _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public int nextIndex() {
return itr.nextIndex();
}
public Object next() {
_last = itr.next();
return _last;
}
public boolean hasPrevious() {
return itr.hasPrevious();
}
public int previousIndex() {
return itr.previousIndex();
}
public Object previous() {
_last = itr.previous();
return _last;
}
public void set(Object o) {
assertAllowedType(o, coll.getElementType());
dirty(coll, false);
itr.set(o);
if (coll.getChangeTracker() != null)
coll.getChangeTracker().stopTracking();
Proxies.removed(coll, _last, false);
_last = o;
}
public void add(Object o) {
assertAllowedType(o, coll.getElementType());
dirty(coll, false);
itr.add(o);
if (coll.getChangeTracker() != null) {
if (hasNext())
coll.getChangeTracker().stopTracking();
else
((CollectionChangeTracker) coll.getChangeTracker()).
added(o);
}
_last = o;
}
public void remove() {
dirty(coll, false);
itr.remove();
if (coll.getChangeTracker() != null)
((CollectionChangeTracker) coll.getChangeTracker()).
removed(_last);
Proxies.removed(coll, _last, false);
}
};
}
/**
* Call before invoking {@link List#remove(int)} on super.
*/
public static void beforeRemove(ProxyCollection coll, int index) {
dirty(coll, false);
}
/**
* Call after invoking {@link List#remove(int)} on super.
*
* @param removed the removed object
* @return the removed object, for convenience
*/
public static Object afterRemove(ProxyCollection coll, int index,
Object removed) {
if (coll.getChangeTracker() != null)
((CollectionChangeTracker)coll.getChangeTracker()).removed(removed);
removed(coll, removed, false);
return removed;
}
/**
* Call before invoking {@link Vector#removeElementAt(int)} on super.
*/
public static void beforeRemoveElementAt(ProxyCollection coll, int index) {
beforeRemove(coll, index);
}
/**
* Call before invoking {@link Collection#remove} on super.
*/
public static void beforeRemove(ProxyCollection coll, Object o) {
dirty(coll, false);
}
/**
* Call after invoking {@link Collection#remove} on super.
*
* @param removed whether the object was removed
* @return whether the object was removed, for convenience
*/
public static boolean afterRemove(ProxyCollection coll, Object o,
boolean removed){
if (!removed)
return false;
if (coll.getChangeTracker() != null)
((CollectionChangeTracker) coll.getChangeTracker()).removed(o);
removed(coll, o, false);
return true;
}
/**
* Call before invoking {@link Vector#removeElement} on super.
*/
public static void beforeRemoveElement(ProxyCollection coll, Object o) {
beforeRemove(coll, o);
}
/**
* Call after invoking {@link Vector#removeElement} on super.
*/
public static boolean afterRemoveElement(ProxyCollection coll, Object o,
boolean removed) {
return afterRemove(coll, o, removed);
}
/**
* Call before invoking {@link LinkedList#removeFirst} on super.
*/
public static void beforeRemoveFirst(ProxyCollection coll) {
beforeRemove(coll, 0);
}
/**
* Call after invoking {@link LinkedList#removeFirst} on super.
*/
public static Object afterRemoveFirst(ProxyCollection coll, Object removed){
return afterRemove(coll, 0, removed);
}
/**
* Call after invoking {@link LinkedList#removeLast} on super.
*/
public static void beforeRemoveLast(ProxyCollection coll) {
beforeRemove(coll, coll.size() - 1);
}
/**
* Call after invoking {@link LinkedList#removeLast} on super.
*/
public static Object afterRemoveLast(ProxyCollection coll, Object removed) {
return afterRemove(coll, coll.size(), removed);
}
/**
* Call before invoking {@link Queue#remove} on super.
*/
public static void beforeRemove(ProxyCollection coll) {
beforeRemove(coll, 0);
}
/**
* Call after invoking {@link Queue#remove} on super.
*/
public static Object afterRemove(ProxyCollection coll, Object removed){
return afterRemove(coll, 0, removed);
}
/**
* Call before invoking {@link Queue#poll} on super.
*/
public static void beforePoll(ProxyCollection coll) {
if (!coll.isEmpty())
beforeRemove(coll, 0);
}
/**
* Call after invoking {@link Queue#poll} on super.
*/
public static Object afterPoll(ProxyCollection coll, Object removed) {
if (removed != null)
afterRemove(coll, 0, removed);
return removed;
}
/**
* Override for {@link Collection#removeAll}.
*/
public static boolean removeAll(ProxyCollection coll, Collection vals) {
boolean removed = false;
for (Iterator itr = vals.iterator(); itr.hasNext();)
removed |= coll.remove(itr.next());
return removed;
}
/**
* Override for {@link Collection#retainAll}.
*/
public static boolean retainAll(ProxyCollection coll, Collection vals) {
int size = coll.size();
for (Iterator itr = coll.iterator(); itr.hasNext();)
if (!vals.contains(itr.next()))
itr.remove();
return coll.size() < size;
}
/**
* Call before invoking {@link List#set} on super.
*/
public static void beforeSet(ProxyCollection coll, int index,
Object element) {
assertAllowedType(element, coll.getElementType());
dirty(coll, true);
}
/**
* Call after invoking {@link List#set} on super.
*
* @param replaced the replaced object
* @return the replaced object, for convenience
*/
public static Object afterSet(ProxyCollection coll, int index,
Object element, Object replaced) {
if (replaced != element)
removed(coll, replaced, false);
return replaced;
}
/**
* Call before invoking {@link Vector#setElementAt} on super.
*/
public static void beforeSetElementAt(ProxyCollection coll, Object element,
int index) {
beforeSet(coll, index, element);
}
/**
* Call after invoking {@link Vector#setElementAt} on super.
*/
public static Object afterSetElementAt(ProxyCollection coll, Object element,
int index, Object replaced) {
return afterSet(coll, index, element, replaced);
}
/**
* Marker interface for a proxied iterator.
*/
public static interface ProxyIterator
extends Iterator {
}
/**
* Marker interface for a proxied list iterator.
*/
public static interface ProxyListIterator
extends ProxyIterator, ListIterator {
}
}

View File

@ -16,7 +16,7 @@
package org.apache.openjpa.util;
/**
* Interface implemented by all built-in proxies on {@link java.util.Date}
* Interface implemented by all generated proxies on {@link java.util.Date}
* types.
*
* @author Abe White

View File

@ -1,177 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Calendar} type that calls the <code>dirty</code>
* method on its owning persistence capable instance on modification. This
* class does not support modification via any deprecated method of the
* date class.
*
* @author Marc Prud'hommeaux
* @nojavadoc
*/
public class ProxyGregorianCalendar
extends GregorianCalendar
implements ProxyCalendar {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
public ProxyGregorianCalendar() {
super();
}
public ProxyGregorianCalendar(int year, int month, int dayOfMonth) {
super(year, month, dayOfMonth);
}
public ProxyGregorianCalendar(int year, int month, int dayOfMonth,
int hourOfDay, int minute) {
super(year, month, dayOfMonth, hourOfDay, minute);
}
public ProxyGregorianCalendar(int year, int month, int dayOfMonth,
int hourOfDay, int minute, int second) {
super(year, month, dayOfMonth, hourOfDay, minute, second);
}
public ProxyGregorianCalendar(Locale aLocale) {
super(aLocale);
}
public ProxyGregorianCalendar(TimeZone zone) {
super(zone);
}
public ProxyGregorianCalendar(TimeZone zone, Locale aLocale) {
super(zone, aLocale);
}
public ProxyCalendar newInstance(TimeZone timeZone) {
if (timeZone == null)
return new ProxyGregorianCalendar();
else
return new ProxyGregorianCalendar(timeZone);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return null;
}
public Object copy(Object orig) {
Calendar origCal = (Calendar) orig;
GregorianCalendar cal = new GregorianCalendar(origCal.getTimeZone());
cal.setTime(origCal.getTime());
return cal;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
protected void computeFields() {
// Calendar.computeFields() is called whenever a mutation
// occurs in order to recalculate all the fields
Proxies.dirty(this);
super.computeFields();
}
public void setTimeInMillis(long millis) {
if (millis != getTimeInMillis()) {
Proxies.dirty(this);
super.setTimeInMillis(millis);
}
}
public void set(int field, int value) {
if (get(field) != value) {
Proxies.dirty(this);
super.set(field, value);
}
}
public void add(int field, int amount) {
if (amount != 0) {
Proxies.dirty(this);
super.add(field, amount);
}
}
public void roll(int field, boolean up) {
Proxies.dirty(this);
super.roll(field, up);
}
public void roll(int field, int amount) {
if (amount != 0) {
Proxies.dirty(this);
super.roll(field, amount);
}
}
public void setTimeZone(TimeZone value) {
Proxies.dirty(this);
super.setTimeZone(value);
}
public void setLenient(boolean lenient) {
if (isLenient() != lenient) {
Proxies.dirty(this);
super.setLenient(lenient);
}
}
public void setFirstDayOfWeek(int value) {
if (getFirstDayOfWeek() != value) {
Proxies.dirty(this);
super.setFirstDayOfWeek(value);
}
}
public void setMinimalDaysInFirstWeek(int value) {
if (getMinimalDaysInFirstWeek() != value) {
Proxies.dirty(this);
super.setMinimalDaysInFirstWeek(value);
}
}
}

View File

@ -1,154 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link HashMap} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyHashMap
extends HashMap
implements ProxyMap {
private transient Class _keyType = null;
private transient Class _valueType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient MapChangeTracker _ct = null;
public ProxyHashMap() {
}
public ProxyHashMap(Class keyType, Class valueType, boolean trackChanges,
OpenJPAConfiguration conf) {
_keyType = keyType;
_valueType = valueType;
if (trackChanges)
_ct = new MapChangeTrackerImpl(this, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new HashMap((Map) orig);
}
public ProxyMap newInstance(Class keyType, Class valueType,
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyHashMap(keyType, valueType, trackChanges, conf);
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Map.Entry entry;
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
Proxies.removed(this, entry.getKey(), true);
Proxies.removed(this, entry.getValue(), false);
}
super.clear();
}
public Set keySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
}
public Collection values() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
}
public Set entrySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
}
public Object put(Object key, Object value) {
Proxies.assertAllowedType(key, _keyType);
Proxies.assertAllowedType(value, _valueType);
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.put(key, value);
if (had) {
if (_ct != null)
_ct.changed(key, old, value);
Proxies.removed(this, old, false);
} else if (_ct != null)
_ct.added(key, value);
return old;
}
public void putAll(Map m) {
Map.Entry entry;
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
put(entry.getKey(), entry.getValue());
}
}
public Object remove(Object key) {
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.remove(key);
if (had) {
if (_ct != null)
_ct.removed(key, old);
Proxies.removed(this, key, true);
Proxies.removed(this, old, false);
}
return old;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,146 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link HashSet} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyHashSet
extends HashSet
implements ProxyCollection {
private transient Class _elementType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient CollectionChangeTracker _ct = null;
public ProxyHashSet() {
}
public ProxyHashSet(Class elementType, boolean trackChanges,
OpenJPAConfiguration conf) {
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new HashSet((Collection) orig);
}
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyHashSet(elementType, trackChanges, conf);
}
public boolean add(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (super.add(value)) {
if (_ct != null)
_ct.added(value);
return true;
}
return false;
}
public boolean addAll(Collection values) {
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
return added;
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (Iterator itr = super.iterator(); itr.hasNext();)
Proxies.removed(this, itr.next(), false);
super.clear();
}
public Iterator iterator() {
return Proxies.iterator(this, super.iterator());
}
public boolean remove(Object o) {
Proxies.dirty(this);
if (super.remove(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public boolean removeAll(Collection c) {
boolean removed = false;
for (Iterator itr = c.iterator(); itr.hasNext();)
removed = remove(itr.next()) || removed;
return removed;
}
public boolean retainAll(Collection c) {
int size = size();
for (Iterator itr = iterator(); itr.hasNext();)
if (!c.contains(itr.next()))
itr.remove();
return size() < size;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,154 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Hashtable} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyHashtable
extends Hashtable
implements ProxyMap {
private transient Class _keyType = null;
private transient Class _valueType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient MapChangeTracker _ct = null;
public ProxyHashtable() {
}
public ProxyHashtable(Class keyType, Class valueType, boolean trackChanges,
OpenJPAConfiguration conf) {
_keyType = keyType;
_valueType = valueType;
if (trackChanges)
_ct = new MapChangeTrackerImpl(this, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new Hashtable((Map) orig);
}
public ProxyMap newInstance(Class keyType, Class valueType,
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyHashtable(keyType, valueType, trackChanges, conf);
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Map.Entry entry;
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
Proxies.removed(this, entry.getKey(), true);
Proxies.removed(this, entry.getValue(), false);
}
super.clear();
}
public Set keySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
}
public Collection values() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
}
public Set entrySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
}
public Object put(Object key, Object value) {
Proxies.assertAllowedType(key, _keyType);
Proxies.assertAllowedType(value, _valueType);
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.put(key, value);
if (had) {
if (_ct != null)
_ct.changed(key, old, value);
Proxies.removed(this, old, false);
} else if (_ct != null)
_ct.added(key, value);
return old;
}
public void putAll(Map m) {
Map.Entry entry;
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
put(entry.getKey(), entry.getValue());
}
}
public Object remove(Object key) {
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.remove(key);
if (had) {
if (_ct != null)
_ct.removed(key, old);
Proxies.removed(this, key, true);
Proxies.removed(this, old, false);
}
return old;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,224 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link LinkedList} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyLinkedList
extends LinkedList
implements ProxyCollection {
private transient Class _elementType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient CollectionChangeTracker _ct = null;
public ProxyLinkedList() {
}
public ProxyLinkedList(Class elementType, boolean trackChanges,
OpenJPAConfiguration conf) {
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new LinkedList((Collection) orig);
}
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyLinkedList(elementType, trackChanges, conf);
}
public void add(int index, Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
super.add(index, value);
}
public boolean add(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (super.add(value)) {
if (_ct != null)
_ct.added(value);
return true;
}
return false;
}
public void addFirst(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
super.addFirst(value);
if (_ct != null)
_ct.stopTracking();
}
public void addLast(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
super.addLast(value);
if (_ct != null)
_ct.added(value);
}
public boolean addAll(int index, Collection values) {
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
add(index, itr.next());
return values.size() > 0;
}
public boolean addAll(Collection values) {
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
return added;
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (Iterator itr = super.iterator(); itr.hasNext();)
Proxies.removed(this, itr.next(), false);
super.clear();
}
public Iterator iterator() {
return Proxies.iterator(this, super.iterator());
}
public ListIterator listIterator() {
return Proxies.listIterator(this, super.listIterator(), _elementType);
}
public ListIterator listIterator(int index) {
return Proxies.listIterator(this, super.listIterator(index),
_elementType);
}
public Object remove(int index) {
Proxies.dirty(this);
Object rem = super.remove(index);
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
return rem;
}
public boolean remove(Object o) {
Proxies.dirty(this);
if (super.remove(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public Object removeFirst() {
Proxies.dirty(this);
Object rem = super.removeFirst();
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
return rem;
}
public Object removeLast() {
Proxies.dirty(this);
Object rem = super.removeLast();
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
return rem;
}
public boolean removeAll(Collection c) {
boolean removed = false;
for (Iterator itr = c.iterator(); itr.hasNext();)
removed = remove(itr.next()) || removed;
return removed;
}
public boolean retainAll(Collection c) {
int size = size();
for (Iterator itr = iterator(); itr.hasNext();)
if (!c.contains(itr.next()))
itr.remove();
return size() < size;
}
public Object set(int index, Object element) {
Proxies.assertAllowedType(element, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Object rem = super.set(index, element);
if (rem != element)
Proxies.removed(this, rem, false);
return rem;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -40,32 +40,6 @@ import java.util.TimeZone;
*/
public interface ProxyManager {
/**
* Return a copy of the given date with the same information.
*/
public Date copyDate(Date orig);
/**
* Return a copy of the given Calendar with the same information.
*/
public Calendar copyCalendar(Calendar orig);
/**
* Return a new collection of the same type as the given one
* with a copy of all contained elements.
* If the given owner is non-null, the returned value should be a proxy
* for the given owner, otherwise it should not be a proxy.
*/
public Collection copyCollection(Collection orig);
/**
* Return a new map of the same type as the given one
* with a copy of all contained key/value pairs.
* If the given owner is non-null, the returned value should be a proxy
* for the given owner, otherwise it should not be a proxy.
*/
public Map copyMap(Map orig);
/**
* Return a new array of the same component type as the given array
* and containing the same elements. Works for both primitive and
@ -74,25 +48,31 @@ public interface ProxyManager {
public Object copyArray(Object orig);
/**
* Return a copy of the given object with the same
* information. If this manager cannot proxy the given type, return null.
* If the given owner is non-null, the returned value should be a proxy
* for the given owner, otherwise it should not be a proxy.
*
* @since 0.2.5
* Return a copy of the given date with the same information.
*/
public Object copyCustom(Object orig);
public Date copyDate(Date orig);
/**
* Return a new date proxy.
*/
public Proxy newDateProxy(Class type);
/**
* Return a copy of the given calendar with the same information.
*/
public Calendar copyCalendar(Calendar orig);
/**
* Return a new calendar proxy.
*/
public Proxy newCalendarProxy(Class type, TimeZone timeZone);
/**
* Return a new collection of the same type as the given one
* with a copy of all contained elements.
*/
public Collection copyCollection(Collection orig);
/**
* Return a proxy for the given collection type. The returned collection
* will allow only addition of elements assignable from the given
@ -101,6 +81,12 @@ public interface ProxyManager {
public Proxy newCollectionProxy(Class type, Class elementType,
Comparator compare);
/**
* Return a new map of the same type as the given one
* with a copy of all contained key/value pairs.
*/
public Map copyMap(Map orig);
/**
* Return a proxy for the given map type. The returned map will
* allow only addition of keys/values assignable from the given
@ -109,6 +95,14 @@ public interface ProxyManager {
public Proxy newMapProxy(Class type, Class keyType, Class valueType,
Comparator compare);
/**
* Return a copy of the given object with the same information, or null if
* this manager cannot copy the object.
*
* @since 0.2.5
*/
public Object copyCustom(Object orig);
/**
* Return a proxy for the given object, or null if this manager cannot
* proxy the object.

View File

@ -18,23 +18,27 @@ package org.apache.openjpa.util;
import java.util.Comparator;
import java.util.Map;
import org.apache.openjpa.conf.OpenJPAConfiguration;
/**
* Interface implemented by all built-in proxies on {@link Map} types.
* Interface implemented by proxies on {@link Map} types.
*
* @author Abe White
*/
public interface ProxyMap
extends Proxy {
extends Proxy, Map {
/**
* This method should return a new proxy of the same concrete type as the
* implementing class. Used by the {@link ProxyManager} factories: one
* template instance of each type is created for the purpose of producing
* new instances via this method. Overcomes the performance
* penalties of reflection.
* The map key type.
*/
public Class getKeyType();
/**
* The map value type.
*/
public Class getValueType();
/**
* Create a new instance of this proxy type.
*/
public ProxyMap newInstance(Class keyType, Class valueType,
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf);
Comparator compare, boolean trackChanges);
}

View File

@ -0,0 +1,282 @@
/*
* 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.util;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Map;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
/**
* Utility methods used by map proxies.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyMaps
extends Proxies {
/**
* Call before invoking {@link Map#clear} on super.
*/
public static void beforeClear(ProxyMap map) {
dirty(map, true);
Map.Entry entry;
for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
removed(map, entry.getKey(), true);
removed(map, entry.getValue(), false);
}
}
/**
* Override for {@link Map#keySet}.
*/
public static Set keySet(ProxyMap map) {
ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
entries.setView(ProxyEntrySet.VIEW_KEYS);
return entries;
}
/**
* Override for {@link Map#values}.
*/
public static Collection values(ProxyMap map) {
ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
entries.setView(ProxyEntrySet.VIEW_VALUES);
return entries;
}
/**
* Wrap the given entry set in a proxy.
*/
public static Set afterEntrySet(ProxyMap map, Set entries) {
return new ProxyEntrySetImpl(map, entries);
}
/**
* Call before invoking {@link Map#put} on super.
*/
public static boolean beforePut(ProxyMap map, Object key, Object value) {
assertAllowedType(key, map.getKeyType());
assertAllowedType(value, map.getValueType());
dirty(map, false);
return map.containsKey(key);
}
/**
* Call after invoking {@link Map#put} on super.
*
* @param ret the return value from the super's method
* @param before the return value from {@link #beforePut}
* @return the value to return from {@link Map#put}
*/
public static Object afterPut(ProxyMap map, Object key, Object value,
Object ret, boolean before) {
if (before) {
if (map.getChangeTracker() != null)
((MapChangeTracker) map.getChangeTracker()).changed(key, ret,
value);
removed(map, ret, false);
} else if (map.getChangeTracker() != null)
((MapChangeTracker) map.getChangeTracker()).added(key, value);
return ret;
}
/**
* Call before invoking {@link Properties#setProperty} on super.
*/
public static boolean beforeSetProperty(ProxyMap map, String key,
String value) {
return beforePut(map, key, value);
}
/**
* Call after invoking {@link Properties#setProperty} on super.
*
* @param ret the return value from the super's method
* @param before the return value from {@link #beforeSetProperty}
* @return the value to return from {@link Properties#setProperty}
*/
public static Object afterSetProperty(ProxyMap map, String key,
String value, Object ret, boolean before) {
return afterPut(map, key, value, ret, before);
}
/**
* Call before invoking {@link Properties#load} on super.
*/
public static void beforeLoad(ProxyMap map, InputStream in) {
dirty(map, true);
}
/**
* Call before invoking {@link Properties#loadXML} on super.
*/
public static void beforeLoadFromXML(ProxyMap map, InputStream in) {
dirty(map, true);
}
/**
* Overload for {@link Map#putAll}.
*/
public static void putAll(ProxyMap map, Map values) {
Map.Entry entry;
for (Iterator itr = values.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
map.put(entry.getKey(), entry.getValue());
}
}
/**
* Call before invoking {@link Map#remove} on super.
*/
public static boolean beforeRemove(ProxyMap map, Object key) {
dirty(map, false);
return map.containsKey(key);
}
/**
* Call after invoking {@link Map#remove} on super.
*
* @param ret the return value from the super's method
* @param before the return value from {@link #beforeRemove}
* @return the value to return from {@link Map#remove}
*/
public static Object afterRemove(ProxyMap map, Object key, Object ret,
boolean before) {
if (before) {
if (map.getChangeTracker() != null)
((MapChangeTracker) map.getChangeTracker()).removed(key, ret);
removed(map, key, true);
removed(map, ret, false);
}
return ret;
}
/**
* Marker interface for a proxy entry set.
*/
public static interface ProxyEntrySet
extends Set {
public static final int VIEW_KEYS = 0;
public static final int VIEW_VALUES = 1;
public static final int VIEW_ENTRIES = 2;
/**
* Set what entry view this set exposes.
*/
public void setView(int view);
}
/**
* Dirtying proxy for map entry set.
*/
private static class ProxyEntrySetImpl
extends AbstractSet
implements ProxyEntrySet {
private final ProxyMap _map;
private final Set _entries;
private int _view = VIEW_ENTRIES;
/**
* Supply owning map and delegate entry set on construction.
*/
public ProxyEntrySetImpl(ProxyMap map, Set entries) {
_map = map;
_entries = entries;
}
/**
* View mode.
*/
public int getView() {
return _view;
}
/**
* View mode.
*/
public void setView(int view) {
_view = view;
}
public int size() {
return _entries.size();
}
public boolean remove(Object o) {
if (_view != VIEW_KEYS)
throw new UnsupportedOperationException();
if (!_map.containsKey(o))
return false;
_map.remove(o);
return true;
}
public Iterator iterator() {
final Iterator itr = _entries.iterator();
return new Iterator() {
private Map.Entry _last = null;
public boolean hasNext() {
return itr.hasNext();
}
public Object next() {
_last = (Map.Entry) itr.next();
switch (_view) {
case VIEW_KEYS:
return _last.getKey();
case VIEW_VALUES:
return _last.getValue();
default:
return _last;
}
}
public void remove() {
dirty(_map, false);
itr.remove();
if (_map.getChangeTracker() != null)
((MapChangeTracker) _map.getChangeTracker()).
removed(_last.getKey(), _last.getValue());
Proxies.removed(_map, _last.getKey(), true);
Proxies.removed(_map, _last.getValue(), false);
}
};
}
protected Object writeReplace()
throws ObjectStreamException {
switch (_view) {
case VIEW_KEYS:
return ((Map) _map).keySet();
case VIEW_VALUES:
return ((Map) _map).values();
default:
return ((Map) _map).entrySet();
}
}
}
}

View File

@ -1,162 +0,0 @@
/*
* 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.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Properties} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyProperties
extends Properties
implements ProxyMap {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient MapChangeTracker _ct = null;
public ProxyProperties() {
}
public ProxyProperties(boolean trackChanges, OpenJPAConfiguration conf) {
if (trackChanges)
_ct = new MapChangeTrackerImpl(this, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
Properties props = new Properties();
props.putAll((Map) orig);
return props;
}
public ProxyMap newInstance(Class keyType, Class valueType,
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyProperties(trackChanges, conf);
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Map.Entry entry;
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
Proxies.removed(this, entry.getKey(), true);
Proxies.removed(this, entry.getValue(), false);
}
super.clear();
}
public Set keySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
}
public Collection values() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
}
public Set entrySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
}
public Object put(Object key, Object value) {
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.put(key, value);
if (had) {
if (_ct != null)
_ct.changed(key, old, value);
Proxies.removed(this, old, false);
} else if (_ct != null)
_ct.added(key, value);
return old;
}
public void putAll(Map m) {
Map.Entry entry;
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
put(entry.getKey(), entry.getValue());
}
}
public Object remove(Object key) {
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.remove(key);
if (had) {
if (_ct != null)
_ct.removed(key, old);
Proxies.removed(this, key, true);
Proxies.removed(this, old, false);
}
return old;
}
public Object setProperty(String key, String value) {
return put(key, value);
}
public void load(InputStream in)
throws IOException {
if (_ct != null)
_ct.stopTracking();
super.load(in);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,113 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.sql.Date;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Date} type that calls the <code>dirty</code>
* method on its owning persistence capable instance on modification. This
* class does not support modification via any deprecated method of the
* date class.
*
* @author Abe White
* @nojavadoc
*/
public class ProxySQLDate
extends Date
implements ProxyDate {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
public ProxySQLDate() {
super(System.currentTimeMillis());
}
public ProxySQLDate(long time) {
super(time);
}
public ProxyDate newInstance() {
return new ProxySQLDate();
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return null;
}
public Object copy(Object orig) {
return new Date(((Date) orig).getTime());
}
public void setYear(int val) {
Proxies.dirty(this);
super.setYear(val);
}
public void setMonth(int val) {
Proxies.dirty(this);
super.setMonth(val);
}
public void setDate(int val) {
Proxies.dirty(this);
super.setDate(val);
}
public void setHours(int val) {
Proxies.dirty(this);
super.setHours(val);
}
public void setMinutes(int val) {
Proxies.dirty(this);
super.setMinutes(val);
}
public void setSeconds(int val) {
Proxies.dirty(this);
super.setSeconds(val);
}
public void setTime(long millis) {
Proxies.dirty(this);
super.setTime(millis);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return new Date(getTime());
}
}

View File

@ -1,113 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.sql.Time;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Time} type that calls the <code>dirty</code>
* method on its owning persistence capable instance on modification. This
* class does not support modification via any deprecated method of the
* date class.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyTime
extends Time
implements ProxyDate {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
public ProxyTime() {
super(System.currentTimeMillis());
}
public ProxyTime(long time) {
super(time);
}
public ProxyDate newInstance() {
return new ProxyTime();
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return null;
}
public Object copy(Object orig) {
return new Time(((Time) orig).getTime());
}
public void setYear(int val) {
Proxies.dirty(this);
super.setYear(val);
}
public void setMonth(int val) {
Proxies.dirty(this);
super.setMonth(val);
}
public void setDate(int val) {
Proxies.dirty(this);
super.setDate(val);
}
public void setHours(int val) {
Proxies.dirty(this);
super.setHours(val);
}
public void setMinutes(int val) {
Proxies.dirty(this);
super.setMinutes(val);
}
public void setSeconds(int val) {
Proxies.dirty(this);
super.setSeconds(val);
}
public void setTime(long millis) {
Proxies.dirty(this);
super.setTime(millis);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return new Time(getTime());
}
}

View File

@ -1,124 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.sql.Timestamp;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Timestamp} type that calls the <code>dirty</code>
* method on its owning persistence capable instance on modification. This
* class does not support modification via any deprecated method of the
* date class.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyTimestamp
extends Timestamp
implements ProxyDate {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
public ProxyTimestamp() {
super(System.currentTimeMillis());
}
public ProxyTimestamp(long time) {
super(time);
}
public ProxyDate newInstance() {
return new ProxyTimestamp();
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return null;
}
public Object copy(Object orig) {
Timestamp origTimestamp = (Timestamp)orig;
Timestamp copy = new Timestamp(origTimestamp.getTime());
copy.setNanos(origTimestamp.getNanos());
return copy;
}
public void setYear(int val) {
Proxies.dirty(this);
super.setYear(val);
}
public void setMonth(int val) {
Proxies.dirty(this);
super.setMonth(val);
}
public void setDate(int val) {
Proxies.dirty(this);
super.setDate(val);
}
public void setHours(int val) {
Proxies.dirty(this);
super.setHours(val);
}
public void setMinutes(int val) {
Proxies.dirty(this);
super.setMinutes(val);
}
public void setSeconds(int val) {
Proxies.dirty(this);
super.setSeconds(val);
}
public void setTime(long millis) {
Proxies.dirty(this);
super.setTime(millis);
}
public void setNanos(int nanos) {
Proxies.dirty(this);
super.setNanos(nanos);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
Timestamp t = new Timestamp(getTime());
t.setNanos(getNanos());
return t;
}
}

View File

@ -1,169 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link TreeMap} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyTreeMap
extends TreeMap
implements ProxyMap {
private transient Class _keyType = null;
private transient Class _valueType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient MapChangeTracker _ct = null;
public ProxyTreeMap() {
}
public ProxyTreeMap(Class keyType, Class valueType, boolean trackChanges,
OpenJPAConfiguration conf) {
_keyType = keyType;
_valueType = valueType;
if (trackChanges)
_ct = new MapChangeTrackerImpl(this, conf);
}
public ProxyTreeMap(Class keyType, Class valueType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
super(compare);
_keyType = keyType;
_valueType = valueType;
if (trackChanges)
_ct = new MapChangeTrackerImpl(this, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
if (orig instanceof SortedMap)
return new TreeMap((SortedMap) orig);
return new TreeMap((Map) orig);
}
public ProxyMap newInstance(Class keyType, Class valueType,
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
if (compare == null)
return new ProxyTreeMap(keyType, valueType, trackChanges, conf);
return new ProxyTreeMap(keyType, valueType, compare, trackChanges,
conf);
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Map.Entry entry;
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
Proxies.removed(this, entry.getKey(), true);
Proxies.removed(this, entry.getValue(), false);
}
super.clear();
}
public Set keySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
}
public Collection values() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
}
public Set entrySet() {
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
}
public Object put(Object key, Object value) {
Proxies.assertAllowedType(key, _keyType);
Proxies.assertAllowedType(value, _valueType);
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.put(key, value);
if (had) {
if (_ct != null)
_ct.changed(key, old, value);
Proxies.removed(this, old, false);
} else if (_ct != null)
_ct.added(key, value);
return old;
}
public void putAll(Map m) {
Map.Entry entry;
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next();
put(entry.getKey(), entry.getValue());
}
}
public Object remove(Object key) {
Proxies.dirty(this);
boolean had = containsKey(key);
Object old = super.remove(key);
if (had) {
if (_ct != null)
_ct.removed(key, old);
Proxies.removed(this, key, true);
Proxies.removed(this, old, false);
}
return old;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,159 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link TreeSet} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyTreeSet
extends TreeSet
implements ProxyCollection {
private transient Class _elementType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient CollectionChangeTracker _ct = null;
public ProxyTreeSet() {
}
public ProxyTreeSet(Class elementType, boolean trackChanges,
OpenJPAConfiguration conf) {
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
}
public ProxyTreeSet(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
super(compare);
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
if (orig instanceof SortedSet)
return new TreeSet((SortedSet) orig);
return new TreeSet((Collection) orig);
}
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
if (compare == null)
return new ProxyTreeSet(elementType, trackChanges, conf);
return new ProxyTreeSet(elementType, compare, trackChanges, conf);
}
public boolean add(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (super.add(value)) {
if (_ct != null)
_ct.added(value);
return true;
}
return false;
}
public boolean addAll(Collection values) {
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
return added;
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (Iterator itr = super.iterator(); itr.hasNext();)
Proxies.removed(this, itr.next(), false);
super.clear();
}
public Iterator iterator() {
return Proxies.iterator(this, super.iterator());
}
public boolean remove(Object o) {
Proxies.dirty(this);
if (super.remove(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public boolean removeAll(Collection c) {
boolean removed = false;
for (Iterator itr = c.iterator(); itr.hasNext();)
removed = remove(itr.next()) || removed;
return removed;
}
public boolean retainAll(Collection c) {
int size = size();
for (Iterator itr = iterator(); itr.hasNext();)
if (!c.contains(itr.next()))
itr.remove();
return size() < size;
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -1,113 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Date;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Date} type that calls the <code>dirty</code>
* method on its owning persistence capable instance on modification. This
* class does not support modification via any deprecated method of the
* date class.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyUtilDate
extends Date
implements ProxyDate {
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
public ProxyUtilDate() {
super();
}
public ProxyUtilDate(long time) {
super(time);
}
public ProxyDate newInstance() {
return new ProxyUtilDate();
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return null;
}
public Object copy(Object orig) {
return new Date(((Date) orig).getTime());
}
public void setYear(int val) {
Proxies.dirty(this);
super.setYear(val);
}
public void setMonth(int val) {
Proxies.dirty(this);
super.setMonth(val);
}
public void setDate(int val) {
Proxies.dirty(this);
super.setDate(val);
}
public void setHours(int val) {
Proxies.dirty(this);
super.setHours(val);
}
public void setMinutes(int val) {
Proxies.dirty(this);
super.setMinutes(val);
}
public void setSeconds(int val) {
Proxies.dirty(this);
super.setSeconds(val);
}
public void setTime(long millis) {
Proxies.dirty(this);
super.setTime(millis);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return new Date(getTime());
}
}

View File

@ -1,246 +0,0 @@
/*
* 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.util;
import java.io.ObjectStreamException;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
/**
* Extension of the {@link Vector} type that dirties the
* persistent/transactional field it is assigned to on modification.
* The need to dirty the field on <b>any</b> modification mandates that
* this class must override all mutator methods of the base type.
* This may lead to multiple calls to <code>dirty</code> for one state
* change if one mutator method of the base type calls another.
*
* @author Abe White
* @nojavadoc
*/
public class ProxyVector
extends Vector
implements ProxyCollection {
private transient Class _elementType = null;
private transient OpenJPAStateManager _sm = null;
private transient int _field = -1;
private transient CollectionChangeTracker _ct = null;
public ProxyVector() {
}
public ProxyVector(Class elementType, boolean trackChanges,
OpenJPAConfiguration conf) {
_elementType = elementType;
if (trackChanges)
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
}
public void setOwner(OpenJPAStateManager sm, int field) {
_sm = sm;
_field = field;
}
public OpenJPAStateManager getOwner() {
return _sm;
}
public int getOwnerField() {
return _field;
}
public ChangeTracker getChangeTracker() {
return _ct;
}
public Object copy(Object orig) {
return new Vector((Collection) orig);
}
public ProxyCollection newInstance(Class elementType, Comparator compare,
boolean trackChanges, OpenJPAConfiguration conf) {
return new ProxyVector(elementType, trackChanges, conf);
}
public void add(int index, Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
super.add(index, value);
}
public void insertElementAt(Object value, int index) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
super.insertElementAt(value, index);
}
public boolean add(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (super.add(value)) {
if (_ct != null)
_ct.added(value);
return true;
}
return false;
}
public void addElement(Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
super.addElement(value);
if (_ct != null)
_ct.added(value);
}
public boolean addAll(int index, Collection values) {
ensureCapacity(size() + values.size());
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
add(index, itr.next());
return values.size() > 0;
}
public boolean addAll(Collection values) {
ensureCapacity(size() + values.size());
boolean added = false;
for (Iterator itr = values.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
return added;
}
public void clear() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (int i = 0; i < size(); i++)
Proxies.removed(this, get(i), false);
super.clear();
}
public void removeAllElements() {
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
for (int i = 0; i < size(); i++)
Proxies.removed(this, get(i), false);
super.removeAllElements();
}
public Iterator iterator() {
return Proxies.iterator(this, super.iterator());
}
public ListIterator listIterator() {
return Proxies.listIterator(this, super.listIterator(), _elementType);
}
public ListIterator listIterator(int index) {
return Proxies.listIterator(this, super.listIterator(index),
_elementType);
}
public Object remove(int index) {
Proxies.dirty(this);
Object rem = super.remove(index);
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
return rem;
}
public void removeElementAt(int index) {
Proxies.dirty(this);
Object rem = get(index);
super.removeElementAt(index);
if (_ct != null)
_ct.removed(rem);
Proxies.removed(this, rem, false);
}
public boolean remove(Object o) {
Proxies.dirty(this);
if (super.remove(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public boolean removeElement(Object o) {
Proxies.dirty(this);
if (super.removeElement(o)) {
if (_ct != null)
_ct.removed(o);
Proxies.removed(this, o, false);
return true;
}
return false;
}
public boolean removeAll(Collection c) {
boolean removed = false;
for (Iterator itr = c.iterator(); itr.hasNext();)
removed = remove(itr.next()) || removed;
return removed;
}
public boolean retainAll(Collection c) {
int size = size();
for (Iterator itr = iterator(); itr.hasNext();)
if (!c.contains(itr.next()))
itr.remove();
return size() < size;
}
public Object set(int index, Object value) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Object rem = super.set(index, value);
Proxies.removed(this, rem, false);
return rem;
}
public void setElementAt(Object value, int index) {
Proxies.assertAllowedType(value, _elementType);
Proxies.dirty(this);
if (_ct != null)
_ct.stopTracking();
Object rem = get(index);
super.setElementAt(value, index);
Proxies.removed(this, rem, false);
}
protected Object writeReplace()
throws ObjectStreamException {
if (_sm != null && _sm.isDetached())
return this;
return copy(this);
}
}

View File

@ -42,16 +42,20 @@ opt-lock-nested: Optimistic locking errors were detected when \
concurrently modified in another transaction. Each exception in \
the nested throwables array contains a failed object representing \
a concurrently modified object.
bad-proxy: Unable to create second class object proxy for type: "{0}".
bad-array: Unable to copy array: {0}.
no-proxy-intf: Unable to create a second class object proxy for interface \
"{0}". No corresponding concrete types are known.
no-proxy-abstract: Unable to create a second class object proxy for abstract \
type "{0}". You must use a concrete type or a recognized interface.
cant-classforname: Unable to instantiate proxy for type "{0}". Make sure the \
class has a default constructor.
no-date-cons: Custom date type "{0}" needs a default constructor or a \
millisecond constructor.
bad-elem-type: The given element does not meet the requirements for this \
field. The container requires that all non-null objects are of the type \
declared in the XML metadata for this container. \
"{1}(loader={0}).isAssignableFrom ({3}(loader={2}))" failed.
string-id: Unable to create a valid id from string "{0}".
no-proxy-cons: An exception was thrown while creating a new instance of \
custom proxy collection type "{0}". This could mean that there is no \
public no-args constructor for this type.
bad-single-id: Invalid single identity declaration for type "{0}". Only \
a single field can be declared for single field identity.
not-single: The given type "{0}" does not use single field identity.

View File

@ -0,0 +1,971 @@
/*
* 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.util;
import java.io.InputStream;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.AbstractMap;
import java.util.AbstractSequentialList;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.TreeMap;
import java.util.Vector;
import junit.framework.TestCase;
import junit.textui.TestRunner;
/**
* Test proxies generated by the proxy manager.
*
* @author Abe White
*/
public class TestProxyManager
extends TestCase {
private ProxyManagerImpl _mgr;
public void setUp() {
_mgr = new ProxyManagerImpl();
}
public void testCopyLists() {
List orig = new ArrayList();
populate(orig);
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
orig = new LinkedList();
populate(orig);
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
orig = new CustomList();
populate(orig);
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
}
/**
* Populate the given list with arbitrary data.
*/
private static void populate(Collection coll) {
coll.add(new Integer(1));
coll.add("foo");
coll.add(new Long(99));
coll.add("bar");
coll.add(new Short((short) 50));
}
/**
* Assert that the given lists are exactly the same.
*/
private static void assertListsEqual(List l1, List l2) {
assertTrue(l1.getClass() == l2.getClass());
assertEquals(l1.size(), l2.size());
for (int i = 0; i < l1.size(); i++)
assertTrue(l1.get(i) + " != " + l2.get(i), l1.get(i) == l2.get(i));
}
public void testCopySets() {
Set orig = new HashSet();
populate(orig);
assertSetsEqual(orig, (Set) _mgr.copyCollection(orig));
orig = new CustomSet();
populate(orig);
assertSetsEqual(orig, (Set) _mgr.copyCollection(orig));
}
/**
* Assert that the given sets are exactly the same.
*/
private static void assertSetsEqual(Set s1, Set s2) {
assertTrue(s1.getClass() == s2.getClass());
assertEquals(s1.size(), s2.size());
assertEquals(s1, s2);
}
public void testCopySortedSets() {
SortedSet orig = new TreeSet();
populate(orig);
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
orig = new TreeSet(new CustomComparator());
populate(orig);
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
orig = new CustomSortedSet();
populate(orig);
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
orig = new CustomComparatorSortedSet(new CustomComparator());
populate(orig);
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
}
/**
* Populate the given sorted set with arbitrary data.
*/
private static void populate(SortedSet coll) {
coll.add(new Integer(1));
coll.add(new Integer(99));
coll.add(new Integer(50));
coll.add(new Integer(-5));
coll.add(new Integer(10));
}
/**
* Assert that the given sets are exactly the same.
*/
private static void assertSortedSetsEqual(SortedSet s1, SortedSet s2) {
assertTrue(s1.getClass() == s2.getClass());
assertEquals(s1.comparator(), s2.comparator());
assertEquals(s1.size(), s2.size());
Iterator itr1 = s1.iterator();
Iterator itr2 = s2.iterator();
while (itr1.hasNext())
assertTrue(itr1.next() == itr2.next());
}
public void testCopyNullCollection() {
assertNull(_mgr.copyCollection(null));
}
public void testCopyProxyCollection() {
List orig = (List) _mgr.newCollectionProxy(ArrayList.class, null, null);
populate(orig);
assertListsEqual(new ArrayList(orig), (List) _mgr.copyCollection(orig));
TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null,
new CustomComparator());
assertTrue(torig.comparator() instanceof CustomComparator);
populate(torig);
assertSortedSetsEqual(new TreeSet(torig), (SortedSet)
_mgr.copyCollection(torig));
}
public void testListMethodsProxied()
throws Exception {
Class proxy = _mgr.newCollectionProxy(ArrayList.class, null, null).
getClass();
assertListMethodsProxied(proxy);
proxy = _mgr.newCollectionProxy(CustomList.class, null, null).
getClass();
assertListMethodsProxied(proxy);
}
/**
* Assert that the methods we need to override to dirty the collection are
* proxied appropriately.
*/
private void assertCollectionMethodsProxied(Class cls)
throws Exception {
assertNotNull(cls.getDeclaredMethod("add", new Class[] {Object.class}));
assertNotNull(cls.getDeclaredMethod("addAll",
new Class[] {Collection.class}));
assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("iterator", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("remove",
new Class[] {Object.class}));
assertNotNull(cls.getDeclaredMethod("removeAll",
new Class[] {Collection.class}));
assertNotNull(cls.getDeclaredMethod("retainAll",
new Class[] {Collection.class}));
// check a non-mutating method to make sure we're not just proxying
// everything
try {
cls.getDeclaredMethod("contains", new Class[] {Object.class});
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
/**
* Assert that the methods we need to override to dirty the list are
* proxied appropriately.
*/
private void assertListMethodsProxied(Class cls)
throws Exception {
assertCollectionMethodsProxied(cls);
assertNotNull(cls.getDeclaredMethod("add",
new Class[] {int.class, Object.class}));
assertNotNull(cls.getDeclaredMethod("addAll",
new Class[] {int.class, Collection.class}));
assertNotNull(cls.getDeclaredMethod("listIterator", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("listIterator",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("remove", new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("set",
new Class[] {int.class, Object.class}));
}
public void testSetMethodsProxied()
throws Exception {
Class proxy = _mgr.newCollectionProxy(HashSet.class, null, null).
getClass();
assertCollectionMethodsProxied(proxy);
proxy = _mgr.newCollectionProxy(CustomSet.class, null, null).getClass();
assertCollectionMethodsProxied(proxy);
proxy = _mgr.newCollectionProxy(CustomSortedSet.class, null, null).
getClass();
assertCollectionMethodsProxied(proxy);
proxy = _mgr.newCollectionProxy(CustomComparatorSortedSet.class, null,
new CustomComparator()).getClass();
assertCollectionMethodsProxied(proxy);
}
public void testQueueMethodsProxied()
throws Exception {
Class queue = getQueueClass();
if (queue == null)
return;
Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null).
getClass();
assertTrue(queue.isAssignableFrom(proxy));
assertCollectionMethodsProxied(proxy);
assertNotNull(proxy.getDeclaredMethod("offer",
new Class[] {Object.class}));
assertNotNull(proxy.getDeclaredMethod("poll", (Class[]) null));
assertNotNull(proxy.getDeclaredMethod("remove", (Class[]) null));
try {
proxy.getDeclaredMethod("peek", (Class[]) null);
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
public void testLinkedListMethodsProxied()
throws Exception {
Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null).
getClass();
assertListMethodsProxied(proxy);
assertNotNull(proxy.getDeclaredMethod("addFirst",
new Class[] {Object.class}));
assertNotNull(proxy.getDeclaredMethod("addLast",
new Class[] {Object.class}));
assertNotNull(proxy.getDeclaredMethod("removeFirst", (Class[]) null));
assertNotNull(proxy.getDeclaredMethod("removeLast", (Class[]) null));
}
public void testVectorMethodsProxied()
throws Exception {
Class proxy = _mgr.newCollectionProxy(Vector.class, null, null).
getClass();
assertListMethodsProxied(proxy);
assertNotNull(proxy.getDeclaredMethod("addElement",
new Class[] {Object.class}));
assertNotNull(proxy.getDeclaredMethod("insertElementAt",
new Class[] {Object.class, int.class}));
assertNotNull(proxy.getDeclaredMethod("removeAllElements",
(Class[]) null));
assertNotNull(proxy.getDeclaredMethod("removeElement",
new Class[] {Object.class}));
assertNotNull(proxy.getDeclaredMethod("removeElementAt",
new Class[] {int.class}));
assertNotNull(proxy.getDeclaredMethod("setElementAt",
new Class[] {Object.class, int.class}));
}
public void testListChangeTracker() {
Proxy coll = _mgr.newCollectionProxy(ArrayList.class, null, null);
assertNotNull(coll);
assertNotNull(coll.getChangeTracker());
assertTrue(coll.getChangeTracker()
instanceof CollectionChangeTrackerImpl);
CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl)
coll.getChangeTracker();
assertTrue(ct.allowsDuplicates());
assertTrue(ct.isOrdered());
}
public void testSetChangeTracker() {
Proxy coll = _mgr.newCollectionProxy(HashSet.class, null, null);
assertNotNull(coll);
assertNotNull(coll.getChangeTracker());
assertTrue(coll.getChangeTracker()
instanceof CollectionChangeTrackerImpl);
CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl)
coll.getChangeTracker();
assertFalse(ct.allowsDuplicates());
assertFalse(ct.isOrdered());
}
public void testCollectionInterfaceProxy() {
Proxy coll = _mgr.newCollectionProxy(Collection.class, null, null);
assertNotNull(coll);
}
public void testListInterfaceProxy() {
Proxy coll = _mgr.newCollectionProxy(List.class, null, null);
assertNotNull(coll);
assertTrue(coll instanceof List);
}
public void testSetInterfaceProxy() {
Proxy coll = _mgr.newCollectionProxy(Set.class, null, null);
assertNotNull(coll);
assertTrue(coll instanceof Set);
assertFalse(coll instanceof SortedSet);
}
public void testSortedSetInterfaceProxy() {
Proxy coll = _mgr.newCollectionProxy(SortedSet.class, null, null);
assertNotNull(coll);
assertTrue(coll instanceof SortedSet);
}
public void testQueueInterfaceProxy() {
Class queue = getQueueClass();
if (queue == null)
return;
Proxy coll = _mgr.newCollectionProxy(queue, null, null);
assertNotNull(coll);
assertTrue(queue.isInstance(coll));
}
/**
* Return the {@link java.util.Queue} class if avaialble.
*/
private static Class getQueueClass() {
try {
return Class.forName("java.util.Queue");
} catch (Throwable t) {
return null;
}
}
public void testCopyMaps() {
Map orig = new HashMap();
populate(orig);
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
orig = new CustomMap();
populate(orig);
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
Properties porig = new Properties();
porig.setProperty("foo", "bar");
porig.setProperty("bar", "biz");
porig.setProperty("biz", "baz");
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
}
/**
* Populate the given map with arbitrary data.
*/
private static void populate(Map map) {
map.put(new Integer(1), "1");
map.put(new Integer(99), "99");
map.put(new Integer(-2), "-2");
map.put(new Integer(50), "50");
}
/**
* Assert that the given maps are exactly the same.
*/
private static void assertMapsEqual(Map m1, Map m2) {
assertTrue(m1.getClass() == m2.getClass());
assertEquals(m1.size(), m2.size());
assertEquals(m1, m2);
}
public void testCopySortedMaps() {
SortedMap orig = new TreeMap();
populate(orig);
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
orig = new TreeMap(new CustomComparator());
populate(orig);
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
orig = new CustomSortedMap();
populate(orig);
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
orig = new CustomComparatorSortedMap(new CustomComparator());
populate(orig);
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
}
/**
* Assert that the given maps are exactly the same.
*/
private static void assertSortedMapsEqual(SortedMap m1, SortedMap m2) {
assertTrue(m1.getClass() == m2.getClass());
assertEquals(m1.comparator(), m2.comparator());
assertEquals(m1.size(), m2.size());
Map.Entry entry1;
Map.Entry entry2;
Iterator itr1 = m1.entrySet().iterator();
Iterator itr2 = m2.entrySet().iterator();
while (itr1.hasNext()) {
entry1 = (Map.Entry) itr1.next();
entry2 = (Map.Entry) itr2.next();
assertTrue(entry1.getKey() == entry2.getKey());
assertTrue(entry1.getValue() == entry2.getValue());
}
}
public void testCopyNullMap() {
assertNull(_mgr.copyMap(null));
}
public void testCopyProxyMap() {
Map orig = (Map) _mgr.newMapProxy(HashMap.class, null, null, null);
populate(orig);
assertMapsEqual(new HashMap(orig), (Map) _mgr.copyMap(orig));
TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null,
new CustomComparator());
assertTrue(torig.comparator() instanceof CustomComparator);
populate(torig);
assertSortedMapsEqual(new TreeMap(torig), (SortedMap)
_mgr.copyMap(torig));
}
public void testMapMethodsProxied()
throws Exception {
Class proxy = _mgr.newMapProxy(HashMap.class, null, null, null).
getClass();
assertMapMethodsProxied(proxy);
proxy = _mgr.newMapProxy(TreeMap.class, null, null, null).getClass();
assertMapMethodsProxied(proxy);
proxy = _mgr.newMapProxy(TreeMap.class, null, null,
new CustomComparator()).getClass();
assertMapMethodsProxied(proxy);
proxy = _mgr.newMapProxy(CustomMap.class, null, null, null).getClass();
assertMapMethodsProxied(proxy);
proxy = _mgr.newMapProxy(CustomSortedMap.class, null, null, null).
getClass();
assertMapMethodsProxied(proxy);
proxy = _mgr.newMapProxy(CustomComparatorSortedMap.class, null, null,
new CustomComparator()).getClass();
assertMapMethodsProxied(proxy);
}
/**
* Assert that the methods we need to override to dirty the collection are
* proxied appropriately.
*/
private void assertMapMethodsProxied(Class cls)
throws Exception {
assertNotNull(cls.getDeclaredMethod("put",
new Class[] {Object.class, Object.class}));
assertNotNull(cls.getDeclaredMethod("putAll", new Class[] {Map.class}));
assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("remove",
new Class[] {Object.class}));
assertNotNull(cls.getDeclaredMethod("keySet", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("values", (Class[]) null));
assertNotNull(cls.getDeclaredMethod("entrySet", (Class[]) null));
// check a non-mutating method to make sure we're not just proxying
// everything
try {
cls.getDeclaredMethod("containsKey", new Class[] {Object.class});
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
public void testPropertiesMethodsProxied()
throws Exception {
Class proxy = _mgr.newMapProxy(Properties.class, null, null, null).
getClass();
assertMapMethodsProxied(proxy);
assertNotNull(proxy.getDeclaredMethod("setProperty",
new Class[] {String.class, String.class}));
assertNotNull(proxy.getDeclaredMethod("load",
new Class[] {InputStream.class}));
assertNotNull(proxy.getDeclaredMethod("loadFromXML",
new Class[] {InputStream.class}));
}
public void testCopyDates() {
Date orig = new Date(1999);
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
orig = new java.sql.Date(1999);
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
orig = new Time(1999);
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
Timestamp torig = new Timestamp(1999);
torig.setNanos(2001);
assertDatesEqual(torig, (Date) _mgr.copyDate(torig));
torig = new CustomDate(1999);
torig.setNanos(2001);
assertDatesEqual(torig, (Date) _mgr.copyDate(torig));
}
/**
* Assert that the given dates are exactly the same.
*/
private static void assertDatesEqual(Date d1, Date d2) {
assertTrue(d1.getClass() == d1.getClass());
assertEquals(d1, d2);
}
public void testCopyNullDate() {
assertNull(_mgr.copyDate(null));
}
public void testCopyProxyDate() {
Date orig = (Date) _mgr.newDateProxy(Time.class);
orig.setTime(1999);
assertDatesEqual(new Date(orig.getTime()), (Date) _mgr.copyDate(orig));
}
public void testDateMethodsProxied()
throws Exception {
Class proxy = _mgr.newDateProxy(Date.class).getClass();
assertDateMethodsProxied(proxy);
proxy = _mgr.newDateProxy(java.sql.Date.class).getClass();
assertDateMethodsProxied(proxy);
proxy = _mgr.newDateProxy(Time.class).getClass();
assertDateMethodsProxied(proxy);
proxy = _mgr.newDateProxy(Timestamp.class).getClass();
assertTimestampMethodsProxied(proxy);
proxy = _mgr.newDateProxy(CustomDate.class).getClass();
assertTimestampMethodsProxied(proxy);
}
/**
* Assert that the methods we need to override to dirty the date are
* proxied appropriately.
*/
private void assertDateMethodsProxied(Class cls)
throws Exception {
assertNotNull(cls.getDeclaredMethod("setDate",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("setHours",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("setMinutes",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("setMonth",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("setSeconds",
new Class[] {int.class}));
assertNotNull(cls.getDeclaredMethod("setTime",
new Class[] {long.class}));
assertNotNull(cls.getDeclaredMethod("setYear",
new Class[] {int.class}));
// check a non-mutating method to make sure we're not just proxying
// everything
try {
cls.getDeclaredMethod("getTime", (Class[]) null);
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
/**
* Assert that the methods we need to override to dirty the timestamp are
* proxied appropriately.
*/
private void assertTimestampMethodsProxied(Class cls)
throws Exception {
assertDateMethodsProxied(cls);
assertNotNull(cls.getDeclaredMethod("setNanos",
new Class[] {int.class}));
}
public void testCopyCalendars() {
Calendar orig = new GregorianCalendar();
populate(orig);
assertCalendarsEqual(orig, _mgr.copyCalendar(orig));
orig = new CustomCalendar();
populate(orig);
assertCalendarsEqual(orig, _mgr.copyCalendar(orig));
}
/**
* Populate calendar with arbitrary data.
*/
private static void populate(Calendar cal) {
cal.setTimeInMillis(1999);
cal.setTimeZone(TimeZone.getTimeZone("CST"));
}
/**
* Assert that the given dates are exactly the same.
*/
private static void assertCalendarsEqual(Calendar c1, Calendar c2) {
assertTrue(c1.getClass() == c1.getClass());
assertEquals(c1, c2);
}
public void testCopyNullCalendar() {
assertNull(_mgr.copyCalendar(null));
}
public void testCopyProxyCalendar() {
Calendar orig = (Calendar) _mgr.newCalendarProxy
(GregorianCalendar.class, TimeZone.getTimeZone("CST"));
populate(orig);
Calendar cal = new GregorianCalendar();
populate(cal);
assertCalendarsEqual(cal, _mgr.copyCalendar(orig));
}
public void testCalendarAbstractClassProxy() {
Proxy cal = _mgr.newCalendarProxy(Calendar.class, null);
assertNotNull(cal);
}
public void testCalendarMethodsProxied()
throws Exception {
Class proxy = _mgr.newCalendarProxy(GregorianCalendar.class,
TimeZone.getDefault()).getClass();
assertCalendarMethodsProxied(proxy);
proxy = _mgr.newCalendarProxy(CustomCalendar.class,
TimeZone.getDefault()).getClass();
assertCalendarMethodsProxied(proxy);
proxy = _mgr.newCalendarProxy(Calendar.class,
TimeZone.getDefault()).getClass();
assertCalendarMethodsProxied(proxy);
}
/**
* Assert that the methods we need to override to dirty the calendar are
* proxied appropriately.
*/
private void assertCalendarMethodsProxied(Class cls)
throws Exception {
assertNotNull(cls.getDeclaredMethod("set",
new Class[] {int.class, int.class}));
assertNotNull(cls.getDeclaredMethod("roll",
new Class[] {int.class, int.class}));
assertNotNull(cls.getDeclaredMethod("setTimeInMillis",
new Class[] {long.class}));
assertNotNull(cls.getDeclaredMethod("setTimeZone",
new Class[] {TimeZone.class}));
assertNotNull(cls.getDeclaredMethod("computeFields", (Class[]) null));
// check a non-mutating method to make sure we're not just proxying
// everything
try {
cls.getDeclaredMethod("getTimeInMillis", (Class[]) null);
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
public void testCopyBeans() {
CustomBean orig = new CustomBean();
populate(orig);
assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig));
orig = new CustomCopyConstructorBean(orig);
assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig));
}
/**
* Populate the given bean with arbitrary data.
*/
private void populate(CustomBean bean) {
bean.setString("foo");
bean.setNumber(99);
}
public void testNonproxyableBean() {
NonproxyableBean orig = new NonproxyableBean(1);
populate(orig);
assertNull(_mgr.copyCustom(orig));
assertNull(_mgr.newCustomProxy(orig));
}
/**
* Assert that the given beans are exactly the same.
*/
private static void assertBeansEqual(CustomBean b1, CustomBean b2) {
assertTrue(b1.getClass() == b2.getClass());
assertTrue(b1.getString() == b2.getString());
assertTrue(b1.getNumber() == b2.getNumber());
}
public void testCopyNullBean() {
assertNull(_mgr.copyCustom(null));
}
public void testCopyProxyBean() {
CustomBean orig = (CustomBean) _mgr.newCustomProxy(new CustomBean());
populate(orig);
CustomBean comp = new CustomBean();
populate(comp);
assertBeansEqual(comp, (CustomBean) _mgr.copyCustom(orig));
}
public void testBeanMethodsProxied()
throws Exception {
Class proxy = _mgr.newCustomProxy(new CustomBean()).getClass();
assertBeanMethodsProxied(proxy);
proxy = _mgr.newCustomProxy(new CustomCopyConstructorBean
(new CustomBean())).getClass();
assertBeanMethodsProxied(proxy);
}
/**
* Assert that the methods we need to override to dirty the bean are
* proxied appropriately.
*/
private void assertBeanMethodsProxied(Class cls)
throws Exception {
assertNotNull(cls.getDeclaredMethod("setString",
new Class[] {String.class}));
assertNotNull(cls.getDeclaredMethod("setNumber",
new Class[] {int.class}));
// check a non-mutating method to make sure we're not just proxying
// everything
try {
cls.getDeclaredMethod("getString", (Class[]) null);
fail("Proxied non-mutating method.");
} catch (NoSuchMethodException nsme) {
// expected
}
}
public static void main(String[] args) {
TestRunner.run(TestProxyManager.class);
}
/**
* Used to test custom list handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomList
extends AbstractSequentialList {
private final List _delegate = new ArrayList();
public int size() {
return _delegate.size();
}
public ListIterator listIterator(int idx) {
return _delegate.listIterator(idx);
}
}
/**
* Used to test custom set handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomSet
extends AbstractSet {
private final Set _delegate = new HashSet();
public int size() {
return _delegate.size();
}
public Iterator iterator() {
return _delegate.iterator();
}
public boolean add(Object o) {
return _delegate.add(o);
}
}
/**
* Used to test custom set handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomSortedSet
extends TreeSet {
}
/**
* Used to test custom set handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomComparatorSortedSet
extends TreeSet {
public CustomComparatorSortedSet() {
}
public CustomComparatorSortedSet(Comparator comp) {
super(comp);
}
}
/**
* Used to test custom map handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomMap
extends AbstractMap {
private final Map _delegate = new HashMap();
public Object put(Object key, Object value) {
return _delegate.put(key, value);
}
public Set entrySet() {
return _delegate.entrySet();
}
}
/**
* Used to test custom map handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomSortedMap
extends TreeMap {
}
/**
* Used to test custom map handling. Copy constructor intentionally
* ommitted.
*/
public static class CustomComparatorSortedMap
extends TreeMap {
public CustomComparatorSortedMap() {
}
public CustomComparatorSortedMap(Comparator comp) {
super(comp);
}
}
/**
* Used to test transfer of comparators to proxies.
*/
private static class CustomComparator
implements Comparator {
public int compare(Object o1, Object o2) {
return ((Comparable) o1).compareTo(o2);
}
}
/**
* Used to test custom date handling.
*/
public static class CustomDate
extends Timestamp {
public CustomDate(long time) {
super(time);
}
}
/**
* Used to test custom bean handling.
*/
public static class CustomBean {
private String _string;
private int _number;
public String getString() {
return _string;
}
public void setString(String str) {
_string = str;
}
public int getNumber() {
return _number;
}
public void setNumber(int number) {
_number = number;
}
}
/**
* Used to test custom bean handling.
*/
public static class CustomCopyConstructorBean
extends CustomBean {
public CustomCopyConstructorBean(CustomBean bean) {
setString(bean.getString());
setNumber(bean.getNumber());
}
}
/**
* Used to non-proxyable custom bean handling.
*/
public static class NonproxyableBean
extends CustomBean {
public NonproxyableBean(long x) {
// single non-default, non-copy constructor
}
}
/**
* Used to test custom calendar handling.
*/
public static class CustomCalendar
extends GregorianCalendar {
}
}