Search in sources :

Example 1 with ClassDefinition

use of sun.tools.java.ClassDefinition in project jdk8u_jdk by JetBrains.

the class RMIGenerator method writeStubMethod.

/**
     * Write the stub method for the remote method with the given "opnum".
     */
private void writeStubMethod(IndentingWriter p, int opnum) throws IOException {
    RemoteClass.Method method = remoteMethods[opnum];
    Identifier methodName = method.getName();
    Type methodType = method.getType();
    Type[] paramTypes = methodType.getArgumentTypes();
    String[] paramNames = nameParameters(paramTypes);
    Type returnType = methodType.getReturnType();
    ClassDeclaration[] exceptions = method.getExceptions();
    /*
         * Declare stub method; throw exceptions declared in remote
         * interface(s).
         */
    p.pln("// implementation of " + methodType.typeString(methodName.toString(), true, false));
    p.p("public " + returnType + " " + methodName + "(");
    for (int i = 0; i < paramTypes.length; i++) {
        if (i > 0)
            p.p(", ");
        p.p(paramTypes[i] + " " + paramNames[i]);
    }
    p.plnI(")");
    if (exceptions.length > 0) {
        p.p("throws ");
        for (int i = 0; i < exceptions.length; i++) {
            if (i > 0)
                p.p(", ");
            p.p(exceptions[i].getName().toString());
        }
        p.pln();
    }
    p.pOlnI("{");
    /*
         * The RemoteRef.invoke methods throw Exception, but unless this
         * stub method throws Exception as well, we must catch Exceptions
         * thrown from the invocation.  So we must catch Exception and
         * rethrow something we can throw: UnexpectedException, which is a
         * subclass of RemoteException.  But for any subclasses of Exception
         * that we can throw, like RemoteException, RuntimeException, and
         * any of the exceptions declared by this stub method, we want them
         * to pass through unharmed, so first we must catch any such
         * exceptions and rethrow it directly.
         *
         * We have to be careful generating the rethrowing catch blocks
         * here, because javac will flag an error if there are any
         * unreachable catch blocks, i.e. if the catch of an exception class
         * follows a previous catch of it or of one of its superclasses.
         * The following method invocation takes care of these details.
         */
    Vector<ClassDefinition> catchList = computeUniqueCatchList(exceptions);
    /*
         * If we need to catch any particular exceptions (i.e. this method
         * does not declare java.lang.Exception), put the entire stub
         * method in a try block.
         */
    if (catchList.size() > 0) {
        p.plnI("try {");
    }
    if (version == STUB_VERSION_FAT) {
        p.plnI("if (useNewInvoke) {");
    }
    if (version == STUB_VERSION_FAT || version == STUB_VERSION_1_2) {
        if (!returnType.isType(TC_VOID)) {
            // REMIND: why $?
            p.p("Object $result = ");
        }
        p.p("ref.invoke(this, " + methodFieldNames[opnum] + ", ");
        if (paramTypes.length > 0) {
            p.p("new java.lang.Object[] {");
            for (int i = 0; i < paramTypes.length; i++) {
                if (i > 0)
                    p.p(", ");
                p.p(wrapArgumentCode(paramTypes[i], paramNames[i]));
            }
            p.p("}");
        } else {
            p.p("null");
        }
        p.pln(", " + method.getMethodHash() + "L);");
        if (!returnType.isType(TC_VOID)) {
            p.pln("return " + unwrapArgumentCode(returnType, "$result") + ";");
        }
    }
    if (version == STUB_VERSION_FAT) {
        p.pOlnI("} else {");
    }
    if (version == STUB_VERSION_1_1 || version == STUB_VERSION_FAT) {
        p.pln(idRemoteCall + " call = ref.newCall((" + idRemoteObject + ") this, operations, " + opnum + ", interfaceHash);");
        if (paramTypes.length > 0) {
            p.plnI("try {");
            p.pln("java.io.ObjectOutput out = call.getOutputStream();");
            writeMarshalArguments(p, "out", paramTypes, paramNames);
            p.pOlnI("} catch (java.io.IOException e) {");
            p.pln("throw new " + idMarshalException + "(\"error marshalling arguments\", e);");
            p.pOln("}");
        }
        p.pln("ref.invoke(call);");
        if (returnType.isType(TC_VOID)) {
            p.pln("ref.done(call);");
        } else {
            // REMIND: why $?
            p.pln(returnType + " $result;");
            p.plnI("try {");
            p.pln("java.io.ObjectInput in = call.getInputStream();");
            boolean objectRead = writeUnmarshalArgument(p, "in", returnType, "$result");
            p.pln(";");
            p.pOlnI("} catch (java.io.IOException e) {");
            p.pln("throw new " + idUnmarshalException + "(\"error unmarshalling return\", e);");
            /*
                 * If any only if readObject has been invoked, we must catch
                 * ClassNotFoundException as well as IOException.
                 */
            if (objectRead) {
                p.pOlnI("} catch (java.lang.ClassNotFoundException e) {");
                p.pln("throw new " + idUnmarshalException + "(\"error unmarshalling return\", e);");
            }
            p.pOlnI("} finally {");
            p.pln("ref.done(call);");
            p.pOln("}");
            p.pln("return $result;");
        }
    }
    if (version == STUB_VERSION_FAT) {
        // end if/else (useNewInvoke) block
        p.pOln("}");
    }
    /*
         * If we need to catch any particular exceptions, finally write
         * the catch blocks for them, rethrow any other Exceptions with an
         * UnexpectedException, and end the try block.
         */
    if (catchList.size() > 0) {
        for (Enumeration<ClassDefinition> enumeration = catchList.elements(); enumeration.hasMoreElements(); ) {
            ClassDefinition def = enumeration.nextElement();
            p.pOlnI("} catch (" + def.getName() + " e) {");
            p.pln("throw e;");
        }
        p.pOlnI("} catch (java.lang.Exception e) {");
        p.pln("throw new " + idUnexpectedException + "(\"undeclared checked exception\", e);");
        // end try/catch block
        p.pOln("}");
    }
    // end stub method
    p.pOln("}");
}
Also used : ClassDefinition(sun.tools.java.ClassDefinition) Type(sun.tools.java.Type) Identifier(sun.tools.java.Identifier) ClassDeclaration(sun.tools.java.ClassDeclaration)

