Java Class Info

Java Class Info

---------------- ClassInfo.java ----------------

import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.function.*;

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.web.*;
import javafx.concurrent.*;
import javafx.collections.*;

import netscape.javascript.JSObject;

public class ClassInfo extends Application {

  TabPane tabPane;

  @Override
  public void start(Stage stage) {
    tabPane = new TabPane();
    tabPane.setTabMinWidth(50.0);
    tabPane.setTabMaxWidth(150.0);
    tabPane.getTabs().addListener((ListChangeListener.Change<? extends Tab> c) -> {
      while (c.next()) {
        if (c.wasAdded()) {
          tabPane.getTabs().get(0).setClosable(tabPane.getTabs().size() != 1);
        } else if (c.wasRemoved() && tabPane.getTabs().size() == 1) {
          tabPane.getTabs().get(0).setClosable(false);
        }
      }
    });
    List<String> p = getParameters().getRaw();
    String className = (p.isEmpty() ? getClass().getCanonicalName() : p.get(0));
    addTab(className);
    stage.setScene(new Scene(tabPane, 800, 600));
    stage.show();
  }

  public void addTab(String className) {
    for (Tab tab : tabPane.getTabs()) {
      if (className.equals(tab.getId())) {
        tabPane.getSelectionModel().select(tab);
        return;
      }
    }
    WebView webView = new WebView();
    WebEngine webEngine = webView.getEngine();
    webEngine.getLoadWorker().stateProperty().addListener((v, o, n) -> {
      if (n == Worker.State.SUCCEEDED) {
        JSObject jsobj = (JSObject) webEngine.executeScript("window");
        jsobj.setMember("jMember", this);
      }
    });
    StringBuilder sb = new StringBuilder();
    sb.append("<html><head>\n");
    sb.append(" <script language=\"javascript\">\n");
    sb.append("  function f(element) {\n");
    sb.append("   jMember.addTab(element.href);\n");
    sb.append("   return false;\n");
    sb.append("  }\n");
    sb.append(" </script>\n");
    sb.append(" <style> p { margin-top: 0; margin-bottom: 0.4em; } </style>\n");
    sb.append("</head><body>\n ");
    Class<?> c = null;
    char[] chars = className.toCharArray();
    for (int i = chars.length - 1; i >= 0; i--) {
      try {
        c = Class.forName(String.valueOf(chars));
        break;
      } catch (Exception e) {}
      for (; i >= 0; i--) {
        if (chars[i] == '.') {
          chars[i] = '$';
          break;
        }
      }
    }
    if (c == null) {
      sb.append("<p>Error loading class <b>").append(className).append("</b></p>");
    } else {
      final String cName = className = c.getCanonicalName();
      String sName = shortName(cName);
      Function<Class<?>, String> getType = type -> {
        String tcName = type.getCanonicalName();
        int i = 0;
        char ch = 0;
        for (String s = type.getName(); i < s.length(); i++) {
          if ((ch = s.charAt(i)) != '[') break;
        }
        boolean primitive = type.isPrimitive();
        if (i > 0) {
          tcName = tcName.substring(0, tcName.length() - i * 2);
          primitive |= (ch != 'L');
        }
        String tsName = shortName(tcName);
        String taq = type.getCanonicalName().substring(tcName.length());
        if (cName.equals(tcName)) return tsName.concat(taq);
        if (primitive) return new StringBuilder("<i>").append(tsName).append("</i>").append(taq).toString();
        return new StringBuilder("<a href=\"").append(tcName).append("\" title=\"").append(tcName)
          .append("\" onclick=\"return f(this);\">").append(tsName).append("</a>").append(taq).toString();
      };
      Module mdl = c.getModule();
      if (mdl != null && mdl.getName() != null && !mdl.getName().isEmpty()) {
        sb.append(getAnnotations(mdl.getDeclaredAnnotations()));
        sb.append("<p><b>Module</b> ").append(mdl.getName()).append("</p>");
      }
      Package pcg = c.getPackage();
      if (pcg != null && pcg.getName() != null && !pcg.getName().isEmpty()) {
        sb.append(getAnnotations(pcg.getDeclaredAnnotations()));
        sb.append("<p><b>Package</b> ").append(pcg.getName()).append("</p>");
      }
      String t = (c.isInterface() ? "Interface" : (c.isEnum() ? "Enum" : "Class"));
      sb.append("<p><font size=\"+2\"><b>").append(t).append(' ').append(sName).append("</b></font></p>");
      ArrayList<Class<?>> al = new ArrayList<>();
      for (Class<?> sc = c; (sc = sc.getSuperclass()) != null; al.add(sc));
      sb.append("<p>");
      String indent = "";
      for (int i = al.size() - 1; i >= 0; i--){
        sb.append(indent).append("<a href=\"").append(al.get(i).getCanonicalName()).append("\" onclick=\"return f(this);\">")
          .append(al.get(i).getCanonicalName()).append("</a><br>");
        indent = indent.concat("&emsp;");
      }
      sb.append(indent).append(cName).append("</p>");
      Class<?>[] interfaces = c.getInterfaces();
      if (interfaces.length > 0) {
        sb.append("<p><b>Implemented Interfaces:</b><br>");
        for (int i = 0; i < interfaces.length; i++) {
          if (i > 0) sb.append(", ");
          sb.append(getType.apply(interfaces[i]));
        }
        sb.append("</p>");
      }
      sb.append(getAnnotations(c.getDeclaredAnnotations()));
      sb.append("<p>").append(getModifiers(c.getModifiers())).append(t.toLowerCase()).append(' ').append(sName).append("</p>");
      Field[] fields = c.getDeclaredFields();
      if (fields.length > 0) {
        sb.append("<p><b>Fields:</b><br>");
        for (Field field : fields) { 
          sb.append(getAnnotations(field.getDeclaredAnnotations()));
          sb.append(getModifiers(field.getModifiers()));
          sb.append(getType.apply(field.getType())).append(' ');
          sb.append(field.getName()).append("<br>");
        }
        sb.append("</p>");
      }
      for (Class<?> sc : al) {
        boolean first = true;
        for (Field field : sc.getDeclaredFields()) {
          if ((field.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
            if (first) sb.append("<p><b>Fields inherited from ").append(getType.apply(sc)).append(":</b> ");
            else sb.append(", ");
            sb.append(field.getName());
            first = false;
          }
        }
        if (!first) sb.append("</p>");
      }
      for (int n = 0; n < 2; n++) {
        Executable[] executables = (n == 0 ? c.getDeclaredConstructors() : c.getDeclaredMethods());
        if (executables.length > 0) {
          sb.append("<p><b>").append(n == 0 ? "Constructors" : "Methods").append(":</b><br>");
          for (Executable executable : executables) {
            sb.append(getAnnotations(executable.getDeclaredAnnotations()));
            sb.append(getModifiers(executable.getModifiers()));
            if (n > 0) sb.append(getType.apply(((Method)executable).getReturnType())).append(' ');
            sb.append(shortName(executable.getName())).append('(');
            Class<?>[] paramTypes = executable.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
              if (i > 0) sb.append(", ");
              sb.append(getType.apply(paramTypes[i]));
            }
            sb.append(")<br>");
          }
          sb.append("</p>");
        }
        if (n > 0) {
          for (Class<?> sc : al) {
            boolean first = true;
            for (Method method : sc.getDeclaredMethods()) {
              if ((method.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
                if (first) sb.append("<p><b>Methods inherited from ").append(getType.apply(sc)).append(":</b> ");
                else sb.append(", ");
                sb.append(method.getName());
                first = false;
              }
            }
            if (!first) sb.append("</p>");
          }
        }
      }
    }
    sb.append("\n</body></html>\n");
    //try { java.nio.file.Files.write(java.nio.file.Paths.get("out_"+shortName(className)+".html"), sb.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8)); } catch (Exception e) {}
    webEngine.loadContent(sb.toString());
    Tab tab = new Tab(shortName(className), webView);
    tab.setId(className);
    tab.setTooltip(new Tooltip(className));
    tabPane.getTabs().add(tab);
    tabPane.getSelectionModel().select(tab);
  }

  String shortName(String name) {
    char[] chars = name.toCharArray();
    int i = chars.length - 1, end = i;
    for (; i >= 0; i--) {
      if (chars[i] == '.' || chars[i] == '$') break;
    }
    return (i < 0 ? name : new String(chars, i + 1, end - i));
  }

  String getModifiers(int mod) {
    String str = Modifier.toString(~Modifier.INTERFACE & mod);
    return (str.isEmpty() ? str : str.concat(" "));
  }

  String getAnnotations(Annotation[] annotations) {
    if (annotations.length == 0) return "";
    StringBuilder sb = new StringBuilder();
    for (Annotation annotation : annotations) {
      sb.append(annotation.toString()).append("<br>");
    }
    return sb.toString();
  }
}

Download ZIP

Back