From 4f3044fec87a93d74356c457ccb920eb9225673c Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Fri, 1 Dec 2017 12:25:09 +0100 Subject: [PATCH] logic: implemented using .aar files as Java project dependencies --- .../java/com/sourcetrail/JavaIndexer.java | 134 +++++++++++++----- .../main/java/com/sourcetrail/Utility.java | 7 + 2 files changed, 103 insertions(+), 38 deletions(-) diff --git a/java_indexer/src/main/java/com/sourcetrail/JavaIndexer.java b/java_indexer/src/main/java/com/sourcetrail/JavaIndexer.java index 4c21079c..bc620adf 100644 --- a/java_indexer/src/main/java/com/sourcetrail/JavaIndexer.java +++ b/java_indexer/src/main/java/com/sourcetrail/JavaIndexer.java @@ -1,5 +1,10 @@ package com.sourcetrail; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Path; @@ -7,6 +12,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; @@ -39,44 +46,16 @@ public class JavaIndexer parser.setResolveBindings(true); // solve "bindings" like the declatarion of the type used in a var decl parser.setKind(ASTParser.K_COMPILATION_UNIT); // specify to parse the entire compilation unit parser.setBindingsRecovery(true); // also return bindings that are not resolved completely - parser.setStatementsRecovery(true); + parser.setStatementsRecovery(true); - Hashtable options = JavaCore.getOptions(); - - String convertedLanguageStandard; - switch (languageStandard) - { - case "1": - convertedLanguageStandard = JavaCore.VERSION_1_1; - break; - case "2": - convertedLanguageStandard = JavaCore.VERSION_1_2; - break; - case "3": - convertedLanguageStandard = JavaCore.VERSION_1_3; - break; - case "4": - convertedLanguageStandard = JavaCore.VERSION_1_4; - break; - case "5": - convertedLanguageStandard = JavaCore.VERSION_1_5; - break; - case "6": - convertedLanguageStandard = JavaCore.VERSION_1_6; - break; - case "7": - convertedLanguageStandard = JavaCore.VERSION_1_7; - break; - case "8": - default: - convertedLanguageStandard = JavaCore.VERSION_1_8; - break; - } - - astVisitorClient.logInfo("using language standard " + convertedLanguageStandard); - - JavaCore.setComplianceOptions(convertedLanguageStandard, options); - parser.setCompilerOptions(options); + { + Hashtable options = JavaCore.getOptions(); + + String convertedLanguageStandard = convertLanguageStandard(languageStandard); + astVisitorClient.logInfo("using language standard " + convertedLanguageStandard); + JavaCore.setComplianceOptions(convertedLanguageStandard, options); + parser.setCompilerOptions(options); + } parser.setUnitName(path.getFileName().toString()); @@ -89,6 +68,14 @@ public class JavaIndexer { classpath.add(classPathEntry); } + else if(classPathEntry.endsWith(".aar")) + { + File extractedJarFile = extractClassesJarFileFromAarFile(Paths.get(classPathEntry), astVisitorClient); + if (extractedJarFile != null) + { + classpath.add(extractedJarFile.getAbsolutePath()); + } + } else if (!classPathEntry.isEmpty()) { sources.add(classPathEntry); @@ -164,8 +151,79 @@ public class JavaIndexer Runtime.getRuntime().gc(); } + private static String convertLanguageStandard(String s) + { + switch (s) + { + case "1": + return JavaCore.VERSION_1_1; + case "2": + return JavaCore.VERSION_1_2; + case "3": + return JavaCore.VERSION_1_3; + case "4": + return JavaCore.VERSION_1_4; + case "5": + return JavaCore.VERSION_1_5; + case "6": + return JavaCore.VERSION_1_6; + case "7": + return JavaCore.VERSION_1_7; + case "8": + default: + return JavaCore.VERSION_1_8; + } + } - + private static File extractClassesJarFileFromAarFile(Path aarFilePath, AstVisitorClient astVisitorClient) throws IOException + { + JarFile jarFile = new JarFile(aarFilePath.toString()); + ZipEntry classesJarEntry = jarFile.getEntry("classes.jar"); + if (classesJarEntry != null) + { + InputStream inputStream = jarFile.getInputStream(classesJarEntry); + File tempFile = File.createTempFile("jar_file_from_" + Utility.getFilenameWithoutExtension(aarFilePath) + "_", ".jar"); + tempFile.deleteOnExit(); + + byte[] buffer = new byte[8 * 1024]; + + try + { + OutputStream output = new FileOutputStream(tempFile); + try + { + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) + { + output.write(buffer, 0, bytesRead); + } + } + finally + { + output.close(); + } + } + finally + { + inputStream.close(); + } + + astVisitorClient.logInfo( + "Extracted classes.jar file from \"" + aarFilePath.toString() + "\" to \"" + tempFile.getAbsolutePath() + "\". " + + "This file will be automatically deleted when the session ends." + ); + + return tempFile; + } + else + { + astVisitorClient.logError("Classpath entry \"" + aarFilePath + "\" is malformed. No internal \"classes.jar\" entry could be found."); + } + jarFile.close(); + + return null; + } + // the following methods are defined in the native c++ code static public native boolean getInterrupted(int address); diff --git a/java_indexer/src/main/java/com/sourcetrail/Utility.java b/java_indexer/src/main/java/com/sourcetrail/Utility.java index f657ae70..e37ed717 100644 --- a/java_indexer/src/main/java/com/sourcetrail/Utility.java +++ b/java_indexer/src/main/java/com/sourcetrail/Utility.java @@ -1,5 +1,7 @@ package com.sourcetrail; +import java.nio.file.Path; + import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; @@ -24,4 +26,9 @@ public class Utility compilationUnit.getLineNumber(endPosition), compilationUnit.getColumnNumber(endPosition) + 1); } + + public static String getFilenameWithoutExtension(Path filePath) + { + return filePath.getFileName().toString().replaceFirst("[.][^.]+$", ""); + } }