Search in sources :

Example 1 with Identifier

use of sun.tools.java.Identifier 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 Identifier

use of sun.tools.java.Identifier 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)

Example 3 with Identifier

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

the class RemoteClass method computeInterfaceHash.

/**
     * Compute the "interface hash" of the stub/skeleton pair for this
     * remote implementation class.  This is the 64-bit value used to
     * enforce compatibility between a stub and a skeleton using the
     * JDK 1.1 version of the stub/skeleton protocol.
     *
     * It is calculated using the first 64 bits of a SHA digest.  The
     * digest is from a stream consisting of the following data:
     *     (int) stub version number, always 1
     *     for each remote method, in order of operation number:
     *         (UTF) method name
     *         (UTF) method type signature
     *         for each declared exception, in alphabetical name order:
     *             (UTF) name of exception class
     *
     */
private long computeInterfaceHash() {
    long hash = 0;
    ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
    try {
        MessageDigest md = MessageDigest.getInstance("SHA");
        DataOutputStream out = new DataOutputStream(new DigestOutputStream(sink, md));
        out.writeInt(INTERFACE_HASH_STUB_VERSION);
        for (int i = 0; i < remoteMethods.length; i++) {
            MemberDefinition m = remoteMethods[i].getMemberDefinition();
            Identifier name = m.getName();
            Type type = m.getType();
            out.writeUTF(name.toString());
            // type signatures already use mangled class names
            out.writeUTF(type.getTypeSignature());
            ClassDeclaration[] exceptions = m.getExceptions(env);
            sortClassDeclarations(exceptions);
            for (int j = 0; j < exceptions.length; j++) {
                out.writeUTF(Names.mangleClass(exceptions[j].getName()).toString());
            }
        }
        out.flush();
        // use only the first 64 bits of the digest for the hash
        byte[] hashArray = md.digest();
        for (int i = 0; i < Math.min(8, hashArray.length); i++) {
            hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
        }
    } catch (IOException e) {
        throw new Error("unexpected exception computing intetrface hash: " + e);
    } catch (NoSuchAlgorithmException e) {
        throw new Error("unexpected exception computing intetrface hash: " + e);
    }
    return hash;
}
Also used : DataOutputStream(java.io.DataOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Type(sun.tools.java.Type) Identifier(sun.tools.java.Identifier) ClassDeclaration(sun.tools.java.ClassDeclaration) DigestOutputStream(java.security.DigestOutputStream) MessageDigest(java.security.MessageDigest) MemberDefinition(sun.tools.java.MemberDefinition)

Example 4 with Identifier

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

the class RMIGenerator method writeSkeletonDispatchCase.

/**
     * Write the case block for the skeleton's dispatch method for
     * the remote method with the given "opnum".
     */
private void writeSkeletonDispatchCase(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();
    p.pOlnI("case " + opnum + ": // " + methodType.typeString(methodName.toString(), true, false));
    /*
         * Use nested block statement inside case to provide an independent
         * namespace for local variables used to unmarshal parameters for
         * this remote method.
         */
    p.pOlnI("{");
    if (paramTypes.length > 0) {
        /*
             * Declare local variables to hold arguments.
             */
        for (int i = 0; i < paramTypes.length; i++) {
            p.pln(paramTypes[i] + " " + paramNames[i] + ";");
        }
        /*
             * Unmarshal arguments from call stream.
             */
        p.plnI("try {");
        p.pln("java.io.ObjectInput in = call.getInputStream();");
        boolean objectsRead = writeUnmarshalArguments(p, "in", paramTypes, paramNames);
        p.pOlnI("} catch (java.io.IOException e) {");
        p.pln("throw new " + idUnmarshalException + "(\"error unmarshalling arguments\", e);");
        /*
             * If any only if readObject has been invoked, we must catch
             * ClassNotFoundException as well as IOException.
             */
        if (objectsRead) {
            p.pOlnI("} catch (java.lang.ClassNotFoundException e) {");
            p.pln("throw new " + idUnmarshalException + "(\"error unmarshalling arguments\", e);");
        }
        p.pOlnI("} finally {");
        p.pln("call.releaseInputStream();");
        p.pOln("}");
    } else {
        p.pln("call.releaseInputStream();");
    }
    if (!returnType.isType(TC_VOID)) {
        /*
             * Declare variable to hold return type, if not void.
             */
        // REMIND: why $?
        p.p(returnType + " $result = ");
    }
    /*
         * Invoke the method on the server object.
         */
    p.p("server." + methodName + "(");
    for (int i = 0; i < paramNames.length; i++) {
        if (i > 0)
            p.p(", ");
        p.p(paramNames[i]);
    }
    p.pln(");");
    /*
         * Always invoke getResultStream(true) on the call object to send
         * the indication of a successful invocation to the caller.  If
         * the return type is not void, keep the result stream and marshal
         * the return value.
         */
    p.plnI("try {");
    if (!returnType.isType(TC_VOID)) {
        p.p("java.io.ObjectOutput out = ");
    }
    p.pln("call.getResultStream(true);");
    if (!returnType.isType(TC_VOID)) {
        writeMarshalArgument(p, "out", returnType, "$result");
        p.pln(";");
    }
    p.pOlnI("} catch (java.io.IOException e) {");
    p.pln("throw new " + idMarshalException + "(\"error marshalling return\", e);");
    p.pOln("}");
    // break from switch statement
    p.pln("break;");
    // end nested block statement
    p.pOlnI("}");
    p.pln();
}
Also used : Type(sun.tools.java.Type) Identifier(sun.tools.java.Identifier)

Example 5 with Identifier

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

the class RMIGenerator method writeMethodFieldInitializers.

/**
     * Write code to initialize the static fields for each method
     * using the Java Reflection API.
     */
private void writeMethodFieldInitializers(IndentingWriter p) throws IOException {
    for (int i = 0; i < methodFieldNames.length; i++) {
        p.p(methodFieldNames[i] + " = ");
        /*
             * Here we look up the Method object in the arbitrary interface
             * that we find in the RemoteClass.Method object.
             * REMIND: Is this arbitrary choice OK?
             * REMIND: Should this access be part of RemoteClass.Method's
             * abstraction?
             */
        RemoteClass.Method method = remoteMethods[i];
        MemberDefinition def = method.getMemberDefinition();
        Identifier methodName = method.getName();
        Type methodType = method.getType();
        Type[] paramTypes = methodType.getArgumentTypes();
        p.p(def.getClassDefinition().getName() + ".class.getMethod(\"" + methodName + "\", new java.lang.Class[] {");
        for (int j = 0; j < paramTypes.length; j++) {
            if (j > 0)
                p.p(", ");
            p.p(paramTypes[j] + ".class");
        }
        p.pln("});");
    }
}
Also used : Type(sun.tools.java.Type) Identifier(sun.tools.java.Identifier) MemberDefinition(sun.tools.java.MemberDefinition)

Aggregations

Identifier (sun.tools.java.Identifier)5 Type (sun.tools.java.Type)4 ClassDeclaration (sun.tools.java.ClassDeclaration)3 IOException (java.io.IOException)2 ClassDefinition (sun.tools.java.ClassDefinition)2 MemberDefinition (sun.tools.java.MemberDefinition)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 DataOutputStream (java.io.DataOutputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 PrintStream (java.io.PrintStream)1 DigestOutputStream (java.security.DigestOutputStream)1 MessageDigest (java.security.MessageDigest)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 MissingResourceException (java.util.MissingResourceException)1 ClassNotFound (sun.tools.java.ClassNotFound)1