package org.nutz.aop;

import java.security.AccessController;
import java.security.PrivilegedAction;

import org.nutz.lang.Lang;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * 一个默认的类加载器
 * 
 * @author Wendal(wendal1985@gmail.com)
 */
public class DefaultClassDefiner extends ClassLoader implements ClassDefiner {
	
    private static final Log log = Logs.get();
    
	protected static ClassDefiner one;
	
	protected static ClassLoader moreClassLoader;
	
	public static void init(final ClassLoader cd) {
	    log.debug("init DefaultClassDefiner by ClassLoader=" + cd);
		if (one == null) {
			synchronized (DefaultClassDefiner.class) {
				if (one == null) {
					AccessController.doPrivileged(new PrivilegedAction<DefaultClassDefiner>() {
			            public DefaultClassDefiner run() {
			                if (cd != null)
			                    one = new DefaultClassDefiner(cd);
			                else
			                    one = new DefaultClassDefiner(DefaultClassDefiner.class.getClassLoader());
			                return (DefaultClassDefiner) DefaultClassDefiner.defaultOne();
			            }
			        });
				}
			}
		}
		if (moreClassLoader == null && cd != null)
			moreClassLoader = cd;
	}

	public static ClassDefiner defaultOne() {
		if (one == null)
			init(null);
		return one;
	}
	
	public static final Class<?> def(String className, byte[] bytes) {
		try {
			return defaultOne().load(className);
		} catch (Throwable e) {
			// TODO: handle exception
		}
		return defaultOne().define(className, bytes);
	}
	
	/**
	 * 虽然是public的,但一般情况下不需要用哦. 用默认的全局ClassDefiner就很好.
	 */
    public DefaultClassDefiner(ClassLoader parent) {
        super(parent);
    }

    public Class<?> define(String className, byte[] bytes) throws ClassFormatError {
        try {
            return load(className);
        }
        catch (ClassNotFoundException e) {}
        // If not found ...
        return defineClass(className, bytes, 0, bytes.length);
    }

    public boolean has(String className) {
        try {
            load(className);
            return true;
        }
        catch (ClassNotFoundException e) {}
        return false;
    }

    public Class<?> load(String className) throws ClassNotFoundException {
        try {
            return Lang.loadClass(className);
        }
        catch (ClassNotFoundException e) {
            try {
                return ClassLoader.getSystemClassLoader().loadClass(className);
            }
            catch (ClassNotFoundException e2) {
                try {
                    return getParent().loadClass(className);
                }
                catch (ClassNotFoundException e3) {}
            }
            catch (SecurityException e2) {// Fix for GAE 1.3.7, Fix issue 296
                try {
                    return getParent().loadClass(className);
                }
                catch (ClassNotFoundException e3) {}
            }
        }
        if (moreClassLoader != null) {
        	try {
				return moreClassLoader.loadClass(className);
			} catch (Throwable e) {
			}
        }
        return super.loadClass(className);
    }
    
    public static void reset() {
    	one = null;
    	defaultOne();
    }
}

@@ -201,11 +201,12 @@
 %E9%BB%98%E8%AE%A4%E7%9A%84%E7%B1%BB
-%E5%8A%A0%E8%BD%BD%E5%99%A8
+%E5%AE%9A%E4%B9%89%E5%AE%9E%E7%8E%B0
 %0D%0A *

fix javadoc:DefaultClassDefiner