Search in sources :

Example 1 with ClassDeclaration

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

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

use of sun.tools.java.ClassDeclaration 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 4 with ClassDeclaration

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

the class RemoteClass method sortClassDeclarations.

/**
     * Sort array of class declarations alphabetically by their mangled
     * fully-qualified class name.  This is used to feed a method's exceptions
     * in a canonical order into the digest stream for the interface hash
     * computation.
     */
private void sortClassDeclarations(ClassDeclaration[] decl) {
    for (int i = 1; i < decl.length; i++) {
        ClassDeclaration curr = decl[i];
        String name = Names.mangleClass(curr.getName()).toString();
        int j;
        for (j = i; j > 0; j--) {
            if (name.compareTo(Names.mangleClass(decl[j - 1].getName()).toString()) >= 0) {
                break;
            }
            decl[j] = decl[j - 1];
        }
        decl[j] = curr;
    }
}
Also used : ClassDeclaration(sun.tools.java.ClassDeclaration)

Example 5 with ClassDeclaration

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

Aggregations

ClassDeclaration (sun.tools.java.ClassDeclaration)7 ClassDefinition (sun.tools.java.ClassDefinition)3 Identifier (sun.tools.java.Identifier)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 IOException (java.io.IOException)2 ClassNotFound (sun.tools.java.ClassNotFound)2 Type (sun.tools.java.Type)2 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 Hashtable (java.util.Hashtable)1 MissingResourceException (java.util.MissingResourceException)1 Vector (java.util.Vector)1 BatchEnvironment (sun.rmi.rmic.BatchEnvironment)1 MemberDefinition (sun.tools.java.MemberDefinition)1