1 package eu.svjatoslav.inspector.java.commandline;
3 import eu.svjatoslav.inspector.java.structure.ClassGraph;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.net.MalformedURLException;
10 import java.net.URLClassLoader;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.jar.JarEntry;
14 import java.util.jar.JarInputStream;
17 * This class acts as a commandline interface for JavaInspect.
20 public static void main(String[] args) throws IOException, ClassNotFoundException {
21 CommandlineConfiguration configuration = new CommandlineConfiguration(args);
22 if (!configuration.configurationOk)
25 getClassGraph(configuration).generateGraph(configuration.graphName.getValue());
27 if (configuration.isDebug())
28 System.out.println("Graph ready.");
31 private static ClassGraph getClassGraph(CommandlineConfiguration configuration) throws IOException, ClassNotFoundException {
32 List<File> jarFiles = configuration.jarFiles.getValue();
34 URLClassLoader classLoader = new URLClassLoader(
35 getFileUrls(jarFiles),
36 configuration.getClass().getClassLoader());
38 ClassGraph classGraph = new ClassGraph();
40 if (configuration.targetDirectory.isSpecified())
41 classGraph.setTargetDirectory(configuration.targetDirectory.getValue());
43 if (configuration.targetImageType.isSpecified())
44 classGraph.setTargetImageType(configuration.targetImageType.getValue());
46 classGraph.setKeepDotFile(configuration.keepDotFile.getValue());
48 if (configuration.rootClasses.isSpecified()){
49 // add only selected root classes
50 for (String rootClass : configuration.rootClasses.getValue())
51 attemptClassAdditionByName(classLoader, classGraph, configuration, rootClass);
54 // add all classes in the jar files to graph
55 for (File jarFile : jarFiles)
56 addJarToGraph(jarFile, classLoader, classGraph, configuration);
58 configuration.blacklistGlob.getValue().forEach(classGraph::blacklistClassGlob);
59 configuration.whitelistGlob.getValue().forEach(classGraph::whitelistClassGlob);
61 if (configuration.hideOrphanedClasses.getValue())
62 classGraph.hideOrphanedClasses();
67 private static URL[] getFileUrls(List<File> jarFiles) {
68 List<URL> urls = new ArrayList<>();
69 jarFiles.forEach((File file) -> {
71 urls.add(file.toURI().toURL());
72 } catch (MalformedURLException e) {
73 throw new RuntimeException(e);
77 return urls.toArray(new URL[urls.size()]);
80 private static void addJarToGraph(
81 File jarFile, URLClassLoader classLoader, ClassGraph classGraph, CommandlineConfiguration configuration)
82 throws IOException, ClassNotFoundException {
84 for (String className : getClassNamesFromJar(jarFile))
85 attemptClassAdditionByName(classLoader, classGraph, configuration, className);
88 private static void attemptClassAdditionByName(URLClassLoader classLoader, ClassGraph classGraph, CommandlineConfiguration configuration, String className) throws ClassNotFoundException {
89 if (configuration.isDebug())
90 System.out.println("Adding class to graph: " + className);
92 classGraph.add(loadClassByName(classLoader, className));
93 } catch (NoClassDefFoundError e){
94 if (configuration.isDebug())
95 System.out.println("Class definition was not found.");
96 // Sometimes referenced classes are not found in the same Jar.
97 // Let's ignore this and proceed with the classes that we have.
101 private static Class loadClassByName(URLClassLoader classLoader, String className) throws ClassNotFoundException {
102 return Class.forName(className, true, classLoader);
105 public static List<String> getClassNamesFromJar(File jarFile) throws IOException {
106 List<String> result = new ArrayList<>();
108 JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile))
111 JarEntry jarEntry = jarInputStream.getNextJarEntry();
112 if (jarEntry == null)
115 if (isClassFile(jarEntry))
116 result.add(getClassNameFromFileName(jarEntry));
123 private static boolean isClassFile(JarEntry jarEntry) {
124 return jarEntry.getName().endsWith(".class");
127 private static String getClassNameFromFileName(JarEntry jarEntry) {
128 String result = jarEntry.getName().replaceAll("/", "\\.");
129 return result.substring(0, result.lastIndexOf('.'));