package org.nutz.ioc.aop.impl;

import java.util.List;

import org.nutz.aop.ClassAgent;
import org.nutz.aop.ClassDefiner;
import org.nutz.aop.DefaultClassDefiner;
import org.nutz.aop.MethodInterceptor;
import org.nutz.aop.asm.AsmClassAgent;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.aop.MirrorFactory;
import org.nutz.ioc.aop.config.AopConfigration;
import org.nutz.ioc.aop.config.InterceptorPair;
import org.nutz.ioc.aop.config.impl.AnnotationAopConfigration;
import org.nutz.lang.Mirror;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * 通过AopConfigration来识别需要拦截的方法,并根据需要生成新的类
 * 
 * @author zozoh(zozohtnt@gmail.com)
 * @author Wendal(wendal1985@gmail.com)
 */
public class DefaultMirrorFactory implements MirrorFactory {
    
    private static final Log log = Logs.get();

    private Ioc ioc;

    private ClassDefiner cd;

    private AopConfigration aopConfigration;

    public DefaultMirrorFactory(Ioc ioc) {
        this.ioc = ioc;
        this.cd = new DefaultClassDefiner(getClass().getClassLoader());
    }

    @SuppressWarnings("unchecked")
    public <T> Mirror<T> getMirror(Class<T> type, String name) {
        if (MethodInterceptor.class.isAssignableFrom(type)
            || type.getName().endsWith(ClassAgent.CLASSNAME_SUFFIX)
            || AopConfigration.IOCNAME.equals(name)
            || AopConfigration.class.isAssignableFrom(type)) {
            return Mirror.me(type);
        }
        try {
            return (Mirror<T>) Mirror.me(cd.load(type.getName() + ClassAgent.CLASSNAME_SUFFIX));
        }
        catch (ClassNotFoundException e) {}
        if (aopConfigration == null)
            if (ioc.has(AopConfigration.IOCNAME))
                aopConfigration = ioc.get(AopConfigration.class, AopConfigration.IOCNAME);
            else
                aopConfigration = new AnnotationAopConfigration();
        List<InterceptorPair> interceptorPairs = aopConfigration.getInterceptorPairList(ioc, type);
        if (interceptorPairs == null || interceptorPairs.size() < 1) {
            if (log.isDebugEnabled())
                log.debugf("%s , no config to enable AOP.", type);
            return Mirror.me(type);
        }
        ClassAgent agent = new AsmClassAgent();
        for (InterceptorPair interceptorPair : interceptorPairs)
            agent.addInterceptor(    interceptorPair.getMethodMatcher(),
                                    interceptorPair.getMethodInterceptor());
        return Mirror.me(agent.define(cd, type));
    }

    public void setAopConfigration(AopConfigration aopConfigration) {
        this.aopConfigration = aopConfigration;
    }
}

@@ -912,16 +912,76 @@
 ration;%0D
+%0A    %0D%0A    private static final Object lock = new Object();%0D
 %0A%0D%0A    p
@@ -1048,81 +1048,8 @@
 c;%0D%0A
-        this.cd = new DefaultClassDefiner(getClass().getClassLoader());%0D%0A
     
@@ -1441,32 +1441,32 @@
 e);%0D%0A        %7D%0D%0A
-
         try %7B%0D%0A 
@@ -1460,24 +1460,623 @@
      try %7B%0D%0A
+        %09// %E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E7%9A%84%E7%94%B1%E6%9D%A5:%0D%0A        %09// %E5%BD%93%E7%94%A8%E6%88%B7%E6%8A%8Anutz.jar%E6%94%BE%E5%88%B0java.ext.dirs%E4%B8%8B%E9%9D%A2%E6%97%B6,DefaultMirrorFactory%E7%9A%84classloader%E5%B0%86%E6%97%A0%E6%B3%95%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E7%9A%84%E7%B1%BB%0D%0A        %09if (cd == null) %7B%0D%0A        %09%09synchronized (lock) %7B%0D%0A        %09%09%09if (cd == null) %7B%0D%0A        %09%09%09%09ClassLoader cd = type.getClassLoader();%0D%0A        %09%09%09%09if (cd == null) %7B%0D%0A        %09%09%09%09%09cd = Thread.currentThread().getContextClassLoader();%0D%0A        %09%09%09%09%09if (cd == null)%0D%0A        %09%09%09%09%09%09cd = getClass().getClassLoader();%0D%0A        %09%09%09%09%7D%0D%0A        %09%09%09%09log.info(%22Use as AOP ClassLoader parent : %22 + cd);%0D%0A        %09%09        this.cd = new DefaultClassDefiner(cd);%0D%0A        %09%09%09%7D%0D%0A%09%09%09%09%7D%0D%0A        %09%7D%0D%0A
             

fix issue #487