Logo Search packages:      
Sourcecode: japitools version File versions  Download package

static boolean net::wuffies::japi::Japize::japizeClass ( String  n  )  throws NoSuchMethodException, IllegalAccessException [inline, static]

Write out API information for a given class. Nothing will be written if the class is not public/protected.

Parameters:
n The name of the class to process.
Returns:
true if the class was public/protected, false if not.

Definition at line 620 of file Japize.java.

References net::wuffies::japi::ClassType::bind(), getClassWrapper(), getFieldsAndCalls(), net::wuffies::japi::ClassType::getJavaRepr(), getObjComparableString(), net::wuffies::japi::ClassType::getWrapper(), includeException(), isEntirelyVisible(), mkIfaceString(), and printEntry().

                                                           {
    try {

      // De-mangle the class name.
      if (n.charAt(0) == ',') n = n.substring(1);
      n = n.replace(',', '.');

      // Get a ClassWrapper to work on.
      ClassWrapper c = getClassWrapper(n);

      // Load the class and check its accessibility.
      int mods = c.getModifiers();
      if (!Modifier.isPublic(mods) && !Modifier.isProtected(mods)) {
        progress('-');
        return false;
      }

      // Construct the basic strings that will be used in the output.
      String entry = toClassRoot(c.getName()) + "!";
      String classEntry = entry;
      String type;
      if (c.isEnum()) {
        type = "enum";
      } else if (c.isAnnotation()) {
        type = "annotation";
      } else if (c.isInterface()) {
        type = "interface";
      } else {
        type = "class";
      }

      type += getTypeParamStr(c);
      
      if (c.isInterface()) {
        mods |= Modifier.ABSTRACT; // Interfaces are abstract by definition,

      } else {

        // Classes that happen to be Serializable get their SerialVersionUID
        // output as well. The separation by the '#' character from the rest
        // of the type string has mnemonic value for Brits, as the SVUID is a
        // special sort of 'hash' of the class.
        if (c.isSerializable()) {
          Long svuid = c.getSerialVersionUID();
          if (svuid == null) lintPrint(c.getName() + " has a blank final serialVersionUID");
          type += "#" + svuid;
        }
      }

      // Iterate over the class's superclasses adding them to its "type" name,
      // skipping any superclasses that are not public/protected.
      int smods = mods;
      ClassType supt = c.getSuperclass();
      while (supt != null) {
        ClassWrapper sup = supt.getWrapper();
        smods = sup.getModifiers();
        if (!Modifier.isPublic(smods) && !Modifier.isProtected(smods)) {
          lintPrint(c.getName() + " has non-public class " + sup.getName() + " among its superclasses");
          progress('^');
        } else {
          type += ":" + supt.getJavaRepr(c);
        }
        if (sup.getSuperclass() == null) {
          supt = null;
        } else {
          supt = (ClassType) sup.getSuperclass().bind(supt);
        }
      }
      type += mkIfaceString(c, "");

      // Skip things that aren't entirely visible as defined below.
      if (!isEntirelyVisible(c)) return false;

      // Print out the japi entry for the class itself.
      printEntry(entry, type, mods, c.isDeprecated(), false);

      // Get the class's members.
      Map fieldMap = new HashMap();
      Map callMap = new HashMap();
      getFieldsAndCalls(c, null, fieldMap, callMap);
      BoundField[] fields = new BoundField[fieldMap.size()];
      fieldMap.values().toArray(fields);
      Arrays.sort(fields);
      BoundCall[] calls = new BoundCall[callMap.size()];
      callMap.values().toArray(calls);
      Arrays.sort(calls);

      // Iterate over the fields in the class.
      for (int i = 0; i < fields.length; i++) {

        // Fields that are declared in a non-public superclass are not accessible.
        // Skip them.
        int dmods = fields[i].getDeclaringClass().getModifiers();
        if (!Modifier.isPublic(dmods) && !Modifier.isProtected(dmods)) {
          progress('>');
          continue;
        }

        // Get the modifiers and type of the field.
        mods = fields[i].getModifiers();

        // Fields of interfaces are *always* public, static and final, although
        // wrapper implementations are inconsistent about telling us this.
        if (fields[i].getDeclaringClass().isInterface()) {
          mods |= Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC;
        }
        type = fields[i].getType().getTypeSig(c);

        if (fields[i].getName().equals("serialVersionUID") &&
            fields[i].getDeclaringClass() == c) {
          if (c.isInterface()) {
            lintPrint("Useless serialVersionUID field in interface " + c.getName());
          } else if (!Modifier.isStatic(fields[i].getModifiers()) ||
                     !Modifier.isFinal(fields[i].getModifiers())) {
            lintPrint("serialVersionUID field in " + c.getName() + " not 'static final'");
          } else if (!c.isSerializable()) {
            lintPrint("serialVersionUID field in non-serializable class " + c.getName());
          }
        }

        if (!Modifier.isFinal(fields[i].getModifiers()) &&
            (Modifier.isPublic(fields[i].getModifiers()) ||
             Modifier.isStatic(fields[i].getModifiers()))) {
          type += '=' + fields[i].getDeclaringClass().getName();
        }

        // A static, final field is a primitive constant if it is initialized to
        // a compile-time constant.
        if (fields[i].isPrimitiveConstant()) {
          Object o = fields[i].getPrimitiveValue();

          // Character values get int-ized to keep the output nice and 7bit.
          if (o instanceof Character) {
            type += ":" + (int)((Character)o).charValue();
          
          // String values get newlines and backslashes escaped to stop them from
          // going onto a second line.
          } else if (o instanceof String) {
            String val = (String)o;
            StringBuffer sb = new StringBuffer('\"');
            int p = 0, q = 0;
            while (q >= 0) {
              q = val.indexOf("\n", p);
              int r = val.indexOf("\\", p);
              if (r >= 0 && (r < q || q < 0)) q = r;
              if (q >= 0) {
                sb.append(val.substring(p, q));
                sb.append('\\');
                if (val.charAt(q) == '\\') sb.append('\\'); else sb.append('n');
                p = ++q;
              }
            }
            sb.append(val.substring(p));
            type += ":" + sb;

          // Floats and doubles get their toRaw*Bits() value printed as well as
          // their actual value.
          } else if (o instanceof Float) {
            type += ':' + o.toString() + '/' +
                Integer.toHexString(Float.floatToRawIntBits(
                                    ((Float) o).floatValue()));
          } else if (o instanceof Double) {
            type += ':' + o.toString() + '/' +
                Long.toHexString(Double.doubleToRawLongBits(
                                 ((Double) o).doubleValue()));

          // Other types just get output.
          } else {
            type += ":" + o;
          }
        }

        // Skip things that aren't entirely visible as defined below.
        if (!isEntirelyVisible(fields[i])) continue;

        // Output the japi entry for the field.
        printEntry(classEntry + "#" + fields[i].getName(), type, mods,
                   fields[i].isDeprecated(), fields[i].isEnumField());
      }

      // Iterate over the methods and constructors in the class.
      for (int i = 0; i < calls.length; i++) {

        // Methods that are declared in a non-public superclass are not
        // publically accessible. Skip them.
        int dmods = calls[i].getDeclaringClass().getModifiers();
        if (!Modifier.isPublic(dmods) && !Modifier.isProtected(dmods)) {
          progress('}');
          continue;
        }

        // Skip calls called <init> and <clinit>. Constructors are handled
        // with an empty method name, and class initializers are never part of
        // the public API.
        if ("<init>".equals(calls[i].getName()) ||
            "<clinit>".equals(calls[i].getName())) {
          continue;
        }

        // Skip methods in interfaces that are also defined identically in
        // Object. Specifically, it needs to be defined in Object with
        // *exactly* the same parameter types, return types *and* thrown
        // exceptions (because it *is* legal for an interface to specify,
        // say, "Object clone();" and thereby specify that implementors must
        // not throw CloneNotSupportedException from their clone method.
        // Surprisingly, Cloneable doesn't do this...)
        if (c.isInterface()) {
          if (objCalls.contains(getObjComparableString(calls[i]))) {
            progress(';');
            continue;
          }
        }

        // Construct the name of the method, of the form Class!method(params).
        entry = classEntry + calls[i].getName() + "(";
        Type[] params = calls[i].getParameterTypes();
        String comma = "";
        for (int j = 0; j < params.length; j++) {
          entry += comma + params[j].getTypeSig(calls[i]);
          comma = ",";
        }
        entry += ")";
        if (calls[i].getExclude14()) {
          entry += "+";
        } else if (calls[i].getExclude15()) {
          entry += "-";
        }

        // Construct the "type" field, of the form returnType*exception*except2...
        type = "";

        // ... but if it's a generic method it gets the type parameters first
        type += getTypeParamStr(calls[i]);

        Type rtnType = calls[i].getReturnType();
        type += (rtnType == null) ? "constructor" : rtnType.getTypeSig(calls[i]);
        NonArrayRefType[] excps = calls[i].getExceptionTypes();
        for (int j = 0; j < excps.length; j++) {
          if (includeException(excps, j)) type += "*" + excps[j].getJavaRepr(calls[i]);
        }

        // Get the modifiers for this method. Methods of interfaces are
        // by definition public and abstract, although wrapper implementations
        // are inconsistent about telling us this.
        int mmods = calls[i].getModifiers();
        if (c.isInterface()) {
          mmods |= Modifier.ABSTRACT | Modifier.PUBLIC;
        }

        // Methods of final classes are by definition final
        if (Modifier.isFinal(c.getModifiers())) {
          mmods |= Modifier.FINAL;
        }

        // Constructors are never final. The verifier should enforce this
        // so this should always be a no-op, except for when the line above
        // set it.
        if ("".equals(calls[i].getName())) {
          mmods &= ~Modifier.FINAL;
        }

        // Skip things that aren't entirely visible as defined below.
        if (!isEntirelyVisible(calls[i])) continue;

        // Print the japi entry for the method.
        printEntry(entry, type, mmods, calls[i].isDeprecated(), false);
      }

      // Return true because we did parse this class.
      progress('+');
      return true;
    } catch (NoClassDefFoundError e) {
      System.err.println("\nFailed to Japize " + n + ": " + e);
      e.printStackTrace();
    } catch (NullPointerException e) {
      System.err.println("\nFailed to Japize " + n + ": " + e);
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      System.err.println("\nFailed to Japize " + n + ": " + e);
      e.printStackTrace();
    } catch (IndexOutOfBoundsException e) {
      System.err.println("\nFailed to Japize " + n + ": " + e);
      e.printStackTrace();
    } catch (RuntimeException e) {
      System.err.println("\nFailed to Japize " + n + ": " + e);
      e.printStackTrace();
    }
    return false;
  }


Generated by  Doxygen 1.6.0   Back to index