/*
 * 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.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 {
    }
}
