Package org.jruby.util

Examples of org.jruby.util.ClassDefiningClassLoader


            name = getName();
        }
       
        String javaName = "rubyobj." + name.replaceAll("::", ".");
        String javaPath = "rubyobj/" + name.replaceAll("::", "/");
        ClassDefiningClassLoader parentCL;
        Class parentReified = superClass.getRealClass().getReifiedClass();
        if (parentReified == null) {
            throw getClassRuntime().newTypeError("class " + getName() + " parent class is not yet reified");
        }
       
        if (parentReified.getClassLoader() instanceof OneShotClassLoader) {
            parentCL = (OneShotClassLoader)superClass.getRealClass().getReifiedClass().getClassLoader();
        } else {
            if (useChildLoader) {
                parentCL = new OneShotClassLoader(runtime.getJRubyClassLoader());
            } else {
                parentCL = runtime.getJRubyClassLoader();
            }
        }

        if (superClass.reifiedClass != null) {
            reifiedParent = superClass.reifiedClass;
        }

        Class[] interfaces = Java.getInterfacesFromRubyClass(this);
        String[] interfaceNames = new String[interfaces.length + 1];
       
        // mark this as a Reified class
        interfaceNames[0] = p(Reified.class);

        // add the other user-specified interfaces
        for (int i = 0; i < interfaces.length; i++) {
            interfaceNames[i + 1] = p(interfaces[i]);
        }

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, javaPath, null, p(reifiedParent),
                interfaceNames);

        if (classAnnotations != null && classAnnotations.size() != 0) {
            for (Map.Entry<Class,Map<String,Object>> entry : classAnnotations.entrySet()) {
                Class annoType = entry.getKey();
                Map<String,Object> fields = entry.getValue();

                AnnotationVisitor av = cw.visitAnnotation(ci(annoType), true);
                CodegenUtils.visitAnnotationFields(av, fields);
                av.visitEnd();
            }
        }

        // fields to hold Ruby and RubyClass references
        cw.visitField(ACC_STATIC | ACC_PRIVATE, "ruby", ci(Ruby.class), null, null);
        cw.visitField(ACC_STATIC | ACC_PRIVATE, "rubyClass", ci(RubyClass.class), null, null);

        // static initializing method
        SkinnyMethodAdapter m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_STATIC, "clinit", sig(void.class, Ruby.class, RubyClass.class), null, null);
        m.start();
        m.aload(0);
        m.putstatic(javaPath, "ruby", ci(Ruby.class));
        m.aload(1);
        m.putstatic(javaPath, "rubyClass", ci(RubyClass.class));
        m.voidreturn();
        m.end();

        // standard constructor that accepts Ruby, RubyClass
        m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", sig(void.class, Ruby.class, RubyClass.class), null, null);
        m.aload(0);
        m.aload(1);
        m.aload(2);
        m.invokespecial(p(reifiedParent), "<init>", sig(void.class, Ruby.class, RubyClass.class));
        m.voidreturn();
        m.end();

        // no-arg constructor using static references to Ruby and RubyClass
        m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", CodegenUtils.sig(void.class), null, null);
        m.aload(0);
        m.getstatic(javaPath, "ruby", ci(Ruby.class));
        m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
        m.invokespecial(p(reifiedParent), "<init>", sig(void.class, Ruby.class, RubyClass.class));
        m.voidreturn();
        m.end();

        // gather a list of instance methods, so we don't accidentally make static ones that conflict
        Set<String> instanceMethods = new HashSet<String>();

        // define instance methods
        for (Map.Entry<String,DynamicMethod> methodEntry : getMethods().entrySet()) {
            String methodName = methodEntry.getKey();

            if (!JavaNameMangler.willMethodMangleOk(methodName)) continue;

            String javaMethodName = JavaNameMangler.mangleMethodName(methodName);

            Map<Class,Map<String,Object>> methodAnnos = getMethodAnnotations().get(methodName);
            List<Map<Class,Map<String,Object>>> parameterAnnos = getParameterAnnotations().get(methodName);
            Class[] methodSignature = getMethodSignatures().get(methodName);

            String signature;
            if (methodSignature == null) {
                // non-signature signature with just IRubyObject
                switch (methodEntry.getValue().getArity().getValue()) {
                case 0:
                    signature = sig(IRubyObject.class);
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.aload(0);
                    m.ldc(methodName);
                    m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class));
                    break;
                default:
                    signature = sig(IRubyObject.class, IRubyObject[].class);
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.aload(0);
                    m.ldc(methodName);
                    m.aload(1);
                    m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));
                }
                m.areturn();
            } else {
                // generate a real method signature for the method, with to/from coercions

                // indices for temp values
                Class[] params = new Class[methodSignature.length - 1];
                System.arraycopy(methodSignature, 1, params, 0, params.length);
                int baseIndex = 1;
                for (Class paramType : params) {
                    if (paramType == double.class || paramType == long.class) {
                        baseIndex += 2;
                    } else {
                        baseIndex += 1;
                    }
                }
                int rubyIndex = baseIndex;

                signature = sig(methodSignature[0], params);
                m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                m.getstatic(javaPath, "ruby", ci(Ruby.class));
                m.astore(rubyIndex);

                m.aload(0); // self
                m.ldc(methodName); // method name
                RealClassGenerator.coerceArgumentsToRuby(m, params, rubyIndex);
                m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));

                RealClassGenerator.coerceResultAndReturn(m, methodSignature[0]);
            }

            if (DEBUG_REIFY) LOG.debug("defining {}#{} as {}#{}", getName(), methodName, javaName, javaMethodName + signature);

            instanceMethods.add(javaMethodName + signature);

            m.end();
        }

        // define class/static methods
        for (Map.Entry<String,DynamicMethod> methodEntry : getMetaClass().getMethods().entrySet()) {
            String methodName = methodEntry.getKey();

            if (!JavaNameMangler.willMethodMangleOk(methodName)) continue;

            String javaMethodName = JavaNameMangler.mangleMethodName(methodName);

            Map<Class,Map<String,Object>> methodAnnos = getMetaClass().getMethodAnnotations().get(methodName);
            List<Map<Class,Map<String,Object>>> parameterAnnos = getMetaClass().getParameterAnnotations().get(methodName);
            Class[] methodSignature = getMetaClass().getMethodSignatures().get(methodName);

            String signature;
            if (methodSignature == null) {
                // non-signature signature with just IRubyObject
                switch (methodEntry.getValue().getArity().getValue()) {
                case 0:
                    signature = sig(IRubyObject.class);
                    if (instanceMethods.contains(javaMethodName + signature)) continue;
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
                    //m.invokevirtual("org/jruby/RubyClass", "getMetaClass", sig(RubyClass.class) );
                    m.ldc(methodName); // Method name
                    m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class) );
                    break;
                default:
                    signature = sig(IRubyObject.class, IRubyObject[].class);
                    if (instanceMethods.contains(javaMethodName + signature)) continue;
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
                    m.ldc(methodName); // Method name
                    m.aload(0);
                    m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class) );
                }
                m.areturn();
            } else {
                // generate a real method signature for the method, with to/from coercions

                // indices for temp values
                Class[] params = new Class[methodSignature.length - 1];
                System.arraycopy(methodSignature, 1, params, 0, params.length);
                int baseIndex = 0;
                for (Class paramType : params) {
                    if (paramType == double.class || paramType == long.class) {
                        baseIndex += 2;
                    } else {
                        baseIndex += 1;
                    }
                }
                int rubyIndex = baseIndex;

                signature = sig(methodSignature[0], params);
                if (instanceMethods.contains(javaMethodName + signature)) continue;
                m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                m.getstatic(javaPath, "ruby", ci(Ruby.class));
                m.astore(rubyIndex);

                m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
               
                m.ldc(methodName); // method name
                RealClassGenerator.coerceArgumentsToRuby(m, params, rubyIndex);
                m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));

                RealClassGenerator.coerceResultAndReturn(m, methodSignature[0]);
            }

            if (DEBUG_REIFY) LOG.debug("defining {}.{} as {}.{}", getName(), methodName, javaName, javaMethodName + signature);

            m.end();
        }


        cw.visitEnd();
        byte[] classBytes = cw.toByteArray();
        dumpReifiedClass(classDumpDir, javaPath, classBytes);
        Class result = parentCL.defineClass(javaName, classBytes);

        try {
            java.lang.reflect.Method clinit = result.getDeclaredMethod("clinit", Ruby.class, RubyClass.class);
            clinit.invoke(null, runtime, this);
        } catch (Exception e) {
View Full Code Here


            name = getName();
        }
       
        String javaName = "rubyobj." + name.replaceAll("::", ".");
        String javaPath = "rubyobj/" + name.replaceAll("::", "/");
        ClassDefiningClassLoader parentCL;
        Class parentReified = superClass.getRealClass().getReifiedClass();
        if (parentReified == null) {
            throw getClassRuntime().newTypeError("class " + getName() + " parent class is not yet reified");
        }
       
        if (parentReified.getClassLoader() instanceof OneShotClassLoader) {
            parentCL = (OneShotClassLoader)superClass.getRealClass().getReifiedClass().getClassLoader();
        } else {
            if (useChildLoader) {
                parentCL = new OneShotClassLoader(runtime.getJRubyClassLoader());
            } else {
                parentCL = runtime.getJRubyClassLoader();
            }
        }

        if (superClass.reifiedClass != null) {
            reifiedParent = superClass.reifiedClass;
        }

        Class[] interfaces = Java.getInterfacesFromRubyClass(this);
        String[] interfaceNames = new String[interfaces.length + 1];
       
        // mark this as a Reified class
        interfaceNames[0] = p(Reified.class);

        // add the other user-specified interfaces
        for (int i = 0; i < interfaces.length; i++) {
            interfaceNames[i + 1] = p(interfaces[i]);
        }

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, javaPath, null, p(reifiedParent),
                interfaceNames);

        if (classAnnotations != null && !classAnnotations.isEmpty()) {
            for (Map.Entry<Class,Map<String,Object>> entry : classAnnotations.entrySet()) {
                Class annoType = entry.getKey();
                Map<String,Object> fields = entry.getValue();

                AnnotationVisitor av = cw.visitAnnotation(ci(annoType), true);
                CodegenUtils.visitAnnotationFields(av, fields);
                av.visitEnd();
            }
        }

        // fields to hold Ruby and RubyClass references
        cw.visitField(ACC_STATIC | ACC_PRIVATE, "ruby", ci(Ruby.class), null, null);
        cw.visitField(ACC_STATIC | ACC_PRIVATE, "rubyClass", ci(RubyClass.class), null, null);

        // static initializing method
        SkinnyMethodAdapter m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_STATIC, "clinit", sig(void.class, Ruby.class, RubyClass.class), null, null);
        m.start();
        m.aload(0);
        m.putstatic(javaPath, "ruby", ci(Ruby.class));
        m.aload(1);
        m.putstatic(javaPath, "rubyClass", ci(RubyClass.class));
        m.voidreturn();
        m.end();

        // standard constructor that accepts Ruby, RubyClass
        m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", sig(void.class, Ruby.class, RubyClass.class), null, null);
        m.aload(0);
        m.aload(1);
        m.aload(2);
        m.invokespecial(p(reifiedParent), "<init>", sig(void.class, Ruby.class, RubyClass.class));
        m.voidreturn();
        m.end();

        // no-arg constructor using static references to Ruby and RubyClass
        m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", CodegenUtils.sig(void.class), null, null);
        m.aload(0);
        m.getstatic(javaPath, "ruby", ci(Ruby.class));
        m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
        m.invokespecial(p(reifiedParent), "<init>", sig(void.class, Ruby.class, RubyClass.class));
        m.voidreturn();
        m.end();

        // define fields
        for (Map.Entry<String, Class> fieldSignature : getFieldSignatures().entrySet()) {
            String fieldName = fieldSignature.getKey();
            Class type = fieldSignature.getValue();
            Map<Class, Map<String, Object>> fieldAnnos = getFieldAnnotations().get(fieldName);

            FieldVisitor fieldVisitor = cw.visitField(ACC_PUBLIC, fieldName, ci(type), null, null);

            if (fieldAnnos == null) {
              continue;
            }

            for (Map.Entry<Class, Map<String, Object>> fieldAnno : fieldAnnos.entrySet()) {
                Class annoType = fieldAnno.getKey();
                AnnotationVisitor av = fieldVisitor.visitAnnotation(ci(annoType), true);
                CodegenUtils.visitAnnotationFields(av, fieldAnno.getValue());
            }
            fieldVisitor.visitEnd();
        }

        // gather a list of instance methods, so we don't accidentally make static ones that conflict
        Set<String> instanceMethods = new HashSet<String>();

        // define instance methods
        for (Map.Entry<String,DynamicMethod> methodEntry : getMethods().entrySet()) {
            String methodName = methodEntry.getKey();

            if (!JavaNameMangler.willMethodMangleOk(methodName)) continue;

            String javaMethodName = JavaNameMangler.mangleMethodName(methodName);

            Map<Class,Map<String,Object>> methodAnnos = getMethodAnnotations().get(methodName);
            List<Map<Class,Map<String,Object>>> parameterAnnos = getParameterAnnotations().get(methodName);
            Class[] methodSignature = getMethodSignatures().get(methodName);

            String signature;
            if (methodSignature == null) {
                // non-signature signature with just IRubyObject
                switch (methodEntry.getValue().getArity().getValue()) {
                case 0:
                    signature = sig(IRubyObject.class);
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.aload(0);
                    m.ldc(methodName);
                    m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class));
                    break;
                default:
                    signature = sig(IRubyObject.class, IRubyObject[].class);
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.aload(0);
                    m.ldc(methodName);
                    m.aload(1);
                    m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));
                }
                m.areturn();
            } else {
                // generate a real method signature for the method, with to/from coercions

                // indices for temp values
                Class[] params = new Class[methodSignature.length - 1];
                System.arraycopy(methodSignature, 1, params, 0, params.length);
                int baseIndex = 1;
                for (Class paramType : params) {
                    if (paramType == double.class || paramType == long.class) {
                        baseIndex += 2;
                    } else {
                        baseIndex += 1;
                    }
                }
                int rubyIndex = baseIndex;

                signature = sig(methodSignature[0], params);
                m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
                generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                m.getstatic(javaPath, "ruby", ci(Ruby.class));
                m.astore(rubyIndex);

                m.aload(0); // self
                m.ldc(methodName); // method name
                RealClassGenerator.coerceArgumentsToRuby(m, params, rubyIndex);
                m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));

                RealClassGenerator.coerceResultAndReturn(m, methodSignature[0]);
            }

            if (DEBUG_REIFY) LOG.debug("defining {}#{} as {}#{}", getName(), methodName, javaName, javaMethodName + signature);

            instanceMethods.add(javaMethodName + signature);

            m.end();
        }

        // define class/static methods
        for (Map.Entry<String,DynamicMethod> methodEntry : getMetaClass().getMethods().entrySet()) {
            String methodName = methodEntry.getKey();

            if (!JavaNameMangler.willMethodMangleOk(methodName)) continue;

            String javaMethodName = JavaNameMangler.mangleMethodName(methodName);

            Map<Class,Map<String,Object>> methodAnnos = getMetaClass().getMethodAnnotations().get(methodName);
            List<Map<Class,Map<String,Object>>> parameterAnnos = getMetaClass().getParameterAnnotations().get(methodName);
            Class[] methodSignature = getMetaClass().getMethodSignatures().get(methodName);

            String signature;
            if (methodSignature == null) {
                // non-signature signature with just IRubyObject
                switch (methodEntry.getValue().getArity().getValue()) {
                case 0:
                    signature = sig(IRubyObject.class);
                    if (instanceMethods.contains(javaMethodName + signature)) continue;
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
                    //m.invokevirtual("org/jruby/RubyClass", "getMetaClass", sig(RubyClass.class) );
                    m.ldc(methodName); // Method name
                    m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class) );
                    break;
                default:
                    signature = sig(IRubyObject.class, IRubyObject[].class);
                    if (instanceMethods.contains(javaMethodName + signature)) continue;
                    m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                    generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                    m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
                    m.ldc(methodName); // Method name
                    m.aload(0);
                    m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class) );
                }
                m.areturn();
            } else {
                // generate a real method signature for the method, with to/from coercions

                // indices for temp values
                Class[] params = new Class[methodSignature.length - 1];
                System.arraycopy(methodSignature, 1, params, 0, params.length);
                int baseIndex = 0;
                for (Class paramType : params) {
                    if (paramType == double.class || paramType == long.class) {
                        baseIndex += 2;
                    } else {
                        baseIndex += 1;
                    }
                }
                int rubyIndex = baseIndex;

                signature = sig(methodSignature[0], params);
                if (instanceMethods.contains(javaMethodName + signature)) continue;
                m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS | ACC_STATIC, javaMethodName, signature, null, null);
                generateMethodAnnotations(methodAnnos, m, parameterAnnos);

                m.getstatic(javaPath, "ruby", ci(Ruby.class));
                m.astore(rubyIndex);

                m.getstatic(javaPath, "rubyClass", ci(RubyClass.class));
               
                m.ldc(methodName); // method name
                RealClassGenerator.coerceArgumentsToRuby(m, params, rubyIndex);
                m.invokevirtual("org/jruby/RubyClass", "callMethod", sig(IRubyObject.class, String.class, IRubyObject[].class));

                RealClassGenerator.coerceResultAndReturn(m, methodSignature[0]);
            }

            if (DEBUG_REIFY) LOG.debug("defining {}.{} as {}.{}", getName(), methodName, javaName, javaMethodName + signature);

            m.end();
        }


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



        // Attempt to load the name we plan to use; skip reification if it exists already (see #1229).
        Throwable failure = null;
        try {
            Class result = parentCL.defineClass(javaName, classBytes);
            dumpReifiedClass(classDumpDir, javaPath, classBytes);

            java.lang.reflect.Method clinit = result.getDeclaredMethod("clinit", Ruby.class, RubyClass.class);
            clinit.invoke(null, runtime, this);
View Full Code Here

TOP

Related Classes of org.jruby.util.ClassDefiningClassLoader

Copyright © 2018 www.massapicom. 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.