Added all important commandline options. Updated documentation.
[javainspect.git] / src / main / java / eu / svjatoslav / inspector / java / Main.java
index f57f787..9b706d3 100644 (file)
 package eu.svjatoslav.inspector.java;
 
+import eu.svjatoslav.inspector.java.commandline.CommandlineConfiguration;
 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) {
-               if (args.length == 0) {
-                       System.err.println("usage: javainspect [PROJECT_DIR] [PACKAGE_GLOB] [GRAPH_NAME]");
-                       System.exit(1);
-               }
-
-               String projectDir  = args[0];
-               String packageGlob = args[1];
-               String graphName   = args[2];
-
-               ClassGraph cg = new ClassGraph();
-               cg.setTargetDirectoryPath(getProperty("user.dir") + separator);
-
-               cg.addProject(projectDir);
-               cg.whitelistClassPattern(packageGlob);
-               cg.setKeepDotFile(true);
-               cg.generateGraph(graphName);
-
-               System.exit(0);
-       }
+    public static void main(String[] args) throws IOException, ClassNotFoundException {
+        CommandlineConfiguration configuration = new CommandlineConfiguration(args);
+        if (!configuration.configurationOk)
+            System.exit(1);
+            
+        getClassGraph(configuration).generateGraph(configuration.graphName.getValue());
+
+        if (configuration.isDebug())
+            System.out.println("Graph ready.");
+    }
+
+    private static ClassGraph getClassGraph(CommandlineConfiguration configuration) throws IOException, ClassNotFoundException {
+        List<File> jarFiles = configuration.jarFiles.getValue();
+
+        URLClassLoader classLoader = new URLClassLoader(
+                getFileUrls(jarFiles),
+                configuration.getClass().getClassLoader());
+
+        ClassGraph classGraph = new ClassGraph();
+
+        classGraph.setTargetDirectory(getTargetDirectory(configuration));
+
+        if (configuration.targetImageType.isSpecified())
+            classGraph.setTargetImageType(configuration.targetImageType.getValue());
+
+        classGraph.setKeepDotFile(configuration.keepDotFile.getValue());
+
+        for (File jarFile : jarFiles)
+            addJarToGraph(jarFile, classLoader, classGraph, configuration);
+
+        configuration.blacklistGlob.getValue().forEach(classGraph::blacklistClassGlob);
+        configuration.whitelistGlob.getValue().forEach(classGraph::whitelistClassGlob);
+
+        if (configuration.hideOrphanedClasses.getValue())
+            classGraph.hideOrphanedClasses();
+
+        return classGraph;
+    }
+
+    private static File getTargetDirectory(CommandlineConfiguration configuration) {
+        if (configuration.targetDirectory.isSpecified())
+            return configuration.targetDirectory.getValue();
+
+        // default to current directory
+        return new File(getProperty("user.dir") + separator);
+    }
+
+    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('.'));
+    }
 }