/*
 * Copyright 1997-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.rmi.rmic;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.DigestOutputStream;
import java.security.NoSuchAlgorithmException;
import sun.tools.java.Type;
import sun.tools.java.ClassDefinition;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.MemberDefinition;
import sun.tools.java.Identifier;
import sun.tools.java.ClassNotFound;

/**
 * A RemoteClass object encapsulates RMI-specific information about
 * a remote implementation class, i.e. a class that implements
 * one or more remote interfaces.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @author      Peter Jones
 */
public class RemoteClass implements sun.rmi.rmic.RMIConstants {

    /**
     * Create a RemoteClass object representing the remote meta-information
     * of the given class.
     *
     * Returns true if successful.  If the class is not a properly formed
     * remote implementation class or if some other error occurs, the
     * return value will be null, and errors will have been reported to
     * the supplied BatchEnvironment.
     */
    public static RemoteClass forClass(BatchEnvironment env,
                                       ClassDefinition implClassDef)
    {
        RemoteClass rc = new RemoteClass(env, implClassDef);
        if (rc.initialize()) {
            return rc;
        } else {
            return null;
        }
    }

    /**
     * Return the ClassDefinition for this class.
     */
    public ClassDefinition getClassDefinition() {
        return implClassDef;
    }

    /**
     * Return the name of the class represented by this object.
     */
    public Identifier getName() {
        return implClassDef.getName();
    }

    /**
     * Return an array of ClassDefinitions representing all of the remote
     * interfaces implemented by this class.
     *
     * A remote interface is any interface that extends Remote,
     * directly or indirectly.  The remote interfaces of a class
     * are the interfaces directly listed in either the class's
     * "implements" clause, or the "implements" clause of any
     * of its superclasses, that are remote interfaces.
     *
     * The order of the array returned is arbitrary, and some elements
     * may be superfluous (i.e., superinterfaces of other interfaces
     * in the array).
     */
    public ClassDefinition[] getRemoteInterfaces() {
        return (ClassDefinition[]) remoteInterfaces.clone();
    }

    /**
     * Return an array of RemoteClass.Method objects representing all of
     * the remote methods implemented by this class, i.e. all of the
     * methods in the class's remote interfaces.
     *
     * The methods in the array are ordered according to the comparision
     * of the strings consisting of their method name followed by their
     * type signature, so each method's index in the array corresponds
     * to its "operation number" in the JDK 1.1 version of the
     * stub/skeleton protocol.
     */
    public Method[] getRemoteMethods() {
        return (Method[]) remoteMethods.clone();
    }

    /**
     * Return the "interface hash" used to match a stub/skeleton pair for
     * this class in the JDK 1.1 version of the stub/skeleton protocol.
     */
    public long getInterfaceHash() {
        return interfaceHash;
    }

    /**
     * Return string representation of this object, consisting of
     * the string "remote class " followed by the class name.
     */
    public String toString() {
        return "remote class " + implClassDef.getName().toString();
    }

    /** rmic environment for this object */
    private BatchEnvironment env;

    /** the remote implementation class this object corresponds to */
    private ClassDefinition implClassDef;

    /** remote interfaces implemented by this class */
    private ClassDefinition[] remoteInterfaces;

    /** all the remote methods of this class */
    private Method[] remoteMethods;

    /** stub/skeleton "interface hash" for this class */
    private long interfaceHash;

    /** cached definition for certain classes used in this environment */
    private ClassDefinition defRemote;
    private ClassDefinition defException;
    private ClassDefinition defRemoteException;

    /**
     * Create a RemoteClass instance for the given class.  The resulting
     * object is not yet initialized.
     */
    private RemoteClass(BatchEnvironment env, ClassDefinition implClassDef) {
        this.env = env;
        this.implClassDef = implClassDef;
    }

