Added support for array of arrays.
package eu.svjatoslav.inspector.java;
import eu.svjatoslav.commons.commandline.parameterparser.Parser;
-import eu.svjatoslav.commons.commandline.parameterparser.parameter.FileParameter;
+import eu.svjatoslav.commons.commandline.parameterparser.parameter.FileParameters;
+import eu.svjatoslav.commons.commandline.parameterparser.parameter.NullParameter;
import eu.svjatoslav.commons.commandline.parameterparser.parameter.StringParameter;
import eu.svjatoslav.commons.commandline.parameterparser.parameter.StringParameters;
public class CommandlineConfiguration {
- public FileParameter jarFile;
+ public FileParameters jarFiles;
public StringParameter graphName;
+ private NullParameter showDebug;
public CommandlineConfiguration (String args[]){
Parser parser = buildCommandlineParameterParser();
}
+ public boolean isDebug(){
+ return showDebug.isSpecified();
+ }
+
public Parser buildCommandlineParameterParser() {
Parser parser = new Parser();
- jarFile = parser.add(
- new FileParameter("JAR file"))
+ jarFiles = parser.add(
+ new FileParameters("JAR file(s)"))
.mustExist()
.addAliases("-j");
.setMandatory()
.addAliases("-n");
+ showDebug = parser.add(
+ new NullParameter("show debug info"))
+ .addAliases("-d");
+
parser.add(
new StringParameters("whitelist glob"))
.addAliases("-w");
import eu.svjatoslav.inspector.java.structure.ClassGraph;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
import static java.io.File.separator;
import static java.lang.System.getProperty;
* This class acts as a commandline interface for JavaInspect.
*/
public class Main {
- public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {
- CommandlineConfiguration commandlineConfiguration = new CommandlineConfiguration(args);
- System.out.println("Commandline config validated");
+ public static void main(String[] args) throws IOException, ClassNotFoundException {
+ CommandlineConfiguration configuration = new CommandlineConfiguration(args);
- File jarFile = commandlineConfiguration.jarFile.getValue();
+ List<File> jarFiles = configuration.jarFiles.getValue();
URLClassLoader classLoader = new URLClassLoader(
- new URL[]{jarFile.toURL()},
- commandlineConfiguration.getClass().getClassLoader());
+ getFileUrls(jarFiles),
+ configuration.getClass().getClassLoader());
- Class classToLoad = Class.forName("eu.svjatoslav.sixth.e3d.gui.GuiComponent", true, classLoader);
+ ClassGraph classGraph = new ClassGraph();
+ classGraph.setTargetDirectoryPath(getProperty("user.dir") + separator);
+ classGraph.setKeepDotFile(true);
+ for (File jarFile : jarFiles)
+ addJarToGraph(jarFile, classLoader, classGraph, configuration);
- ClassGraph cg = new ClassGraph();
- cg.setTargetDirectoryPath(getProperty("user.dir") + separator);
+ classGraph.generateGraph(configuration.graphName.getValue());
-// cg.addProject(projectDir);
-// cg.whitelistClassGlob(packageGlob);
- cg.setKeepDotFile(true);
- cg.add(classToLoad);
- cg.generateGraph(commandlineConfiguration.graphName.getValue());
- }
+ if (configuration.isDebug())
+ System.out.println("Graph ready.");
+ }
+
+ private static URL[] getFileUrls(List<File> jarFiles) {
+ List<URL> urls = new ArrayList<>();
+ jarFiles.forEach((File file) -> {
+ try {
+ urls.add(file.toURI().toURL());
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ return urls.toArray(new URL[urls.size()]);
+ }
+
+ private static void addJarToGraph(
+ File jarFile, URLClassLoader classLoader, ClassGraph classGraph, CommandlineConfiguration configuration)
+ throws IOException, ClassNotFoundException {
+
+ for (String className : getClassNamesFromJar(jarFile)) {
+ if (configuration.isDebug())
+ System.out.println("Adding class to graph: " + className);
+
+ classGraph.add(loadClassByName(classLoader, className));
+ }
+ }
+
+ private static Class loadClassByName(URLClassLoader classLoader, String className) throws ClassNotFoundException {
+ return Class.forName(className, true, classLoader);
+ }
+
+ public static List<String> getClassNamesFromJar(File jarFile) throws IOException {
+ List<String> result = new ArrayList<>();
+ try (
+ JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile));
+ ) {
+ while (true) {
+ JarEntry jarEntry = jarInputStream.getNextJarEntry();
+ if (jarEntry == null)
+ break;
+
+ if (isClassFile(jarEntry))
+ result.add(getClassNameFromFileName(jarEntry));
+ }
+
+ return result;
+ }
+ }
+
+ private static boolean isClassFile(JarEntry jarEntry) {
+ return jarEntry.getName().endsWith(".class");
+ }
+
+ private static String getClassNameFromFileName(JarEntry jarEntry) {
+ String result = jarEntry.getName().replaceAll("/", "\\.");
+ return result.substring(0, result.lastIndexOf('.'));
+ }
}
public class ClassDescriptor implements GraphElement, Comparable<ClassDescriptor> {
private static final int MAX_REFERECNES_COUNT = 10;
- private final Map<String, FieldDescriptor> nameToFieldMap = new TreeMap<String, FieldDescriptor>();
+ private final Map<String, FieldDescriptor> nameToFieldMap = new TreeMap<>();
private final SortedSet<MethodDescriptor> methods = new TreeSet<MethodDescriptor>();
private final ClassGraph classGraph;
boolean isEnum;
result.append("\n");
result.append(" // field references to other classes\n");
- for (final Map.Entry<String, FieldDescriptor> entry : nameToFieldMap
- .entrySet())
- result.append(entry.getValue().getDot());
+ nameToFieldMap.forEach((fieldName, field) -> result.append(field.getDot()));
}
private void enlistFields(final StringBuffer result) {
+ fullyQualifiedName
.replace('.', '_')
.replace(";", "")
- .replace("[L", "")
.replace("[[", "")
+ .replace("[L", "")
+ .replace("[[L", "") // array of arrays
+ .replace("[[[L", "") // array of arrays of arrays
.replace('$', '_');
+
return result;
}
public class FieldDescriptor implements GraphElement {
- private final ClassDescriptor parentClassDescriptior;
+ private final ClassDescriptor parentClassDescriptor;
private final List<ClassDescriptor> typeArguments = new ArrayList<ClassDescriptor>();
private String name;
private ClassDescriptor type;
private boolean isInherited;
public FieldDescriptor(final ClassDescriptor parent) {
- parentClassDescriptior = parent;
+ parentClassDescriptor = parent;
}
public void analyzeField(final Field field) {
if (!field.getDeclaringClass().getName()
- .equals(parentClassDescriptior.getFullyQualifiedName()))
+ .equals(parentClassDescriptor.getFullyQualifiedName()))
isInherited = true;
name = field.getName();
- type = parentClassDescriptior.getClassGraph().getOrCreateClassDescriptor(
+ type = parentClassDescriptor.getClassGraph().getOrCreateClassDescriptor(
field.getType());
type.registerReference();
for (final Type type : fieldParameterizedGenericType.getActualTypeArguments())
if (type instanceof Class) {
final Class aClass = (Class) type;
- final ClassDescriptor genericTypeDescriptor = parentClassDescriptior
+ final ClassDescriptor genericTypeDescriptor = parentClassDescriptor
.getClassGraph().getOrCreateClassDescriptor(aClass);
genericTypeDescriptor.registerReference();
typeArguments.add(genericTypeDescriptor);
// main type
boolean showLink = type.areReferencesShown();
- if (type == parentClassDescriptior)
+ if (type == parentClassDescriptor)
showLink = false;
- if (parentClassDescriptior.isEnum)
+ if (parentClassDescriptor.isEnum)
showLink = false;
if (showLink)
final StringBuffer result = new StringBuffer();
result.append(" // " + name + "\n");
- if (parentClassDescriptior.isEnum && (type == parentClassDescriptior)) {
+ if (parentClassDescriptor.isEnum && (type == parentClassDescriptor)) {
result.append(" <TR><TD colspan=\"2\" PORT=\"" + name);
result.append("\" ALIGN=\"left\"><FONT POINT-SIZE=\"11.0\">");
result.append(name + "</FONT></TD></TR>\n");
@Override
public String getGraphId() {
- return parentClassDescriptior.getGraphId() + ":" + name;
+ return parentClassDescriptor.getGraphId() + ":" + name;
}
protected int getOutsideVisibleReferencesCount() {