All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.util.SubClassGenerator Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2010, InfraDNA, Inc.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 *
 *
 *
 *******************************************************************************/ 

package hudson.util;

import hudson.PluginManager.UberClassLoader;
import hudson.model.Hudson;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

import java.lang.reflect.Constructor;

import static org.objectweb.asm.Opcodes.*;

/**
 * Generates a new class that just defines constructors into the super types.
 *
 * @author Kohsuke Kawaguchi
 */
public class SubClassGenerator extends ClassLoader {

    public SubClassGenerator(ClassLoader parent) {
        super(parent);
    }

    public  Class generate(Class base, String name) {
        ClassWriter cw = new ClassWriter(false, false);//?
        cw.visit(49, ACC_PUBLIC, name.replace('.', '/'), null,
                Type.getInternalName(base), null);

        for (Constructor c : base.getDeclaredConstructors()) {
            Class[] et = c.getExceptionTypes();
            String[] exceptions = new String[et.length];
            for (int i = 0; i < et.length; i++) {
                exceptions[i] = Type.getInternalName(et[i]);
            }

            String methodDescriptor = getMethodDescriptor(c);
            MethodVisitor m = cw.visitMethod(c.getModifiers(), "", methodDescriptor, null, exceptions);
            m.visitCode();

            int index = 1;
            m.visitVarInsn(ALOAD, 0);
            for (Class param : c.getParameterTypes()) {
                Type t = Type.getType(param);
                m.visitVarInsn(t.getOpcode(ILOAD), index);
                index += t.getSize();
            }
            m.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(base), "", methodDescriptor);
            m.visitInsn(RETURN);
            m.visitMaxs(index, index);
            m.visitEnd();
        }

        cw.visitEnd();
        byte[] image = cw.toByteArray();

        Class c = defineClass(name, image, 0, image.length).asSubclass(base);

        Hudson h = Hudson.getInstance();
        if (h != null) // null only during tests.
        {
            ((UberClassLoader) h.pluginManager.uberClassLoader).addNamedClass(name, c); // can't change the field type as it breaks binary compatibility
        }
        return c;
    }

    private String getMethodDescriptor(Constructor c) {
        StringBuilder buf = new StringBuilder();
        buf.append('(');
        for (Class p : c.getParameterTypes()) {
            buf.append(Type.getDescriptor(p));
        }

        buf.append(")V");
        return buf.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy