jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java
author xdono
Wed, 02 Jul 2008 12:55:45 -0700
changeset 715 f16baef3a20e
parent 51 6fe31bc95bbc
child 5506 202f599c92aa
permissions -rw-r--r--
6719955: Update copyright year Summary: Update copyright year for files that have been modified in 2008 Reviewed-by: ohair, tbell
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
715
f16baef3a20e 6719955: Update copyright year
xdono
parents: 51
diff changeset
     2
 * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.rmi.rmic.newrmic.jrmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import com.sun.javadoc.ClassDoc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import com.sun.javadoc.MethodDoc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import com.sun.javadoc.Parameter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import com.sun.javadoc.Type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.io.ByteArrayOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.io.DataOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.security.MessageDigest;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.security.DigestOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.security.NoSuchAlgorithmException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.util.Arrays;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.util.Comparator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.util.HashMap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.Map;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import sun.rmi.rmic.newrmic.BatchEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import static sun.rmi.rmic.newrmic.Constants.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import static sun.rmi.rmic.newrmic.jrmp.Constants.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * Encapsulates RMI-specific information about a remote implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * class (a class that implements one or more remote interfaces).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * WARNING: The contents of this source file are not part of any
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * supported API.  Code that depends on them does so at its own risk:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * they are subject to change or removal without notice.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * @author Peter Jones
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
final class RemoteClass {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    /** rmic environment for this object */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    private final BatchEnvironment env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    /** the remote implementation class this object represents */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    private final ClassDoc implClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    /** remote interfaces implemented by this class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    private ClassDoc[] remoteInterfaces;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    /** the remote methods of this class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    private Method[] remoteMethods;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    /** stub/skeleton "interface hash" for this class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    private long interfaceHash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
     * Creates a RemoteClass instance that represents the RMI-specific
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     * information about the specified remote implementation class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     * If the class is not a valid remote implementation class or if
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     * some other error occurs, the return value will be null, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
     * errors will have been reported to the supplied
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
     * BatchEnvironment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    static RemoteClass forClass(BatchEnvironment env, ClassDoc implClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        RemoteClass remoteClass = new RemoteClass(env, implClass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        if (remoteClass.init()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
            return remoteClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
     * Creates a RemoteClass instance for the specified class.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
     * resulting object is not yet initialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    private RemoteClass(BatchEnvironment env, ClassDoc implClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        this.env = env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        this.implClass = implClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * Returns the ClassDoc for this remote implementation class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    ClassDoc classDoc() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        return implClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * Returns the remote interfaces implemented by this remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * implementation class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * A remote interface is an interface that is a subinterface of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     * java.rmi.Remote.  The remote interfaces of a class are the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * direct superinterfaces of the class and all of its superclasses
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * that are remote interfaces.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     * The order of the array returned is arbitrary, and some elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
     * may be superfluous (i.e., superinterfaces of other interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * in the array).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    ClassDoc[] remoteInterfaces() {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   124
        return remoteInterfaces.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     * Returns an array of RemoteClass.Method objects representing all
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     * of the remote methods of this remote implementation class (all
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * of the member methods of the class's remote interfaces).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     * The methods in the array are ordered according to a comparison
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * of strings consisting of their name followed by their
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     * descriptor, so each method's index in the array corresponds to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * its "operation number" in the JDK 1.1 version of the JRMP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * stub/skeleton protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    Method[] remoteMethods() {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   139
        return remoteMethods.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     * Returns the "interface hash" used to match a stub/skeleton pair
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     * for this remote implementation class in the JDK 1.1 version of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * the JRMP stub/skeleton protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    long interfaceHash() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        return interfaceHash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
     * Validates this remote implementation class and computes the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     * RMI-specific information.  Returns true if successful, or false
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * if an error occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    private boolean init() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
         * Verify that it is really a class, not an interface.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        if (implClass.isInterface()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            env.error("rmic.cant.make.stubs.for.interface",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                      implClass.qualifiedName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
         * Find all of the remote interfaces of our remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
         * implementation class-- for each class up the superclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
         * chain, add each directly-implemented interface that somehow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
         * extends Remote to a list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        List<ClassDoc> remotesImplemented = new ArrayList<ClassDoc>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        for (ClassDoc cl = implClass; cl != null; cl = cl.superclass()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            for (ClassDoc intf : cl.interfaces()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                 * Add interface to the list if it extends Remote and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                 * it is not already there.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                if (!remotesImplemented.contains(intf) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                    intf.subclassOf(env.docRemote()))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                    remotesImplemented.add(intf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                    if (env.verbose()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                        env.output("[found remote interface: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                                   intf.qualifiedName() + "]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
             * Verify that the candidate remote implementation class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
             * implements at least one remote interface directly.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            if (cl == implClass && remotesImplemented.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                if (implClass.subclassOf(env.docRemote())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                     * This error message is used if the class does
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                     * implement a remote interface through one of its
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                     * superclasses, but not directly.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                    env.error("rmic.must.implement.remote.directly",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                              implClass.qualifiedName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                     * This error message is used if the class does
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                     * not implement a remote interface at all.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                    env.error("rmic.must.implement.remote",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                              implClass.qualifiedName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
         * Convert list of remote interfaces to an array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
         * (order is not important for this array).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        remoteInterfaces =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            remotesImplemented.toArray(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                new ClassDoc[remotesImplemented.size()]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
         * Collect the methods from all of the remote interfaces into
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
         * a table, which maps from method name-and-descriptor string
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
         * to Method object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        Map<String,Method> methods = new HashMap<String,Method>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        boolean errors = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        for (ClassDoc intf : remotesImplemented) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            if (!collectRemoteMethods(intf, methods)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                 * Continue iterating despite errors in order to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                 * generate more complete error report.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                errors = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        if (errors) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
         * Sort table of remote methods into an array.  The elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
         * are sorted in ascending order of the string of the method's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
         * name and descriptor, so that each elements index is equal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
         * to its operation number in the JDK 1.1 version of the JRMP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
         * stub/skeleton protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        String[] orderedKeys =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            methods.keySet().toArray(new String[methods.size()]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        Arrays.sort(orderedKeys);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        remoteMethods = new Method[methods.size()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        for (int i = 0; i < remoteMethods.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            remoteMethods[i] = methods.get(orderedKeys[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            if (env.verbose()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                String msg = "[found remote method <" + i + ">: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                    remoteMethods[i].operationString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                ClassDoc[] exceptions = remoteMethods[i].exceptionTypes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                if (exceptions.length > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                    msg += " throws ";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                    for (int j = 0; j < exceptions.length; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                        if (j > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                            msg += ", ";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                        msg +=  exceptions[j].qualifiedName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                msg += "\n\tname and descriptor = \"" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                    remoteMethods[i].nameAndDescriptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                msg += "\n\tmethod hash = " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                    remoteMethods[i].methodHash() + "]";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                env.output(msg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
         * Finally, pre-compute the interface hash to be used by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
         * stubs/skeletons for this remote class in the JDK 1.1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
         * version of the JRMP stub/skeleton protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        interfaceHash = computeInterfaceHash();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * Collects and validates all methods from the specified interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     * and all of its superinterfaces as remote methods.  Remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * methods are added to the supplied table.  Returns true if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     * successful, or false if an error occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    private boolean collectRemoteMethods(ClassDoc intf,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                                         Map<String,Method> table)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if (!intf.isInterface()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            throw new AssertionError(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
                intf.qualifiedName() + " not an interface");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        boolean errors = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
         * Search interface's declared methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    nextMethod:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        for (MethodDoc method : intf.methods()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
             * Verify that each method throws RemoteException (or a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
             * superclass of RemoteException).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            boolean hasRemoteException = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            for (ClassDoc ex : method.thrownExceptions()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                if (env.docRemoteException().subclassOf(ex)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                    hasRemoteException = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
             * If this method did not throw RemoteException as required,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
             * generate the error but continue, so that multiple such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
             * errors can be reported.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
            if (!hasRemoteException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                env.error("rmic.must.throw.remoteexception",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                          intf.qualifiedName(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                          method.name() + method.signature());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                errors = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                continue nextMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
             * Verify that the implementation of this method throws only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
             * java.lang.Exception or its subclasses (fix bugid 4092486).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
             * JRMP does not support remote methods throwing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
             * java.lang.Throwable or other subclasses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            MethodDoc implMethod = findImplMethod(method);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            if (implMethod != null) {           // should not be null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                for (ClassDoc ex : implMethod.thrownExceptions()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                    if (!ex.subclassOf(env.docException())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                        env.error("rmic.must.only.throw.exception",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                                  implMethod.name() + implMethod.signature(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                                  ex.qualifiedName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                        errors = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                        continue nextMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
             * Create RemoteClass.Method object to represent this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
             * found in a remote interface.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            Method newMethod = new Method(method);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
             * Store remote method's representation in the table of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
             * remote methods found, keyed by its name and descriptor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
             * If the table already contains an entry with the same
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
             * method name and descriptor, then we must replace the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
             * old entry with a Method object that represents a legal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
             * combination of the old and the new methods;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
             * specifically, the combined method must have a throws
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
             * clause that contains (only) all of the checked
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
             * exceptions that can be thrown by both the old and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
             * new method (see bugid 4070653).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            String key = newMethod.nameAndDescriptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            Method oldMethod = table.get(key);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            if (oldMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                newMethod = newMethod.mergeWith(oldMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            table.put(key, newMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
         * Recursively collect methods for all superinterfaces.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        for (ClassDoc superintf : intf.interfaces()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            if (!collectRemoteMethods(superintf, table)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                errors = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        return !errors;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
     * Returns the MethodDoc for the method of this remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
     * implementation class that implements the specified remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
     * method of a remote interface.  Returns null if no matching
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     * method was found in this remote implementation class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
    private MethodDoc findImplMethod(MethodDoc interfaceMethod) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        String name = interfaceMethod.name();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        String desc = Util.methodDescriptorOf(interfaceMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        for (MethodDoc implMethod : implClass.methods()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            if (name.equals(implMethod.name()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                desc.equals(Util.methodDescriptorOf(implMethod)))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                return implMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     * Computes the "interface hash" of the stub/skeleton pair for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
     * this remote implementation class.  This is the 64-bit value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
     * used to enforce compatibility between a stub class and a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
     * skeleton class in the JDK 1.1 version of the JRMP stub/skeleton
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
     * protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
     * It is calculated using the first 64 bits of an SHA digest.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
     * digest is of a stream consisting of the following data:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
     *     (int) stub version number, always 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
     *     for each remote method, in order of operation number:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
     *         (UTF-8) method name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
     *         (UTF-8) method descriptor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
     *         for each declared exception, in alphabetical name order:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
     *             (UTF-8) name of exception class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     * (where "UTF-8" includes a 16-bit length prefix as written by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     * java.io.DataOutput.writeUTF).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
    private long computeInterfaceHash() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
        long hash = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
            MessageDigest md = MessageDigest.getInstance("SHA");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            DataOutputStream out = new DataOutputStream(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
                new DigestOutputStream(sink, md));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
            out.writeInt(INTERFACE_HASH_STUB_VERSION);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            for (Method method : remoteMethods) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                MethodDoc methodDoc = method.methodDoc();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                out.writeUTF(methodDoc.name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                out.writeUTF(Util.methodDescriptorOf(methodDoc));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                                // descriptors already use binary names
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                ClassDoc exceptions[] = methodDoc.thrownExceptions();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                Arrays.sort(exceptions, new ClassDocComparator());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                for (ClassDoc ex : exceptions) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                    out.writeUTF(Util.binaryNameOf(ex));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
            out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            // use only the first 64 bits of the digest for the hash
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            byte hashArray[] = md.digest();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            for (int i = 0; i < Math.min(8, hashArray.length); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
            throw new AssertionError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
        } catch (NoSuchAlgorithmException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            throw new AssertionError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
        return hash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * Compares ClassDoc instances according to the lexicographic
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * order of their binary names.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    private static class ClassDocComparator implements Comparator<ClassDoc> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        public int compare(ClassDoc o1, ClassDoc o2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
            return Util.binaryNameOf(o1).compareTo(Util.binaryNameOf(o2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * Encapsulates RMI-specific information about a particular remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     * method in the remote implementation class represented by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
     * enclosing RemoteClass.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    final class Method implements Cloneable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
         * MethodDoc for this remove method, from one of the remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
         * interfaces that this method was found in.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
         * Note that this MethodDoc may be only one of multiple that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
         * correspond to this remote method object, if multiple of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
         * this class's remote interfaces contain methods with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
         * same name and descriptor.  Therefore, this MethodDoc may
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
         * declare more exceptions thrown that this remote method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
         * does.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        private final MethodDoc methodDoc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        /** java.rmi.server.Operation string for this remote method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        private final String operationString;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        /** name and descriptor of this remote method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        private final String nameAndDescriptor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        /** JRMP "method hash" for this remote method */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        private final long methodHash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
         * Exceptions declared to be thrown by this remote method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
         * This list may include superfluous entries, such as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
         * unchecked exceptions and subclasses of other entries.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        private ClassDoc[] exceptionTypes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
         * Creates a new Method instance for the specified method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        Method(MethodDoc methodDoc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
            this.methodDoc = methodDoc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            exceptionTypes = methodDoc.thrownExceptions();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
             * Sort exception types to improve consistency with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
             * previous implementations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            Arrays.sort(exceptionTypes, new ClassDocComparator());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            operationString = computeOperationString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            nameAndDescriptor =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                methodDoc.name() + Util.methodDescriptorOf(methodDoc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
            methodHash = computeMethodHash();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
         * Returns the MethodDoc object corresponding to this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
         * of a remote interface.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        MethodDoc methodDoc() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            return methodDoc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
         * Returns the parameter types declared by this method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        Type[] parameterTypes() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            Parameter[] parameters = methodDoc.parameters();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            Type[] paramTypes = new Type[parameters.length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            for (int i = 0; i < paramTypes.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
                paramTypes[i] = parameters[i].type();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            return paramTypes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
         * Returns the exception types declared to be thrown by this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
         * remote method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
         * For methods with the same name and descriptor inherited
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
         * from multiple remote interfaces, the array will contain the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
         * set of exceptions declared in all of the interfaces'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
         * methods that can be legally thrown by all of them.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        ClassDoc[] exceptionTypes() {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   562
            return exceptionTypes.clone();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
         * Returns the JRMP "method hash" used to identify this remote
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
         * method in the JDK 1.2 version of the stub protocol.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        long methodHash() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            return methodHash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
         * Returns the string representation of this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
         * appropriate for the construction of a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
         * java.rmi.server.Operation object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        String operationString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            return operationString;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
         * Returns a string consisting of this method's name followed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
         * by its descriptor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        String nameAndDescriptor() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            return nameAndDescriptor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
         * Returns a new Method object that is a legal combination of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
         * this Method object and another one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
         * Doing this requires determining the exceptions declared by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
         * the combined method, which must be (only) all of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
         * exceptions declared in both old Methods that may thrown in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
         * either of them.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        Method mergeWith(Method other) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            if (!nameAndDescriptor().equals(other.nameAndDescriptor())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
                throw new AssertionError(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                    "attempt to merge method \"" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                    other.nameAndDescriptor() + "\" with \"" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
                    nameAndDescriptor());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            List<ClassDoc> legalExceptions = new ArrayList<ClassDoc>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            collectCompatibleExceptions(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                other.exceptionTypes, exceptionTypes, legalExceptions);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            collectCompatibleExceptions(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                exceptionTypes, other.exceptionTypes, legalExceptions);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            Method merged = clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            merged.exceptionTypes =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                legalExceptions.toArray(new ClassDoc[legalExceptions.size()]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            return merged;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
         * Cloning is supported by returning a shallow copy of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
         * object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        protected Method clone() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                return (Method) super.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            } catch (CloneNotSupportedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                throw new AssertionError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
         * Adds to the supplied list all exceptions in the "froms"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
         * array that are subclasses of an exception in the "withs"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
         * array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        private void collectCompatibleExceptions(ClassDoc[] froms,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                                                 ClassDoc[] withs,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                                                 List<ClassDoc> list)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            for (ClassDoc from : froms) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                if (!list.contains(from)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                    for (ClassDoc with : withs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                        if (from.subclassOf(with)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                            list.add(from);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
         * Computes the JRMP "method hash" of this remote method.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
         * method hash is a long containing the first 64 bits of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
         * SHA digest from the UTF-8 encoded string of the method name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
         * and descriptor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
        private long computeMethodHash() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
            long hash = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
            ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
                MessageDigest md = MessageDigest.getInstance("SHA");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                DataOutputStream out = new DataOutputStream(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                    new DigestOutputStream(sink, md));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                String methodString = nameAndDescriptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                out.writeUTF(methodString);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                // use only the first 64 bits of the digest for the hash
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                byte hashArray[] = md.digest();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                for (int i = 0; i < Math.min(8, hashArray.length); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                    hash += ((long) (hashArray[i] & 0xFF)) << (i * 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                throw new AssertionError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
            } catch (NoSuchAlgorithmException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                throw new AssertionError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            return hash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
         * Computes the string representation of this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
         * appropriate for the construction of a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
         * java.rmi.server.Operation object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        private String computeOperationString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
             * To be consistent with previous implementations, we use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
             * the deprecated style of placing the "[]" for the return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
             * type (if any) after the parameter list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
            Type returnType = methodDoc.returnType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            String op = returnType.qualifiedTypeName() + " " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
                methodDoc.name() + "(";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
            Parameter[] parameters = methodDoc.parameters();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
            for (int i = 0; i < parameters.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                if (i > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                    op += ", ";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                op += parameters[i].type().toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            op += ")" + returnType.dimension();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            return op;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
}