/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.util; import java.io.InputStream; import java.lang.reflect.Method; 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 org.apache.openjpa.util.Proxy; 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()); assertSortedSetsEquals(s1, s2); } /** * Assert that the given sets are exactly the same (minus the class). */ private static void assertSortedSetsEquals(SortedSet s1, SortedSet s2) { 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()); assertTrue(s1.equals(s2)); } public void testCopyNullCollection() { assertNull(_mgr.copyCollection(null)); } public void testCopyProxyCollection() { List orig = (List) _mgr.newCollectionProxy(ArrayList.class, null, null, true); populate(orig); assertListsEqual(new ArrayList(orig), (List) _mgr.copyCollection(orig)); TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null, new CustomComparator(), true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedSetsEqual(new TreeSet(torig), (SortedSet) _mgr.copyCollection(torig)); } public void testCloneProxyCollection() { // List doesn't support clone() TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null, new CustomComparator(), true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedSetsEquals(new TreeSet(torig), (SortedSet) torig.clone()); } public void testListMethodsProxied() throws Exception { Class proxy = _mgr.newCollectionProxy(ArrayList.class, null, null, true).getClass(); assertListMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomList.class, null, null, true).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, true).getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomSet.class, null, null, true).getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomSortedSet.class, null, null, true).getClass(); assertCollectionMethodsProxied(proxy); proxy = _mgr.newCollectionProxy(CustomComparatorSortedSet.class, null, new CustomComparator(), true).getClass(); assertCollectionMethodsProxied(proxy); } public void testQueueMethodsProxied() throws Exception { Class queue = getQueueClass(); if (queue == null) return; Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null, true).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, true).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, true).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, true); 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, true); 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, true); assertNotNull(coll); } public void testListInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(List.class, null, null, true); assertNotNull(coll); assertTrue(coll instanceof List); } public void testSetInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(Set.class, null, null, true); assertNotNull(coll); assertTrue(coll instanceof Set); assertFalse(coll instanceof SortedSet); } public void testSortedSetInterfaceProxy() { Proxy coll = _mgr.newCollectionProxy(SortedSet.class, null, null, true); assertNotNull(coll); assertTrue(coll instanceof SortedSet); } public void testQueueInterfaceProxy() { Class queue = getQueueClass(); if (queue == null) return; Proxy coll = _mgr.newCollectionProxy(queue, null, null, true); assertNotNull(coll); assertTrue(queue.isInstance(coll)); } public void testProxyCustomDefaultScopedType() throws Exception { // Use reflection to instantiate a type that isn't in the current package. Class<?> cls = Class.forName("org.apache.openjpa.util.custom.CustomProxyDefaultScopeType"); assertNotNull(cls); Method meth = cls.getMethod("instance", new Class[0]); assertNotNull(meth); meth.setAccessible(true); Object obj = meth.invoke(cls, new Object[0]); assertNotNull(obj); assertNull(_mgr.newCustomProxy(obj, true)); } public void testProxyCustomDefaultScopedList() throws Exception { // Use reflection to instantiate a type that isn't in the current package. Class<?> cls = Class.forName("org.apache.openjpa.util.custom.CustomProxyDefaultScopeList"); assertNotNull(cls); Method meth = cls.getMethod("instance", new Class[0]); assertNotNull(meth); meth.setAccessible(true); Object obj = meth.invoke(cls, new Object[0]); assertNotNull(obj); assertNull(_mgr.newCustomProxy(obj, true)); } /** * 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()); assertSortedMapsEquals(m1, m2); } /** * Assert that the given maps are exactly the same (minus the class). */ private static void assertSortedMapsEquals(SortedMap m1, SortedMap m2) { 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()); } assertTrue(m1.equals(m2)); } public void testCopyNullMap() { assertNull(_mgr.copyMap(null)); } public void testCopyProxyMap() { Map orig = (Map) _mgr.newMapProxy(HashMap.class, null, null, null, true); populate(orig); assertMapsEqual(new HashMap(orig), (Map) _mgr.copyMap(orig)); TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(), true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedMapsEqual(new TreeMap(torig), (SortedMap) _mgr.copyMap(torig)); } public void testCloneProxyMap() { // Map does not support clone() TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(), true); assertTrue(torig.comparator() instanceof CustomComparator); populate(torig); assertSortedMapsEquals(new TreeMap(torig), (SortedMap) torig.clone()); } public void testMapMethodsProxied() throws Exception { Class proxy = _mgr.newMapProxy(HashMap.class, null, null, null, true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(TreeMap.class, null, null, null, true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(TreeMap.class, null, null, new CustomComparator(), true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomMap.class, null, null, null, true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomSortedMap.class, null, null, null, true).getClass(); assertMapMethodsProxied(proxy); proxy = _mgr.newMapProxy(CustomComparatorSortedMap.class, null, null, new CustomComparator(), true).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, true).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() == d2.getClass()); assertDatesEquals(d1, d2); } /** * Assert that the given dates are exactly the same (minus the class). */ private static void assertDatesEquals(Date d1, Date d2) { assertTrue(d1.equals(d2)); } public void testCopyNullDate() { assertNull(_mgr.copyDate(null)); } public void testCopyProxyDate() { Date orig = (Date) _mgr.newDateProxy(Time.class); orig.setTime(1999); assertDatesEqual(new Time(orig.getTime()), (Date) _mgr.copyDate(orig)); } public void testCloneProxyDate() { Date orig = (Date) _mgr.newDateProxy(Time.class); orig.setTime(1999); assertDatesEquals(new Time(orig.getTime()), (Date) orig.clone()); } 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() == c2.getClass()); assertCalendarsEquals(c1, c2); } /** * Assert that the given dates are exactly the same (minus the class). */ private static void assertCalendarsEquals(Calendar c1, Calendar c2) { assertTrue(c1.equals(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 testCloneProxyCalendar() { Calendar orig = (Calendar) _mgr.newCalendarProxy(GregorianCalendar.class, TimeZone.getTimeZone("CST")); populate(orig); Calendar cal = new GregorianCalendar(); populate(cal); assertCalendarsEquals(cal, (Calendar) orig.clone()); } 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.copyCustom(orig)); assertNull(_mgr.newCustomProxy(orig, true)); } public void testIsUnproxyable() { CustomBean validBean = new CustomBean(); populate(validBean); assertNotNull(_mgr.copyCustom(validBean)); assertNotNull(_mgr.newCustomProxy(validBean, true)); assertFalse(_mgr.isUnproxyable(CustomBean.class)); NonproxyableBean bean1 = new NonproxyableBean(1); populate(bean1); NonproxyableBean2 bean2 = new NonproxyableBean2(); populate(bean2); assertFalse(_mgr.isUnproxyable(NonproxyableBean.class)); assertNull(_mgr.copyCustom(bean1)); assertTrue(_mgr.isUnproxyable(NonproxyableBean.class)); assertNull(_mgr.newCustomProxy(bean1, true)); assertTrue(_mgr.isUnproxyable(NonproxyableBean.class)); assertFalse(_mgr.isUnproxyable(NonproxyableBean2.class)); assertNull(_mgr.newCustomProxy(bean2, true)); assertTrue(_mgr.isUnproxyable(NonproxyableBean2.class)); assertNull(_mgr.copyCustom(bean2)); assertTrue(_mgr.isUnproxyable(NonproxyableBean2.class)); } /** * 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(), true); 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(), true).getClass(); assertBeanMethodsProxied(proxy); proxy = _mgr.newCustomProxy(new CustomCopyConstructorBean(new CustomBean()), true).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 non-proxyable custom bean handling. */ public class NonproxyableBean2 extends CustomBean { // class is not static } /** * Used to test custom calendar handling. */ public static class CustomCalendar extends GregorianCalendar { } }