mirror of https://github.com/apache/openjpa.git
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:
parent
db25f08565
commit
e54b0c1908
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -123,6 +123,7 @@ class SingleFieldManager
|
|||
proxy = getProxyManager().newCustomProxy(objval);
|
||||
ret = proxy != null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (proxy != null) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue