/*
 *  Copyright 2008 biaoping.yin
 *
 *  Licensed 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.frameworkset.util.asm;

import java.lang.reflect.Method;
import java.util.List;

import org.apache.log4j.Logger;
import org.frameworkset.util.ClassUtil.PropertieDescription;

import bboss.org.objectweb.asm.ClassReader;
import bboss.org.objectweb.asm.ClassWriter;



/**
 * <p>Title: AsmUtil.java</p> 
 * <p>Description: </p>
 * <p>bboss workgroup</p>
 * <p>Copyright (c) 2008</p>
 * @Date 2011-12-29
 * @author biaoping.yin
 * @version 1.0
 */
public class AsmUtil {
	private static final ASMClassLoader classLoader = new ASMClassLoader();
	private static final Logger log = Logger.getLogger(AsmUtil.class);
	
	public static final String bboss_field_getMethod_prex = "___bboss_pull";
	public static final String bboss_field_setMethod_prex = "___bboss_put";
	
//	public static class MethodNode
//	{
//		String field
//	}
//	public static Method addFieldWriteMethodToClass(Class clazz,Field field) throws IOException
//	{
//		ClassWriter cw = new ClassWriter(new ClassReader(clazz.getCanonicalName()),0);
//	    CheckClassAdapter ca = new CheckClassAdapter(cw);
//	    AddMethodAdaptor am = new AddMethodAdaptor(ca);
//	    
//	}
	
