Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: EPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Eclipse Public License Version 1.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.eclipse.org/legal/epl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the EPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the EPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 
 package org.jruby.javasupport.proxy;
 
 import java.util.Map;
 import java.util.Set;
 
 import org.jruby.Ruby;
 import static org.jruby.javasupport.JavaClass.EMPTY_CLASS_ARRAY;
 
 import  org.objectweb.asm.ClassVisitor;
 import  org.objectweb.asm.ClassWriter;
 import  org.objectweb.asm.FieldVisitor;
 import  org.objectweb.asm.Label;
 import  org.objectweb.asm.MethodVisitor;
 import  org.objectweb.asm.Opcodes;
 import  org.objectweb.asm.Type;
 import  org.objectweb.asm.commons.GeneratorAdapter;
 
 public class JavaProxyClassFactory {
     private static final Logger LOG = LoggerFactory.getLogger("JavaProxyClassFactory");
 
     static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
 
     static final Type JAVA_LANG_CLASS_TYPE = Type.getType(Class.class);
 
     private static final org.objectweb.asm.commons.Method forName = org.objectweb.asm.commons.Method
         .getMethod("java.lang.Class forName(java.lang.String)");
 
     private static final String INVOCATION_HANDLER_FIELD_NAME = "__handler";
 
     private static final String PROXY_CLASS_FIELD_NAME = "__proxy_class";
 
     private static final Type PROXY_METHOD_TYPE = Type.getType(JavaProxyMethod.class);
 
     private static final Type PROXY_CLASS_TYPE = Type.getType(JavaProxyClass.class);
 
     private static final Type INVOCATION_HANDLER_TYPE = Type.getType(JavaProxyInvocationHandler.class);
 
     // public Object invoke(Object receiver, JavaProxyMethod method, Object[] args)
     private static final org.objectweb.asm.commons.Method invoke = org.objectweb.asm.commons.Method
         .getMethod("java.lang.Object invoke(java.lang.Object, " + .getClassName() + ", java.lang.Object[])");
 
     private static final Type INTERNAL_PROXY_HELPER_TYPE = Type.getType(InternalJavaProxyHelper.class);
 
     // public static JavaProxyClass initProxyClass(Class)
     private static final org.objectweb.asm.commons.Method initProxyClass = org.objectweb.asm.commons.Method
         .getMethod(JavaProxyClass.class.getName() + " initProxyClass(java.lang.Class)");
 
     // public static JavaProxyMethod initProxyMethod(JavaProxyClass proxyClass, String name, String desc, boolean hasSuper)
     private static final org.objectweb.asm.commons.Method initProxyMethod = org.objectweb.asm.commons.Method
        .getMethod(.getClassName() + " initProxyMethod("
                    + JavaProxyClass.class.getName() + ",java.lang.String,java.lang.String,boolean)");
    private static final Type JAVA_PROXY_TYPE = Type.getType(InternalJavaProxy.class);
    private static final AtomicInteger counter = new AtomicInteger(0);
    private static int nextId() { return .incrementAndGet(); }
    public static JavaProxyClassFactory createFactory() {
        final String factoryClassName = ..load();
        JavaProxyClassFactory factory = null;
        if ( factoryClassName != null ) {
            try {
                Class clazz = Class.forName(factoryClassName);
                Object instance = clazz.newInstance();
                if ( instance instanceof JavaProxyClassFactory ) {
                    factory = (JavaProxyClassFactoryinstance;
                    .info("Created proxy class factory: " + factory);
                } else {
                    .error("Invalid proxy class factory: " + instance);
                }
            }
            catch (ClassNotFoundException e) {
                .error("ClassNotFoundException creating proxy class factory: " + e);
            }
            catch (InstantiationException e) {
                .error("InstantiationException creating proxy class factory: " + e);
            }
            catch (IllegalAccessException e) {
                .error("IllegalAccessException creating proxy class factory: " + e);
            }
        }
        return factory != null ? factory : new JavaProxyClassFactory();
    }
    public JavaProxyClass newProxyClass(final Ruby runtimeClassLoader loader,
            String targetClassNameClass superClassClass[] interfacesSet<Stringnames)
            throws InvocationTargetException {
        if (loader == nullloader = JavaProxyClassFactory.class.getClassLoader();
        if (superClass == nullsuperClass = Object.class;
        if (interfaces == nullinterfaces = ;
        // TODO key is a bit crazy - unfortunately Set<?> leaked into public API
        final Set<ObjectcacheKey = new HashSet<Object>();
        cacheKey.add(superClass);
        for (int i = 0; i < interfaces.lengthi++) {
            cacheKey.add(interfaces[i]);
        }
        // add (potentially) overridden names to the key.
        if (names != nullcacheKey.addAll(names);
        else names = Collections.emptySet(); // so we can assume names != null
        Map<Set<?>, JavaProxyClassproxyCache = runtime.getJavaSupport().getJavaProxyClassCache();
        JavaProxyClass proxyClass = proxyCache.get(cacheKey);
        if (proxyClass == null) {
            if (targetClassName == null) {
                targetClassName = targetClassName(superClass);
            }
            validateArgs(runtimetargetClassNamesuperClass);
            Type selfType = Type.getType("L" + toInternalClassName(targetClassName) + ";");
            Map<MethodKeyMethodDatamethods = collectMethods(superClassinterfacesnames);
            proxyClass = generate(loadertargetClassNamesuperClassinterfacesmethodsselfType);
            proxyCache.put(cacheKeyproxyClass);
        }
        return proxyClass;
    }
    private JavaProxyClass generate(ClassLoader loaderString targetClassName,
            Class superClassClass[] interfaces,
            Map<MethodKeyMethodDatamethods, Type selfType) {
        ClassWriter cw = beginProxyClass(targetClassNamesuperClassinterfaces);
        GeneratorAdapter clazzInit = createClassInitializer(selfTypecw);
        generateConstructors(superClassselfTypecw);
        generateGetProxyClass(selfTypecw);
        generateGetInvocationHandler(selfTypecw);
        generateProxyMethods(superClassmethodsselfTypecwclazzInit);
        // finish class initializer
        clazzInit.returnValue();
        clazzInit.endMethod();
        // end class
        cw.visitEnd();
        Class clazz = invokeDefineClass(loaderselfType.getClassName(), cw.toByteArray());
        // trigger class initialization for the class
        try {
            Field proxy_class = clazz.getDeclaredField();
            proxy_class.setAccessible(true);
            return (JavaProxyClassproxy_class.get(clazz);
        } catch (Exception ex) {
            InternalError ie = new InternalError();
            ie.initCause(ex);
            throw ie;
        }
    }
    private static String targetClassName(final Class clazz) {
        // We always prepend an org.jruby.proxy package to the beginning
        // because java and javax packages are protected and signed
        // jars prevent us generating new classes with those package
        // names. See JRUBY-2439.
        final String pkgName = proxyPackageName(clazz);
        final String fullName = clazz.getName();
        int ix = fullName.lastIndexOf('.');
        String className = ix == -1 ? fullName : fullName.substring(ix + 1);
        return pkgName + '.' + className + "$Proxy" + nextId();
    }
    private static final Method defineClassMethod;
    static {
         = AccessController.doPrivileged(new PrivilegedAction<Method>() {
            public Method run() {
                try {
                    final Class[] parameterTypes = { String.class,
                        byte[].classint.classint.classProtectionDomain.class
                    };
                    final Method method = ClassLoader.class.getDeclaredMethod("defineClass"parameterTypes);
                    method.setAccessible(true);
                    return method;
                }
                catch (Exception e) {
                    .error("could not use ClassLoader.defineClass method"e);
                    return null// should not happen!
                }
            }
        });
    }
    protected Class invokeDefineClass(ClassLoader loaderString classNamefinal byte[] data) {
        try {
            final Object[] parameters = { classNamedata, 0, data.lengthJavaProxyClassFactory.class.getProtectionDomain() };
            return (Class.invoke(loaderparameters);
        }
        catch (IllegalArgumentException e) {
            .warn("defining class with name " + className + " failed"e);
            return null;
        }
        catch (IllegalAccessException e) {
            .warn("defining class with name " + className + " failed"e);
            return null;
        }
        catch (InvocationTargetException e) {
            .warn("defining class with name " + className + " failed"e);
            return null;
        }
    }
    private ClassWriter beginProxyClass(final String className,
            final Class superClassfinal Class[] interfaces) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        // start class
        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER,
                toInternalClassName(className), /*signature*/ null,
                toInternalClassName(superClass),
                interfaceNamesForProxyClass(interfaces));
        cw.visitField(Opcodes.ACC_PRIVATE, ,
                .getDescriptor(), nullnull).visitEnd();
        cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
                .getDescriptor(), null,
                null).visitEnd();
        return cw;
    }
    private String[] interfaceNamesForProxyClass(final Class[] interfaces) {
        String[] interfaceNames = new String[interfaces.length + 1];
        for (int i = 0; i < interfaces.lengthi++) {
            interfaceNames[i] = toInternalClassName(interfaces[i]);
        }
        interfaceNames[interfaces.length] = toInternalClassName(InternalJavaProxy.class);
        return interfaceNames;
    }
    private void generateProxyMethods(Class superClass,
            Map<MethodKeyMethodDatamethods, Type selfType, ClassVisitor cw,
            GeneratorAdapter clazzInit) {
        for (MethodData mdmethods.values()) {
            Type superClassType = Type.getType(superClass);
            generateProxyMethod(selfTypesuperClassTypecwclazzInitmd);
        }
    }
    private void generateGetInvocationHandler(Type selfType, ClassVisitor cw) {
        // make getter for handler
        GeneratorAdapter gh = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
                new org.objectweb.asm.commons.Method("___getInvocationHandler",
                        ), null,
                cw);
        gh.loadThis();
        gh.getField(selfType);
        gh.returnValue();
        gh.endMethod();
    }
    private void generateGetProxyClass(Type selfType, ClassVisitor cw) {
        // make getter for proxy class
        GeneratorAdapter gpc = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
                new org.objectweb.asm.commons.Method("___getProxyClass",
                        ), null,
                cw);
        gpc.getStatic(selfType);
        gpc.returnValue();
        gpc.endMethod();
    }
    private void generateConstructors(Class superClass, Type selfType, ClassVisitor cw) {
        Constructor[] cons = superClass.getDeclaredConstructors();
        for (int i = 0; i < cons.lengthi++) {
            // if the constructor is private, pretend it doesn't exist
            if (Modifier.isPrivate(cons[i].getModifiers())) continue;
            // otherwise, define everything and let some of them fail at invocation
            generateConstructor(selfTypecons[i], cw);
        }
    }
    private GeneratorAdapter createClassInitializer(Type selfType, ClassVisitor cw) {
        GeneratorAdapter clazzInit = new GeneratorAdapter(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
                new org.objectweb.asm.commons.Method("<clinit>", Type.VOID_TYPE, ),
                nullcw);
        clazzInit.visitLdcInsn(selfType.getClassName());
        clazzInit.invokeStatic();
        clazzInit.invokeStatic();
        clazzInit.dup();
        clazzInit.putStatic(selfType);
        return clazzInit;
    }
    private void generateProxyMethod(Type selfType, Type superType,
            ClassVisitor cw, GeneratorAdapter clazzInitMethodData md) {
        if (!md.generateProxyMethod()) return;
        org.objectweb.asm.commons.Method m = md.getMethod();
        Type[] ex = toTypes(md.getExceptions());
        String field_name = "__mth$" + md.getName() + md.scrambledSignature();
        // create static private method field
        FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
                field_name.getDescriptor(), nullnull);
        fv.visitEnd();
        clazzInit.dup();
        clazzInit.push(m.getName());
        clazzInit.push(m.getDescriptor());
        clazzInit.push(md.isImplemented());
        clazzInit.invokeStatic();
        clazzInit.putStatic(selfTypefield_name);
        org.objectweb.asm.commons.Method sm = new org.objectweb.asm.commons.Method(
                "__super$" + m.getName(), m.getReturnType(), m.getArgumentTypes()
        );
        //
        // construct the proxy method
        //
        GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC, mnull,
                excw);
        ga.loadThis();
        ga.getField(selfType);
        // if the method is extending something, then we have
        // to test if the handler is initialized...
        if (md.isImplemented()) {
            ga.dup();
            Label ok = ga.newLabel();
            ga.ifNonNull(ok);
            ga.loadThis();
            ga.loadArgs();
            ga.invokeConstructor(superTypem);
            ga.returnValue();
            ga.mark(ok);
        }
        ga.loadThis();
        ga.getStatic(selfTypefield_name);
        if (m.getArgumentTypes().length == 0) {
            // load static empty array
            ga.getStatic("NO_ARGS"toType(Object[].class));
        } else {
            // box arguments
            ga.loadArgArray();
        }
        Label before = ga.mark();
        ga.invokeInterface();
        Label after = ga.mark();
        ga.unbox(m.getReturnType());
        ga.returnValue();
        // this is a simple rethrow handler
        Label rethrow = ga.mark();
        ga.visitInsn(Opcodes.ATHROW);
        for (int i = 0; i < ex.length; i++) {
            ga.visitTryCatchBlock(beforeafterrethrowex[i].getInternalName());
        }
        ga.visitTryCatchBlock(beforeafterrethrow"java/lang/Error");
        ga.visitTryCatchBlock(beforeafterrethrow"java/lang/RuntimeException");
        Type thr = toType(Throwable.class);
        Label handler = ga.mark();
        Type udt = toType(UndeclaredThrowableException.class);
        int loc = ga.newLocal(thr);
        ga.storeLocal(locthr);
        ga.newInstance(udt);
        ga.dup();
        ga.loadLocal(locthr);
        ga.invokeConstructor(udt, org.objectweb.asm.commons.Method.getMethod("void <init>(java.lang.Throwable)"));
        ga.throwException();
        ga.visitTryCatchBlock(beforeafterhandler"java/lang/Throwable");
        ga.endMethod();
        //
        // construct the super-proxy method
        //
        if (md.isImplemented()) {
            GeneratorAdapter ga2 = new GeneratorAdapter(Opcodes.ACC_PUBLIC, smnullexcw);
            ga2.loadThis();
            ga2.loadArgs();
            ga2.invokeConstructor(superTypem);
            ga2.returnValue();
            ga2.endMethod();
        }
    }
    private Class[] generateConstructor(Type selfTypeConstructor constructor, ClassVisitor cw) {
        Class[] superConstructorParameterTypes = constructor.getParameterTypes();
        Class[] newConstructorParameterTypes = new Class[superConstructorParameterTypes.length + 1];
        System.arraycopy(superConstructorParameterTypes, 0,
                newConstructorParameterTypes, 0,
                superConstructorParameterTypes.length);
        newConstructorParameterTypes[superConstructorParameterTypes.length] = JavaProxyInvocationHandler.class;
        int access = Opcodes.ACC_PUBLIC;
        String name1 = "<init>";
        String signature = null;
        Class[] superConstructorExceptions = constructor.getExceptionTypes();
        boolean superConstructorVarArgs = constructor.isVarArgs();
        org.objectweb.asm.commons.Method super_m = new org.objectweb.asm.commons.Method(
                name1, Type.VOID_TYPE, toTypes(superConstructorParameterTypes));
        org.objectweb.asm.commons.Method m = new org.objectweb.asm.commons.Method(
                name1, Type.VOID_TYPE, toTypes(newConstructorParameterTypes));
        String[] exceptionNames = toInternalNamessuperConstructorExceptions );
        MethodVisitor mv = cw.visitMethod(accessm.getName(), m.getDescriptor(), signatureexceptionNames);
        // marking with @SafeVarargs so that we can correctly detect proxied var-arg consturctors :
        if ( superConstructorVarArgs ) mv.visitAnnotation(Type.getDescriptor(VarArgs.class), true);
        GeneratorAdapter ga = new GeneratorAdapter(accessmmv);
        ga.loadThis();
        ga.loadArgs(0, superConstructorParameterTypes.length);
        ga.invokeConstructor(toType(constructor.getDeclaringClass()), super_m);
        ga.loadThis();
        ga.loadArg(superConstructorParameterTypes.length);
        ga.putField(selfType);
        // do a void return
        ga.returnValue();
        ga.endMethod();
        return newConstructorParameterTypes;
    }
    static boolean isVarArgs(final Constructor<?> ctor) {
        return ctor.isVarArgs() || ctor.getAnnotation(VarArgs.class) != null;
    }
    //static boolean isVarArgs(final Method method) {
    //    return method.isVarArgs() || method.getAnnotation(VarArgs.class) != null;
    //}
    private static String toInternalClassName(Class clazz) {
        return toInternalClassName(clazz.getName());
    }
    private static String toInternalClassName(String name) {
        return name.replace('.''/');
    }
    private static Type toType(Class clazz) {
        return Type.getType(clazz);
    }
    private static Type[] toTypes(Class[] params) {
        Type[] types = new Type[params.length];
        for (int i = 0; i < types.length; i++) {
            types[i] = Type.getType(params[i]);
        }
        return types;
    }
    private static String[] toInternalNames(final Class[] params) {
        if (params == nullreturn null;
        String[] names = new String[params.length];
        for (int i = 0; i < names.length; ++i) {
            names[i] = Type.getType(params[i]).getInternalName();
        }
        return names;
    }
    private static Map<MethodKeyMethodDatacollectMethods(
            final Class superClass,
            final Class[] interfaces,
            final Set<Stringnames) {
        Map<MethodKeyMethodDatamethods = new HashMap<MethodKeyMethodData>();
        HashSet<ClassallClasses = new HashSet<Class>();
        addClass(allClassesmethodssuperClassnames);
        addInterfaces(allClassesmethodsinterfacesnames);
        return methods;
    }
    static class MethodData {
        final Set<Methodmethods = new HashSet<Method>();
        final Method mostSpecificMethod;
        final Class[] mostSpecificParameterTypes;
        //private boolean hasPublicDecl = false;
        MethodData(final Method method) {
            this. = method;
            //hasPublicDecl = method.getDeclaringClass().isInterface() || Modifier.isPublic(method.getModifiers());
        }
        public String scrambledSignature() {
            StringBuilder sb = new StringBuilder();
            Class[] parms = getParameterTypes();
            for (int i = 0; i < parms.lengthi++) {
                sb.append('$');
                String name = parms[i].getName();
                name = name.replace('[''1');
                name = name.replace('.''_');
                name = name.replace(';''2');
                sb.append(name);
            }
            return sb.toString();
        }
        public Class getDeclaringClass() {
            return .getDeclaringClass();
        }
        public org.objectweb.asm.commons.Method getMethod() {
            return new org.objectweb.asm.commons.Method(getName(), Type
                    .getType(getReturnType()), getType(getParameterTypes()));
        }
        private Type[] getType(Class[] parameterTypes) {
            Type[] result = new Type[parameterTypes.length];
            for (int i = 0; i < parameterTypes.lengthi++) {
                result[i] = Type.getType(parameterTypes[i]);
            }
            return result;
        }
        private String getName() {
            return .getName();
        }
        private Class[] getParameterTypes() {
            return ;
        }
        public Class[] getExceptions() {
            final Set<Classexceptions = new HashSet<Class>();
            for ( final Method method : this. ) {
                Class[] exTypes = method.getExceptionTypes();
                for (int i = 0; i < exTypes.lengthi++) {
                    final Class<?> exType = exTypes[i];
                    if ( exceptions.contains(exType) ) continue;
                    boolean add = true;
                    Iterator<Classit = exceptions.iterator();
                    while ( it.hasNext() ) {
                        final Class<?> curType = it.next();
                        if ( curType.isAssignableFrom(exType) ) {
                            add = false;
                            break;
                        }
                        if ( exType.isAssignableFrom(curType) ) {
                            it.remove();
                            add = true;
                        }
                    }
                    if ( add ) exceptions.add(exType);
                }
            }
            return exceptions.toArray(new Classexceptions.size() ]);
        }
        public boolean generateProxyMethod() {
            return ! isFinal() && ! isPrivate();
        }
        public void add(Method method) {
            .add(method);
            //hasPublicDecl |= Modifier.isPublic(method.getModifiers());
        }
        Class getReturnType() {
            return .getReturnType();
        }
        boolean isFinal() {
            if ( .getDeclaringClass().isInterface() ) {
                return false;
            }
            return Modifier.isFinal.getModifiers() );
        }
        boolean isPrivate() {
            if ( .getDeclaringClass().isInterface() ) {
                return false;
            }
            return Modifier.isPrivate.getModifiers() );
        }
        boolean isImplemented() {
            if ( .getDeclaringClass().isInterface() ) {
                return false;
            }
            return ! Modifier.isAbstract.getModifiers() );
        }
    }
    static class MethodKey {
        private final String name;
        private final Class[] arguments;
        MethodKey(final Method method) {
            this. = method.getName();
            this. = method.getParameterTypes();
        }
        @Override
        public boolean equals(Object obj) {
            if ( obj instanceof MethodKey ) {
                MethodKey key = (MethodKeyobj;
                return .equals(key.name) &&
                       Arrays.equals(key.arguments);
            }
            return false;
        }
        @Override
        public int hashCode() {
            return .hashCode();
        }
    }
    private static void addInterfaces(
            final Set<ClassallClasses,
            final Map<MethodKeyMethodDatamethods,
            final Class[] ifaces,
            final Set<Stringnames) {
        for ( int i = 0; i < ifaces.lengthi++ ) {
            addInterface(allClassesmethodsifaces[i], names);
        }
    }
    private static void addInterface(
            final Set<ClassallClasses,
            final Map<MethodKeyMethodDatamethods,
            final Class iface,
            final Set<Stringnames) {
        if ( allClasses.add(iface) ) {
            addMethods(methodsifacenames);
            addInterfaces(allClassesmethodsiface.getInterfaces(), names);
        }
    }
    private static void addMethods(
            final Map<MethodKeyMethodDatamethods,
            final Class classOrIface,
            final Set<Stringnames) {
        final Method[] decMethods = classOrIface.getDeclaredMethods();
        for ( int i = 0; i < decMethods.lengthi++ ) {
            final Method decMethod = decMethods[i];
            if ( names.contains(decMethod.getName()) ) {
                addMethod(methodsdecMethod);
            }
        }
    }
    private static void addMethod(final Map<MethodKeyMethodDatamethodsfinal Method method) {
        final int mod = method.getModifiers();
        if ( Modifier.isStatic(mod) || Modifier.isPrivate(mod) ) {
            return;
        }
        MethodKey methodKey = new MethodKey(method);
        MethodData methodData = methods.get(methodKey);
        if (methodData == null) {
            methodData = new MethodData(method);
            methods.put(methodKeymethodData);
        }
        methodData.add(method);
    }
    private static void addClass(
            final Set<ClassallClasses,
            final Map<MethodKeyMethodDatamethods,
            final Class clazz,
            final Set<Stringnames) {
        if ( allClasses.add(clazz) ) {
            addMethods(methodsclazznames);
            Class superClass = clazz.getSuperclass();
            if ( superClass != null ) {
                addClass(allClassesmethodssuperClassnames);
            }
            addInterfaces(allClassesmethodsclazz.getInterfaces(), names);
        }
    }
    private static void validateArgs(Ruby runtimeString targetClassNameClass superClass) {
        if ( Modifier.isFinal(superClass.getModifiers()) ) {
            throw runtime.newTypeError("cannot extend final class " + superClass.getName());
        }
        if ( ! hasPublicOrProtectedConstructor(superClass) ) {
            throw runtime.newTypeError("class " + superClass.getName() + " doesn't have a public or protected constructor");
        }
        String targetPackage = packageName(targetClassName);
        String packagePath = targetPackage.replace('.''/');
        if (packagePath.startsWith("java")) {
            throw runtime.newTypeError("cannot add classes to package " + packagePath);
        }
        final Package pkg = Package.getPackage(packagePath);
        if ( pkg != null && pkg.isSealed() ) {
            throw runtime.newTypeError("package " + pkg + " is sealed");
        }
    }
    private static boolean hasPublicOrProtectedConstructor(final Class clazz) {
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for ( Constructor constructor : constructors ) {
            final int mod = constructor.getModifiers();
            if ( Modifier.isPublic(mod) || Modifier.isProtected(mod) ) {
                return true;
            }
        }
        return false;
    }
    private static String packageName(String clazzName) {
        int idx = clazzName.lastIndexOf('.');
        if ( idx == -1 ) return "";
        return clazzName.substring(0, idx);
    }
    private static String proxyPackageName(Class clazz) {
        String clazzName = clazz.getName();
        int idx = clazzName.lastIndexOf('.');
        if ( idx == -1 ) return "org.jruby.proxy";
        return "org.jruby.proxy." + clazzName.substring(0, idx);
    }

    
Variable arguments marker for generated constructor.

Note:
could have used @SafeVarargs but it's Java 7+
    public static @interface VarArgs {}
New to GrepCode? Check out our FAQ X