/*
 * 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.commons.beanutils2.bugs;

import java.beans.IntrospectionException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

import org.apache.commons.beanutils2.MappedPropertyDescriptor;
import org.apache.commons.beanutils2.memoryleaktests.MemoryLeakTestCase;

import junit.framework.TestCase;

/**
 * Test case for Jira issue# BEANUTILS-347.
 *
 * @see <a href="https://issues.apache.org/jira/browse/BEANUTILS-347">https://issues.apache.org/jira/browse/BEANUTILS-347</a>
 */
public class Jira347TestCase extends TestCase {

    /**
     * Tests that MappedPropertyDescriptor does not throw an exception while re-creating a Method reference after it
     * has been garbage collected under the following circumstances.
     * - a class has a property 'mappedProperty'
     * - there is no getter for this property
     * - there is method setMappedProperty(MappedPropertyTestBean,MappedPropertyTestBean)
     *
     * In this case getMappedWriteMethod should not throw an exception after the method reference has been garbage collected.
     * It is essential that in both cases the same method is returned or in both cases null.
     * If the constructor of the MappedPropertyDescriptor would recognize the situation (of the first param not being of type String)
     * this would be fine as well.
     */
    public void testMappedPropertyDescriptor_AnyArgsProperty() throws Exception {
        final String className = "org.apache.commons.beanutils2.MappedPropertyTestBean";
        final ClassLoader loader = newClassLoader();
        final Class<?> beanClass    = loader.loadClass(className);
        beanClass.newInstance();


        // Sanity checks only
        assertNotNull("ClassLoader is null", loader);
        assertNotNull("BeanClass is null", beanClass);
        assertNotSame("ClassLoaders should be different..", getClass().getClassLoader(), beanClass.getClassLoader());
        assertSame("BeanClass ClassLoader incorrect", beanClass.getClassLoader(), loader);

        // now start the test
        MappedPropertyDescriptor descriptor = null;
        try {
          descriptor = new MappedPropertyDescriptor("anyMapped", beanClass);
        }
        catch (final IntrospectionException e) {
          // this would be fine as well
        }

        if (descriptor != null) {
            final String m1 = getMappedWriteMethod(descriptor);
             forceGarbageCollection();
             try {
                 final String m2 = getMappedWriteMethod(descriptor);
                 assertEquals("Method returned post garbage collection differs from Method returned prior to gc", m1, m2);
             }
             catch (final RuntimeException e) {
                 fail("getMappedWriteMethod threw an exception after garbage collection " + e);
             }
        }
    }

    /**
     * Retrieves the string representation of the mapped write method
     * for the given descriptor.
     * This conversion is needed as there must not be strong reference to the
     * Method object outside of this method as otherwise the garbage collector will not
     * clean up the soft reference within the MappedPropertyDescriptor.
     *
     * @return the string representation or null if mapped write method does not exist
     */
    private String getMappedWriteMethod(final MappedPropertyDescriptor descriptor) {
        final Method m = descriptor.getMappedWriteMethod();
        return m == null ? null : m.toString();
    }

    /**
     * Try to force the garbage collector to run by filling up memory and calling System.gc().
     */
    private void forceGarbageCollection() throws Exception {
        // Fill up memory
        final SoftReference<Object> ref = new SoftReference<>(new Object());
        int count = 0;
        while(ref.get() != null && count++ < 5) {
            ArrayList<Object> list = new ArrayList<>();
            try {
                long i = 0;
                while (true && ref.get() != null) {
                    list.add("A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String " + i++);
                }
            } catch (final Throwable ignored) {
            }
            list.clear();
            list = null;
            // System.out.println("Count " + count + " : " + getMemoryStats());
            System.gc();
            Thread.sleep(1000);
        }
        // System.out.println("After GC: " + getMemoryStats());

        if (ref.get() != null) {
            throw new IllegalStateException("Your JVM is not releasing SoftReference, try running the testcase with less memory (-Xmx)");
        }
    }

    /**
     * Create a new class loader instance.
     */
    private static URLClassLoader newClassLoader() throws MalformedURLException {

        final String dataFilePath = MemoryLeakTestCase.class.getResource("pojotests").getFile();
        //System.out.println("dataFilePath: " + dataFilePath);
        final String location = "file://" + dataFilePath.substring(0,dataFilePath.length()-"org.apache.commons.beanutils2.memoryleaktests.pojotests".length());
        //System.out.println("location: " + location);

        final StringBuilder newString = new StringBuilder();
        for (int i=0;i<location.length();i++) {
            if (location.charAt(i)=='\\') {
                newString.append("/");
            } else {
                newString.append(location.charAt(i));
            }
        }
        final String classLocation = newString.toString();
        //System.out.println("classlocation: " + classLocation);

        final URLClassLoader theLoader = URLClassLoader.newInstance(new URL[]{new URL(classLocation)},null);
        return theLoader;
    }
}
