/**************************************************************************************
 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
 * http://aspectwerkz.codehaus.org                                                    *
 * ---------------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the LGPL license      *
 * a copy of which has been included with this distribution in the license.txt file.  *
 **************************************************************************************/
package test.clapp;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * App loading lots of class in lots of threads <p/>Mandatory args = thread number, loop per thread,
 * pause between loops <br/>If no args are provided, defaults to 2, 5, 5ms. <br/><br/>Each thread
 * loop loads DummyClass thru a dedicated URLClassLoader (no parent) at each loop
 * <br/>test.xmldef.clapp.DummyClass and test.xmldef.clapp.ReentrantDummyClass must be in directory
 * specified thru -DDummyClass, defaults <i>ASPECTWERKZ_HOME </i>/target/test-classes <br/>During
 * the DummyClass clinit, another class is loaded thru another URLClassLoader (no parent)
 * 
 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
 */
public class CrazyClassLoaderApp {
    private static final String DUMMYCLASS_LOCATION_PROP = "DummyClass";

    public static String DUMMYCLASS_LOCATION = System.getProperty(DUMMYCLASS_LOCATION_PROP);

    static {
        if (DUMMYCLASS_LOCATION == null) {
            DUMMYCLASS_LOCATION = System.getProperty("ASPECTWERKZ_HOME")
                + File.separator
                + "target"
                + File.separator
                + "test-classes";
        }
    }

    /**
     * log
     */
    private static void log(String s) {
        System.out.println(s);
    }

    /**
     * launch all thread and join() with them
     */
    public static void main(String[] args) throws Exception {
        int thread = 2;
        int count = 5;
        int mspause = 5;
        try {
            thread = Integer.parseInt(args[0]);
            count = Integer.parseInt(args[1]);
            mspause = Integer.parseInt(args[2]);
        } catch (Exception e) {
            ;
        }
        long start = System.currentTimeMillis();
        log("BEGIN:" + thread + ':' + count + ':' + mspause + ':' + DUMMYCLASS_LOCATION);
        Thread[] threads = new Thread[thread];
        for (int i = 0; i < thread; i++) {
            Worker w = new Worker(count, mspause);
            w.setPriority(Thread.MAX_PRIORITY - 1);
            w.start();
            log("started " + i);
            threads[i] = w;
        }
        for (int i = 0; i < thread; i++) {
            threads[i].join();
            log("joined " + i);
        }
        log("END");
        log("( " + ((int) (System.currentTimeMillis() - start) / 1000) + " s)");
        log("classes=" + (thread * count * 2));
        System.exit(0);
    }

    private static class Worker extends Thread {
        public static transient int total = 0;

        int count = 10;

        long mspause = 1000;

        URL url = null;

        public Worker(int count, long mspause) {
            this.count = count;
            this.mspause = mspause;
            try {
                this.url = new java.io.File(DUMMYCLASS_LOCATION).toURL();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void run() {
            int i = 0;
            while (i < count) {
                try {
                    i++;
                    ClassLoader tmpLoader = new URLClassLoader(new URL[] {
                        url
                    }, null);
                    Class dummyClass = tmpLoader.loadClass("test.clapp.DummyClass");
                    Object dummyInstance = dummyClass.newInstance();
                    total++;
                    log(total
                        + " "
                        + this.getName()
                        + ':'
                        + i
                        + ":DumyClass.hashcode="
                        + dummyInstance.getClass().hashCode());
                    synchronized (this) {
                        wait(mspause);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}