Example 2 with ClassDefinition

use of sun.tools.java.ClassDefinition in project jdk8u_jdk by JetBrains.

the class RemoteClass method initialize.

/**
     * Validate that the remote implementation class is properly formed
     * and fill in the data structures required by the public interface.
     */
private boolean initialize() {
    /*
         * Verify that the "impl" is really a class, not an interface.
         */
    if (implClassDef.isInterface()) {
        env.error(0, "rmic.cant.make.stubs.for.interface", implClassDef.getName());
        return false;
    }
    /*
         * Initialize cached definitions for the Remote interface and
         * the RemoteException class.
         */
    try {
        defRemote = env.getClassDeclaration(idRemote).getClassDefinition(env);
        defException = env.getClassDeclaration(idJavaLangException).getClassDefinition(env);
        defRemoteException = env.getClassDeclaration(idRemoteException).getClassDefinition(env);
    } catch (ClassNotFound e) {
        env.error(0, "rmic.class.not.found", e.name);
        return false;
    }
    /*
         * Here we find all of the remote interfaces of our remote
         * implementation class.  For each class up the superclass
         * chain, add each directly-implemented interface that
         * somehow extends Remote to a list.
         */
    // list of remote interfaces found
    Vector<ClassDefinition> remotesImplemented = new Vector<ClassDefinition>();
    for (ClassDefinition classDef = implClassDef; classDef != null; ) {
        try {
            ClassDeclaration[] interfaces = classDef.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                ClassDefinition interfaceDef = interfaces[i].getClassDefinition(env);
                /*
                         * Add interface to the list if it extends Remote and
                         * it is not already there.
                         */
                if (!remotesImplemented.contains(interfaceDef) && defRemote.implementedBy(env, interfaces[i])) {
                    remotesImplemented.addElement(interfaceDef);
                    /***** <DEBUG> */
                    if (env.verbose()) {
                        System.out.println("[found remote interface: " + interfaceDef.getName() + "]");
                    /***** </DEBUG> */
                    }
                }
            }
            /*
                     * Verify that the candidate remote implementation class
                     * implements at least one remote interface directly.
                     */
            if (classDef == implClassDef && remotesImplemented.isEmpty()) {
                if (defRemote.implementedBy(env, implClassDef.getClassDeclaration())) {
                    /*
                                 * This error message is used if the class does
                                 * implement a remote interface through one of
                                 * its superclasses, but not directly.
                                 */
                    env.error(0, "rmic.must.implement.remote.directly", implClassDef.getName());
                } else {
                    /*
                                 * This error message is used if the class never
                                 * implements a remote interface.
                                 */
                    env.error(0, "rmic.must.implement.remote", implClassDef.getName());
                }
                return false;
            }
            /*
                     * Get definition for next superclass.
                     */
            classDef = (classDef.getSuperClass() != null ? classDef.getSuperClass().getClassDefinition(env) : null);
        } catch (ClassNotFound e) {
            env.error(0, "class.not.found", e.name, classDef.getName());
            return false;
        }
    }
    /*
         * The "remotesImplemented" vector now contains all of the remote
         * interfaces directly implemented by the remote class or by any
         * of its superclasses.
         *
         * At this point, we could optimize the list by removing superfluous
         * entries, i.e. any interfaces that are implemented by some other
         * interface in the list anyway.
         *
         * This should be correct; would it be worthwhile?
         *
         *      for (int i = 0; i < remotesImplemented.size();) {
         *          ClassDefinition interfaceDef =
         *              (ClassDefinition) remotesImplemented.elementAt(i);
         *          boolean isOtherwiseImplemented = false;
         *          for (int j = 0; j < remotesImplemented.size; j++) {
         *              if (j != i &&
         *                  interfaceDef.implementedBy(env, (ClassDefinition)
         *                  remotesImplemented.elementAt(j).
         *                      getClassDeclaration()))
         *              {
         *                  isOtherwiseImplemented = true;
         *                  break;
         *              }
         *          }
         *          if (isOtherwiseImplemented) {
         *              remotesImplemented.removeElementAt(i);
         *          } else {
         *              ++i;
         *          }
         *      }
         */
    /*
         * Now we collect the methods from all of the remote interfaces
         * into a hashtable.
         */
    Hashtable<String, Method> methods = new Hashtable<String, Method>();
    boolean errors = false;
    for (Enumeration<ClassDefinition> enumeration = remotesImplemented.elements(); enumeration.hasMoreElements(); ) {
        ClassDefinition interfaceDef = enumeration.nextElement();
        if (!collectRemoteMethods(interfaceDef, methods))
            errors = true;
    }
    if (errors)
        return false;
    /*
         * Convert vector of remote interfaces to an array
         * (order is not important for this array).
         */
    remoteInterfaces = new ClassDefinition[remotesImplemented.size()];
    remotesImplemented.copyInto(remoteInterfaces);
    /*
         * Sort table of remote methods into an array.  The elements are
         * sorted in ascending order of the string of the method's name
         * and type signature, so that each elements index is equal to
         * its operation number of the JDK 1.1 version of the stub/skeleton
         * protocol.
         */
    String[] orderedKeys = new String[methods.size()];
    int count = 0;
    for (Enumeration<Method> enumeration = methods.elements(); enumeration.hasMoreElements(); ) {
        Method m = enumeration.nextElement();
        String key = m.getNameAndDescriptor();
        int i;
        for (i = count; i > 0; --i) {
            if (key.compareTo(orderedKeys[i - 1]) >= 0) {
                break;
            }
            orderedKeys[i] = orderedKeys[i - 1];
        }
        orderedKeys[i] = key;
        ++count;
    }
    remoteMethods = new Method[methods.size()];
    for (int i = 0; i < remoteMethods.length; i++) {
        remoteMethods[i] = methods.get(orderedKeys[i]);
        /***** <DEBUG> */
        if (env.verbose()) {
            System.out.print("[found remote method <" + i + ">: " + remoteMethods[i].getOperationString());
            ClassDeclaration[] exceptions = remoteMethods[i].getExceptions();
            if (exceptions.length > 0)
                System.out.print(" throws ");
            for (int j = 0; j < exceptions.length; j++) {
                if (j > 0)
                    System.out.print(", ");
                System.out.print(exceptions[j].getName());
            }
            System.out.println("]");
        }
    /***** </DEBUG> */
    }
    /**
         * Finally, pre-compute the interface hash to be used by
         * stubs/skeletons for this remote class.
         */
    interfaceHash = computeInterfaceHash();
    return true;
}
Also used : Hashtable(java.util.Hashtable) ClassDefinition(sun.tools.java.ClassDefinition) ClassDeclaration(sun.tools.java.ClassDeclaration) ClassNotFound(sun.tools.java.ClassNotFound) Vector(java.util.Vector)

