Package com.alibaba.citrus.codegen

Source Code of com.alibaba.citrus.codegen.ClassPool$PooledClassBuilder

/*
* Copyright 2010 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.citrus.codegen;

import static com.alibaba.citrus.codegen.util.CodegenConstant.*;
import static com.alibaba.citrus.codegen.util.CodegenUtil.*;
import static com.alibaba.citrus.codegen.util.TypeUtil.*;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import com.alibaba.citrus.asm.ClassReader;
import com.alibaba.citrus.asm.ClassWriter;
import com.alibaba.citrus.asm.util.TraceClassVisitor;

/**
* ��̬���ɺͱ������ӿڡ�
*
* @author Michael Zhou
*/
public class ClassPool {
    private final BytecodeLoader classLoader;
    private boolean debugging;
    private File debuggingLocation;
    private int classWriterFlags;
    private String packageName;

    /**
     * ����һ��<code>ClassPool</code>��ʹ��װ��<code>ClassPool</code>���
     * <code>ClassLoader</code>��
     */
    public ClassPool() {
        this(null);
    }

    /**
     * ����һ��<code>ClassPool</code>��ʹ��ָ����<code>ClassLoader</code>��
     */
    public ClassPool(ClassLoader parentClassLoader) {
        if (parentClassLoader == null) {
            parentClassLoader = getClass().getClassLoader();
        }

        this.classLoader = new BytecodeLoader(parentClassLoader);
        this.classWriterFlags = DEFAULT_CLASS_WRITER_FLAGS;
        this.packageName = DEFAULT_PACKAGE_NAME;
    }

    /**
     * ȡ��<code>ClassLoader</code>��
     */
    public ClassLoader getClassLoader() {
        return classLoader;
    }

    /**
     * �Ƿ񱣴�classԴ�ļ���Ŀ���ļ���
     */
    public boolean isDebugging() {
        return debugging;
    }

    /**
     * ���ò������Ƿ񱣴�classԴ�ļ���Ŀ���ļ���
     */
    public void setDebugging(boolean debugging) {
        this.debugging = debugging;
    }

    /**
     * Class��Դ����Ͷ������ļ������������Ŀ¼��
     */
    public File getDebuggingLocation() {
        return debuggingLocation;
    }

    /**
     * ����class��Դ����Ͷ������ļ������Ŀ¼��
     */
    public void setDebuggingLocation(File debuggingLocation) {
        this.debuggingLocation = debuggingLocation;
    }

    /**
     * ȡ��<code>ClassWriter</code>�ı�־λ��
     */
    public int getClassWriterFlags() {
        return classWriterFlags;
    }

    /**
     * ����<code>ClassWriter</code>�ı�־λ��
     */
    public void setClassWriterFlags(int classWriterFlags) {
        this.classWriterFlags = classWriterFlags;
    }

    /**
     * ȡ�����ɴ����package���ơ�
     */
    public String getPackageName() {
        return packageName;
    }

    /**
     * �������ɴ����package���ơ�
     */
    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createClass(String basename, Class<?> superclass, Class<?>[] interfaces) {
        return createClassOrInterface(-1, false, basename, superclass, interfaces, -1, null);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createClass(int access, String basename, Class<?> superclass, Class<?>[] interfaces) {
        return createClassOrInterface(access, false, basename, superclass, interfaces, -1, null);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createClass(int access, String basename, Class<?> superclass, Class<?>[] interfaces,
                                    int classVersion, String source) {
        return createClassOrInterface(access, false, basename, superclass, interfaces, classVersion, source);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�ӿ����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createInterface(String basename, Class<?>[] interfaces) {
        return createClassOrInterface(-1, true, basename, null, interfaces, -1, null);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�ӿ����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createInterface(int access, String basename, Class<?>[] interfaces) {
        return createClassOrInterface(access, true, basename, null, interfaces, -1, null);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�ӿ����������������������͵�<code>ClassBuilder</code>��
     */
    public ClassBuilder createInterface(int access, String basename, Class<?>[] interfaces, int classVersion,
                                        String source) {
        return createClassOrInterface(access, true, basename, null, interfaces, classVersion, source);
    }

    /**
     * ����ָ����<code>basename</code>����һ��Ψһ�����������������������͵�<code>ClassBuilder</code>��
     */
    private ClassBuilder createClassOrInterface(int access, boolean isInterface, String basename, Class<?> superclass,
                                                Class<?>[] interfaces, int classVersion, String source) {
        String className = generateClassName(basename, getPackageName());
        ClassWriter cw = new DebuggingClassWriter();

        return new PooledClassBuilder(cw, access, isInterface, className, superclass, interfaces, classVersion, source);
    }

    /**
     * ����װ��bytecode��<code>ClassLoader</code>��
     */
    private static class BytecodeLoader extends ClassLoader {
        public BytecodeLoader(ClassLoader parentClassLoader) {
            super(parentClassLoader);
        }

        public Class<?> defineClass(String className, byte[] bytes) {
            return defineClass(className, bytes, 0, bytes.length, getClass().getProtectionDomain());
        }
    }

    /**
     * ��̬�������ӿڡ�
     */
    private class PooledClassBuilder extends ClassBuilder {
        public PooledClassBuilder(ClassWriter cw, int access, boolean isInterface, String className,
                                  Class<?> superclass, Class<?>[] interfaces, int classVersion, String source) {
            super(cw, access, isInterface, className, superclass, interfaces, classVersion, source);
        }

        @Override
        public Class<?> defineClass(String className, byte[] bytes) {
            return classLoader.defineClass(className, bytes);
        }
    }

    /**
     * ֧��debugging���ഴ������
     */
    private class DebuggingClassWriter extends ClassWriter {
        private String className;

        public DebuggingClassWriter() {
            super(classWriterFlags);
        }

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            if (debugging) {
                this.className = getTypeFromInternalName(name).getClassName();
            }

            super.visit(version, access, name, signature, superName, interfaces);
        }

        @Override
        public byte[] toByteArray() {
            byte[] bytes = super.toByteArray();

            if (className != null) {
                if (debuggingLocation == null) {
                    debuggingLocation = new File(System.getProperty("java.io.tmpdir"));
                }

                File baseFile = new File(debuggingLocation, className.replace('.', File.separatorChar));
                File classDir = baseFile.getParentFile();

                classDir.mkdirs();

                if (classDir.exists() && classDir.isDirectory()) {
                    try {
                        // ���class�ļ�
                        File classFile = new File(classDir, baseFile.getName() + ".class");
                        OutputStream out = new BufferedOutputStream(new FileOutputStream(classFile));

                        try {
                            out.write(bytes);
                        } finally {
                            out.close();
                        }

                        // ���asm�ļ�
                        File asmFile = new File(classDir, baseFile.getName() + ".asm");
                        out = new BufferedOutputStream(new FileOutputStream(asmFile));

                        try {
                            ClassReader cr = new ClassReader(bytes);
                            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
                            TraceClassVisitor tcv = new TraceClassVisitor(null, pw);

                            cr.accept(tcv, 0);
                            pw.flush();
                        } finally {
                            out.close();
                        }
                    } catch (IOException e) {
                    }
                }
            }

            return bytes;
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.codegen.ClassPool$PooledClassBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.