protected String methodDecl(MethodDoc method, ClassDoc clazz, String cname)
      throws ClassNotFoundException {
    String res = null;

    Type retType = method.returnType();
    String typesig = method.signature();
    TypeSignature newTypeSig = new TypeSignature(root);
    String sig = newTypeSig.getTypeSignature(typesig, retType);
    boolean longName = needLongName(method, clazz);

    if (sig.charAt(0) != '(') Util.error("invalid.method.signature", sig);

    res =
        "JNIEXPORT "
            + jniType(retType)
            + " JNICALL"
            + lineSep
            + jniMethodName(method, cname, longName)
            + "(JNIEnv *, "
            + cRcvrDecl(method, cname);
    Parameter[] params = method.parameters();
    Type argTypes[] = new Type[params.length];
    for (int p = 0; p < params.length; p++) {
      argTypes[p] = params[p].type();
    }

    /* It would have been nice to include the argument names in the
    declaration, but there seems to be a bug in the "BinaryField"
    class, causing the getArguments() method to return "null" for
    most (non-constructor) methods. */
    for (int i = 0; i < argTypes.length; i++) res = res + ", " + jniType(argTypes[i]);
    res = res + ");" + lineSep;
    return res;
  }
  protected final String jniMethodName(MethodDoc method, String cname, boolean longName) {
    String res = "Java_" + cname + "_" + method.name();

    if (longName) {
      Type mType = method.returnType();
      Parameter[] params = method.parameters();
      Type argTypes[] = new Type[params.length];
      for (int p = 0; p < params.length; p++) {
        argTypes[p] = params[p].type();
      }

      res = res + "__";
      for (int i = 0; i < argTypes.length; i++) {
        Type t = argTypes[i];
        String tname = t.typeName();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(tname);
        res = res + nameToIdentifier(sig);
      }
    }
    return res;
  }
  protected void forwardDecls(PrintWriter pw, ClassDoc clazz) throws ClassNotFoundException {
    ClassDoc clazzfield = null;

    if (clazz.qualifiedName().equals("java.lang.Object")) return;
    genHandleType(pw, clazz.qualifiedName());
    ClassDoc superClass = clazz.superclass();

    if (superClass != null) {
      String superClassName = superClass.qualifiedName();
      forwardDecls(pw, superClass);
    }

    for (int i = 0; i < fields.length; i++) {
      FieldDoc field = (FieldDoc) fields[i];

      if (!field.isStatic()) {
        Type t = field.type();
        String tname = t.qualifiedTypeName();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(tname);

        if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig);
      }
    }

    for (int i = 0; i < methods.length; i++) {
      MethodDoc method = (MethodDoc) methods[i];

      if (method.isNative()) {
        Type retType = method.returnType();
        String typesig = method.signature();
        TypeSignature newTypeSig = new TypeSignature(root);
        String sig = newTypeSig.getTypeSignature(typesig, retType);

        if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig);
      }
    }
  }