Example 3 with ClassDefinition

use of sun.tools.java.ClassDefinition in project jdk8u_jdk by JetBrains.

the class Main method doCompile.

/**
     * Do the compile with the switches and files already supplied
     */
public boolean doCompile() {
    // Create batch environment
    BatchEnvironment env = getEnv();
    env.flags |= flags;
    // Set the classfile version numbers
    // Compat and 1.1 stubs must retain the old version number.
    env.majorVersion = 45;
    env.minorVersion = 3;
    // Preload the "out of memory" error string just in case we run
    // out of memory during the compile.
    String noMemoryErrorString = getText("rmic.no.memory");
    String stackOverflowErrorString = getText("rmic.stack.overflow");
    try {
        /** Load the classes on the command line
             * Replace the entries in classes with the ClassDefinition for the class
             */
        for (int i = classes.size() - 1; i >= 0; i--) {
            Identifier implClassName = Identifier.lookup(classes.elementAt(i));
            /*
                 * Fix bugid 4049354: support using '.' as an inner class
                 * qualifier on the command line (previously, only mangled
                 * inner class names were understood, like "pkg.Outer$Inner").
                 *
                 * The following method, also used by "javap", resolves the
                 * given unmangled inner class name to the appropriate
                 * internal identifier.  For example, it translates
                 * "pkg.Outer.Inner" to "pkg.Outer. Inner".
                 */
            implClassName = env.resolvePackageQualifiedName(implClassName);
            /*
                 * But if we use such an internal inner class name identifier
                 * to load the class definition, the Java compiler will notice
                 * if the impl class is a "private" inner class and then deny
                 * skeletons (needed unless "-v1.2" is used) the ability to
                 * cast to it.  To work around this problem, we mangle inner
                 * class name identifiers to their binary "outer" class name:
                 * "pkg.Outer. Inner" becomes "pkg.Outer$Inner".
                 */
            implClassName = Names.mangleClass(implClassName);
            ClassDeclaration decl = env.getClassDeclaration(implClassName);
            try {
                ClassDefinition def = decl.getClassDefinition(env);
                for (int j = 0; j < generators.size(); j++) {
                    Generator gen = generators.elementAt(j);
                    gen.generate(env, def, destDir);
                }
            } catch (ClassNotFound ex) {
                env.error(0, "rmic.class.not.found", implClassName);
            }
        }
        // compile all classes that need compilation
        if (!nocompile) {
            compileAllClasses(env);
        }
    } catch (OutOfMemoryError ee) {
        // The compiler has run out of memory.  Use the error string
        // which we preloaded.
        env.output(noMemoryErrorString);
        return false;
    } catch (StackOverflowError ee) {
        env.output(stackOverflowErrorString);
        return false;
    } catch (Error ee) {
        // compiler more robust in the face of bad error recovery.
        if (env.nerrors == 0 || env.dump()) {
            env.error(0, "fatal.error");
            ee.printStackTrace(out instanceof PrintStream ? (PrintStream) out : new PrintStream(out, true));
        }
    } catch (Exception ee) {
        if (env.nerrors == 0 || env.dump()) {
            env.error(0, "fatal.exception");
            ee.printStackTrace(out instanceof PrintStream ? (PrintStream) out : new PrintStream(out, true));
        }
    }
    env.flushErrors();
    boolean status = true;
    if (env.nerrors > 0) {
        String msg = "";
        if (env.nerrors > 1) {
            msg = getText("rmic.errors", env.nerrors);
        } else {
            msg = getText("rmic.1error");
        }
        if (env.nwarnings > 0) {
            if (env.nwarnings > 1) {
                msg += ", " + getText("rmic.warnings", env.nwarnings);
            } else {
                msg += ", " + getText("rmic.1warning");
            }
        }
        output(msg);
        status = false;
    } else {
        if (env.nwarnings > 0) {
            if (env.nwarnings > 1) {
                output(getText("rmic.warnings", env.nwarnings));
            } else {
                output(getText("rmic.1warning"));
            }
        }
    }
    // last step is to delete generated source files
    if (!keepGenerated) {
        env.deleteGeneratedFiles();
    }
    // We're done
    if (env.verbose()) {
        tm = System.currentTimeMillis() - tm;
        output(getText("rmic.done_in", Long.toString(tm)));
    }
    // Shutdown the environment object and release our resources.
    // Note that while this is unneccessary when rmic is invoked
    // the command line, there are environments in which rmic
    // from is invoked within a server process, so resource
    // reclamation is important...
    env.shutdown();
    sourcePathArg = null;
    sysClassPathArg = null;
    extDirsArg = null;
    classPathString = null;
    destDir = null;
    classes = null;
    generatorArgs = null;
    generators = null;
    environmentClass = null;
    program = null;
    out = null;
    return status;
}
Also used : PrintStream(java.io.PrintStream) ClassDefinition(sun.tools.java.ClassDefinition) MissingResourceException(java.util.MissingResourceException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) Identifier(sun.tools.java.Identifier) ClassDeclaration(sun.tools.java.ClassDeclaration) ClassNotFound(sun.tools.java.ClassNotFound)

Aggregations

ClassDeclaration (sun.tools.java.ClassDeclaration)3 ClassDefinition (sun.tools.java.ClassDefinition)3 ClassNotFound (sun.tools.java.ClassNotFound)2 Identifier (sun.tools.java.Identifier)2 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 PrintStream (java.io.PrintStream)1 Hashtable (java.util.Hashtable)1 MissingResourceException (java.util.MissingResourceException)1 Vector (java.util.Vector)1 Type (sun.tools.java.Type)1