	public static Class addGETSETMethodForClass(List<PropertieDescription> propertieDescriptionies,Class beanType)
	{
		String className = beanType.getName();
		try {
//			String className = beanType.getName();
			ClassReader cr = new ClassReader(className);
			ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
			cr.accept(new ASMPUTGETFieldAdapter(cw,beanType,propertieDescriptionies),0);
			beanType = classLoader.defineClass(className, cw.toByteArray());		
			return beanType;
//			Method temp = beanType.getMethod(AsmUtil.bboss_field_getMethod_prex + "Age");
			
		} catch (Exception e) {
			log.error("Add field's GET/SET Method For ["+className+"] failed:",e);
			return beanType;
		}
	}
	
	
	
//	public static void main(String[] args) throws IOException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, InstantiationException
//	{
////		ClassReader reader = new ClassReader("java.lang.String");
////		reader.accept(new MyClassVisitor(), 0);
//		
//		Foo foo = new Foo();
//		foo.execute("duoduo","中国");
//		
//		ClassReader cr = new ClassReader(Foo.class.getName());
//		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
//		cr.accept(new ClassAdapter(cw,Opcodes.ASM4){
//
//			@Override
//			public void visit(int version, int access, String name,
//					String signature, String superName, String[] interfaces) {
//				// TODO Auto-generated method stub
//				super.visit(version, access, name, signature, superName, interfaces);
//			}
//
//			@Override
//			public MethodVisitor visitMethod(int access, String name,
//					String desc, String signature, String[] exceptions) {
//				// TODO Auto-generated method stub
//				if(name.equals("execute"))
//				{
//					return cv.visitMethod(access, name+"$bboss1", desc, signature, exceptions);
//				}
//				else
//				{
//					return cv.visitMethod(access, name, desc, signature, exceptions);
//				}
//			}
//
//			@Override
//			public FieldVisitor visitField(int access, String name,
//					String desc, String signature, Object value) {
//				if(name.equals("age"))
//				{
//					/**
//					 * //我们接着需要增加一个execute方法
//         MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "execute",
//                 "()V", null,
//                 null);
//         //开始增加代码
//         mv.visitCode();
//         //接下来，我们需要把新的execute方法的内容，增加到这个方法中
//         mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
//         mv.visitLdcInsn("Before execute");
//         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); 
//         mv.visitVarInsn(Opcodes.ALOAD, 0);
//         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/vanadies/bytecode/example/asm3/ClassWriterAopExample$Foo$1", "execute$1", "()V");
//         mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
//         mv.visitLdcInsn("End execute");
//         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
//         mv.visitInsn(Opcodes.RETURN);
//         mv.visitMaxs(0, 0); //这个地方，最大的操作数栈和最大的本地变量的空间，是自动计算的，是因为构造ClassWriter的时候使用了ClassWriter.COMPUTE_MAXS
//         mv.visitEnd();
//         //到这里，就完成了execute方法的添加。
//
//					 */
//					String className = Foo.class.getName();
//					className = className.replace(".", "/");
//					//我们接着需要增加一个execute方法
//					String getMd = new StringBuffer(6).append("get")
//		            .append(Character.toTitleCase(name.charAt(0)))
//		            .append(name.substring(1))
//		            .toString();
//					
//					String setMd = new StringBuffer(6).append("set")
//				            .append(Character.toTitleCase(name.charAt(0)))
//				            .append(name.substring(1))
//				            .toString();
//					
//			         MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, getMd,
//			                 "()" + desc, null,
//			                 null);
//			        
////			         mv = cw.visitMethod(ACC_PUBLIC, getMd, "()I", null, null);
//						mv.visitCode();
//						mv.visitVarInsn(Opcodes.ALOAD, 0);
//						mv.visitFieldInsn(Opcodes.GETFIELD, className, name, desc);
//						mv.visitInsn(Opcodes.ARETURN);
//						mv.visitMaxs(1, 1);
//						// mw.visitInsn(RETURN);
//						// this code uses a maximum of two stack elements and two local
//						// variables
//						mv.visitEnd();
//						mv = cv.visitMethod(Opcodes.ACC_PUBLIC, setMd,
//				                 "("+desc+")V", null,
//				                 null);
//						mv.visitCode();
//						mv.visitVarInsn(Opcodes.ALOAD, 0);
//						mv.visitVarInsn(Opcodes.ALOAD, 1);
//						mv.visitFieldInsn(Opcodes.PUTFIELD, className, name, desc);
//						mv.visitInsn(Opcodes.RETURN);
//						mv.visitMaxs(2, 2);
//						// mw.visitInsn(RETURN);
//						// this code uses a maximum of two stack elements and two local
//						// variables
//						mv.visitEnd();
//			           
//			         //到这里，就完成了execute方法的添加。
//				}
//				return super.visitField(access, name, desc, signature, value);
//			}
//
//			
//			
//		},0);
//		TestClassLoader LOADER = new TestClassLoader();
//		Class c = LOADER.defineClass(Foo.class.getName(), cw.toByteArray());
////		Class c = Class.forName(Foo.class.getName() +"_bboss1");
//		Method m = c.getMethod("execute$bboss1",String.class,String.class);
//		Method gage = c.getMethod("getAge");
//		Method sage = c.getMethod("setAge",String.class);
//		Object o = c.newInstance();
//		sage.invoke(o, "18");
//		m.invoke(c.newInstance(),"duoduo","中国");
//		System.out.println(gage.invoke(o));
//		
//	}
	
	
	
//	static class TestClassLoader extends ClassLoader {
//
//	    public Class defineClass(String name, byte[] b) {
//	      return defineClass(name, b, 0, b.length);
//	    }
//	  }
//	
//	public static class Foo
//	{
//		private String age;
//		public String execute(String name,String country)
//		{
//			System.out.println("helloword:" + name);
//			return "helloword:" + name;
//		}
//	}
//	
//	public static class MyClassVisitor extends ClassVisitor
//	{
//
//		public MyClassVisitor(int api) {
//			super(api);
//			// TODO Auto-generated constructor stub
//		}
//
//		public void visit(int arg0, int arg1, String arg2, String arg3,
//				String arg4, String[] arg5) {
//			System.out.println(arg2);
//			System.out.println(arg3);
//			System.out.println(arg4);
//		}
//
//		public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
//			// TODO Auto-generated method stub
//			return null;
//		}
//
//		public void visitAttribute(Attribute arg0) {
//			// TODO Auto-generated method stub
//			
//		}
//
//		public void visitEnd() {
//			// TODO Auto-generated method stub
//			
//		}
//
//		public FieldVisitor visitField(int arg0, String arg1, String arg2,
//				String arg3, Object arg4) {
//			// TODO Auto-generated method stub
//			return null;
//		}
//
//		public void visitInnerClass(String arg0, String arg1, String arg2,
//				int arg3) {
//			// TODO Auto-generated method stub
//			
//		}
//
//		public MethodVisitor visitMethod(int arg0, String arg1, String arg2,
//				String arg3, String[] arg4) {
//			// TODO Auto-generated method stub
//			return null;
//		}
//
//		public void visitOuterClass(String arg0, String arg1, String arg2) {
//			// TODO Auto-generated method stub
//			
//		}
//
//		public void visitSource(String arg0, String arg1) {
//			// TODO Auto-generated method stub
//			
//		}
//		
//	}
}