    /**
     * 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.
         */
        Vector remotesImplemented =     // list of remote interfaces found
            new Vector();
        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 methods = new Hashtable();
        boolean errors = false;
        for (Enumeration enumeration = remotesImplemented.elements();
             enumeration.hasMoreElements();)
            {
                ClassDefinition interfaceDef =
                    (ClassDefinition) 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 enumeration = methods.elements();
             enumeration.hasMoreElements();)
            {
                Method m = (Method) 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] = (Method) 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;
    }

    /**
     * Collect and validate all methods from given interface and all of
     * its superinterfaces as remote methods.  Remote methods are added
     * to the supplied hashtable.  Returns true if successful,
     * or false if an error occurred.
     */
    private boolean collectRemoteMethods(ClassDefinition interfaceDef,
                                         Hashtable table)
    {
        if (!interfaceDef.isInterface()) {
            throw new Error(
                            "expected interface, not class: " + interfaceDef.getName());
        }

        /*
         * rmic used to enforce that a remote interface could not extend
         * a non-remote interface, i.e. an interface that did not itself
         * extend from Remote.  The current version of rmic does not have
         * this restriction, so the following code is now commented out.
         *
         * Verify that this interface extends Remote, since all interfaces
         * extended by a remote interface must implement Remote.
         *
         *      try {
         *          if (!defRemote.implementedBy(env,
         *              interfaceDef.getClassDeclaration()))
         *          {
         *              env.error(0, "rmic.can.mix.remote.nonremote",
         *                  interfaceDef.getName());
         *              return false;
         *          }
         *      } catch (ClassNotFound e) {
         *          env.error(0, "class.not.found", e.name,
         *              interfaceDef.getName());
         *          return false;
         *      }
         */

        boolean errors = false;

        /*
         * Search interface's members for methods.
         */
    nextMember:
        for (MemberDefinition member = interfaceDef.getFirstMember();
             member != null;
             member = member.getNextMember())
            {
                if (member.isMethod() &&
                    !member.isConstructor() && !member.isInitializer())
                    {
                        /*
                         * Verify that each method throws RemoteException.
                         */
                        ClassDeclaration[] exceptions = member.getExceptions(env);
                        boolean hasRemoteException = false;
                        for (int i = 0; i < exceptions.length; i++) {
                            /*
                             * rmic used to enforce that a remote method had to
                             * explicitly list RemoteException in its "throws"
                             * clause; i.e., just throwing Exception was not
                             * acceptable.  The current version of rmic does not
                             * have this restriction, so the following code is
                             * now commented out.  Instead, the method is
                             * considered valid if RemoteException is a subclass
                             * of any of the methods declared exceptions.
                             *
                             *  if (exceptions[i].getName().equals(
                             *      idRemoteException))
                             *  {
                             *      hasRemoteException = true;
                             *      break;
                             *  }
                             */
                            try {
                                if (defRemoteException.subClassOf(
                                                                  env, exceptions[i]))
                                    {
                                        hasRemoteException = true;
                                        break;
                                    }
                            } catch (ClassNotFound e) {
                                env.error(0, "class.not.found", e.name,
                                          interfaceDef.getName());
                                continue nextMember;
                            }
                        }
                        /*
                         * If this method did not throw RemoteException as required,
                         * generate the error but continue, so that multiple such
                         * errors can be reported.
                         */
                        if (!hasRemoteException) {
                            env.error(0, "rmic.must.throw.remoteexception",
                                      interfaceDef.getName(), member.toString());
                            errors = true;
                            continue nextMember;
                        }

                        /*
                         * Verify that the implementation of this method throws only
                         * java.lang.Exception or its subclasses (fix bugid 4092486).
                         * JRMP does not support remote methods throwing
                         * java.lang.Throwable or other subclasses.
                         */
                        try {
                            MemberDefinition implMethod = implClassDef.findMethod(
                                                                                  env, member.getName(), member.getType());
                            if (implMethod != null) {           // should not be null
                                exceptions = implMethod.getExceptions(env);
                                for (int i = 0; i < exceptions.length; i++) {
                                    if (!defException.superClassOf(
                                                                   env, exceptions[i]))
                                        {
                                            env.error(0, "rmic.must.only.throw.exception",
                                                      implMethod.toString(),
                                                      exceptions[i].getName());
                                            errors = true;
                                            continue nextMember;
                                        }
                                }
                            }
                        } catch (ClassNotFound e) {
                            env.error(0, "class.not.found", e.name,
                                      implClassDef.getName());
                            continue nextMember;
                        }

                        /*
                         * Create RemoteClass.Method object to represent this method
                         * found in a remote interface.
                         */
                        Method newMethod = new Method(member);
                        /*
                         * Store remote method's representation in the table of
                         * remote methods found, keyed by its name and parameter
                         * signature.
                         *
                         * If the table already contains an entry with the same
                         * method name and parameter signature, then we must
                         * replace the old entry with a Method object that
                         * represents a legal combination of the old and the new
                         * methods; specifically, the combined method must have
                         * a throws list that contains (only) all of the checked
                         * exceptions that can be thrown by both the old or
                         * the new method (see bugid 4070653).
                         */
                        String key = newMethod.getNameAndDescriptor();
                        Method oldMethod = (Method) table.get(key);
                        if (oldMethod != null) {
                            newMethod = newMethod.mergeWith(oldMethod);
                            if (newMethod == null) {
                                errors = true;
                                continue nextMember;
                            }
                        }
                        table.put(key, newMethod);
                    }
            }

        /*
         * Recursively collect methods for all superinterfaces.
         */
        try {
            ClassDeclaration[] superDefs = interfaceDef.getInterfaces();
            for (int i = 0; i < superDefs.length; i++) {
                ClassDefinition superDef =
                    superDefs[i].getClassDefinition(env);
                if (!collectRemoteMethods(superDef, table))
                    errors = true;
            }
        } catch (ClassNotFound e) {
            env.error(0, "class.not.found", e.name, interfaceDef.getName());
            return false;
        }

        return !errors;
    }

    /**
     * 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;
    }

    /**
     * Sort array of class declarations alphabetically by their mangled
     * fully-qualfied 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;
        }
    }


    /**
     * A RemoteClass.Method object encapsulates RMI-specific information
     * about a particular remote method in the remote implementation class
     * represented by the outer instance.
     */
    public class Method implements Cloneable {

        /**
         * Return the definition of the actual class member corresponing
         * to this method of a remote interface.
         *
         * REMIND: Can this method be removed?
         */
        public MemberDefinition getMemberDefinition() {
            return memberDef;
        }

        /**
         * Return the name of this method.
         */
        public Identifier getName() {
            return memberDef.getName();
        }

        /**
         * Return the type of this method.
         */
        public Type getType() {
            return memberDef.getType();
        }

        /**
         * Return an array of the exception classes declared to be
         * thrown by this remote method.
         *
         * For methods with the same name and type signature inherited
         * from multiple remote interfaces, the array will contain
         * the set of exceptions declared in all of the interfaces'
         * methods that can be legally thrown in each of them.
         */
        public ClassDeclaration[] getExceptions() {
            return (ClassDeclaration[]) exceptions.clone();
        }

        /**
         * Return the "method hash" used to identify this remote method
         * in the JDK 1.2 version of the stub protocol.
         */
        public long getMethodHash() {
            return methodHash;
        }

        /**
         * Return the string representation of this method.
         */
        public String toString() {
            return memberDef.toString();
        }

        /**
         * Return the string representation of this method appropriate
         * for the construction of a java.rmi.server.Operation object.
         */
        public String getOperationString() {
            return memberDef.toString();
        }

        /**
         * Return a string consisting of this method's name followed by
         * its method descriptor, using the Java VM's notation for
         * method descriptors (see section 4.3.3 of The Java Virtual
         * Machine Specification).
         */
        public String getNameAndDescriptor() {
            return memberDef.getName().toString() +
                memberDef.getType().getTypeSignature();
        }

        /**
         * Member definition for this method, from one of the remote
         * interfaces that this method was found in.
         *
         * Note that this member definition may be only one of several
         * member defintions that correspond to this remote method object,
         * if several of this class's remote interfaces contain methods
         * with the same name and type signature.  Therefore, this member
         * definition may declare more exceptions thrown that this remote
         * method does.
         */
        private MemberDefinition memberDef;

        /** stub "method hash" to identify this method */
        private long methodHash;

        /**
         * Exceptions declared to be thrown by this remote method.
         *
         * This list can include superfluous entries, such as
         * unchecked exceptions and subclasses of other entries.
         */
        private ClassDeclaration[] exceptions;

        /**
         * Create a new Method object corresponding to the given
         * method definition.
         */
        /*
         * Temporarily comment out the private modifier until
         * the VM allows outer class to access inner class's
         * private constructor
         */
        /* private */ Method(MemberDefinition memberDef) {
            this.memberDef = memberDef;
            exceptions = memberDef.getExceptions(env);
            methodHash = computeMethodHash();
        }

        /**
         * Cloning is supported by returning a shallow copy of this object.
         */
        protected Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException e) {
                throw new Error("clone failed");
            }
        }

        /**
         * Return a new Method object that is a legal combination of
         * this method object and another one.
         *
         * This requires determining the exceptions declared by the
         * combined method, which must be (only) all of the exceptions
         * declared in both old Methods that may thrown in either of
         * them.
         */
        private Method mergeWith(Method other) {
            if (!getName().equals(other.getName()) ||
                !getType().equals(other.getType()))
                {
                    throw new Error("attempt to merge method \"" +
                                    other.getNameAndDescriptor() + "\" with \"" +
                                    getNameAndDescriptor());
                }

            Vector legalExceptions = new Vector();
            try {
                collectCompatibleExceptions(
                                            other.exceptions, exceptions, legalExceptions);
                collectCompatibleExceptions(
                                            exceptions, other.exceptions, legalExceptions);
            } catch (ClassNotFound e) {
                env.error(0, "class.not.found", e.name,
                          getClassDefinition().getName());
                return null;
            }

            Method merged = (Method) clone();
            merged.exceptions = new ClassDeclaration[legalExceptions.size()];
            legalExceptions.copyInto(merged.exceptions);

            return merged;
        }

        /**
         * Add to the supplied list all exceptions in the "from" array
         * that are subclasses of an exception in the "with" array.
         */
        private void collectCompatibleExceptions(ClassDeclaration[] from,
                                                 ClassDeclaration[] with,
                                                 Vector list)
            throws ClassNotFound
        {
            for (int i = 0; i < from.length; i++) {
                ClassDefinition exceptionDef = from[i].getClassDefinition(env);
                if (!list.contains(from[i])) {
                    for (int j = 0; j < with.length; j++) {
                        if (exceptionDef.subClassOf(env, with[j])) {
                            list.addElement(from[i]);
                            break;
                        }
                    }
                }
            }
        }

        /**
         * Compute the "method hash" of this remote method.  The method
         * hash is a long containing the first 64 bits of the SHA digest
         * from the UTF encoded string of the method name and descriptor.
         *
         * REMIND: Should this method share implementation code with
         * the outer class's computeInterfaceHash() method?
         */
        private long computeMethodHash() {
            long hash = 0;
            ByteArrayOutputStream sink = new ByteArrayOutputStream(512);
            try {
                MessageDigest md = MessageDigest.getInstance("SHA");
                DataOutputStream out = new DataOutputStream(
                                                            new DigestOutputStream(sink, md));

                String methodString = getNameAndDescriptor();
                /***** <DEBUG> */
                if (env.verbose()) {
                    System.out.println("[string used for method hash: \"" +
                                       methodString + "\"]");
                }
                /***** </DEBUG> */
                out.writeUTF(methodString);

                // use only the first 64 bits of the digest for the hash
                out.flush();
                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;
        }
    }
}
