Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions src/main/java/com/ibm/northstar/SymbolTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.javaparser.ParseResult;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.Problem;
import com.github.javaparser.ast.AccessSpecifier;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
Expand All @@ -12,6 +13,7 @@
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.type.ReferenceType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.github.javaparser.resolution.types.ResolvedType;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
Expand Down Expand Up @@ -498,12 +500,21 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
Log.debug("Could not resolve method call: " + methodCallExpr + ": " + exception.getMessage());
}

// Resolve access qualifier
AccessSpecifier accessSpecifier = AccessSpecifier.NONE;
try {
ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
accessSpecifier = resolvedMethodDeclaration.accessSpecifier();
}
catch (RuntimeException exception) {
Log.debug("Could not resolve access specifier for method call: " + methodCallExpr + ": " + exception.getMessage());
}
// resolve arguments of the method call to types
List<String> arguments = methodCallExpr.getArguments().stream()
.map(SymbolTable::resolveExpression).collect(Collectors.toList());
// add a new call site object
callSites.add(createCallSite(methodCallExpr, methodCallExpr.getNameAsString(), receiverName, declaringType,
arguments, returnType, calleeSignature, isStaticCall, false));
arguments, returnType, calleeSignature, isStaticCall, false, accessSpecifier));
}

for (ObjectCreationExpr objectCreationExpr : callableBody.get().findAll(ObjectCreationExpr.class)) {
Expand All @@ -525,7 +536,7 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
// add a new call site object
callSites.add(createCallSite(objectCreationExpr, "<init>",
objectCreationExpr.getScope().isPresent() ? objectCreationExpr.getScope().get().toString() : "",
instantiatedType, arguments, instantiatedType, calleeSignature,false, true));
instantiatedType, arguments, instantiatedType, calleeSignature,false, true, AccessSpecifier.NONE));
}

return callSites;
Expand All @@ -546,7 +557,7 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
*/
private static CallSite createCallSite(Expression callExpr, String calleeName, String receiverExpr,
String receiverType, List<String> arguments, String returnType,
String calleeSignature, boolean isStaticCall, boolean isConstructorCall) {
String calleeSignature, boolean isStaticCall, boolean isConstructorCall, AccessSpecifier accessSpecifier) {
CallSite callSite = new CallSite();
callSite.setMethodName(calleeName);
callSite.setReceiverExpr(receiverExpr);
Expand All @@ -556,6 +567,10 @@ private static CallSite createCallSite(Expression callExpr, String calleeName, S
callSite.setCalleeSignature(calleeSignature);
callSite.setStaticCall(isStaticCall);
callSite.setConstructorCall(isConstructorCall);
callSite.setPrivate(accessSpecifier.equals(AccessSpecifier.PRIVATE));
callSite.setPublic(accessSpecifier.equals(AccessSpecifier.PUBLIC));
callSite.setProtected(accessSpecifier.equals(AccessSpecifier.PROTECTED));
callSite.setUnspecified(accessSpecifier.equals(AccessSpecifier.NONE));
if (callExpr.getRange().isPresent()) {
callSite.setStartLine(callExpr.getRange().get().begin.line);
callSite.setStartColumn(callExpr.getRange().get().begin.column);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/ibm/northstar/entities/CallSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public class CallSite {
private List<String> argumentTypes;
private String returnType;
private String calleeSignature;
// Access specifiers
private boolean isPublic = false;
private boolean isProtected = false;
private boolean isPrivate = false;
private boolean isUnspecified = false;
private boolean isStaticCall;
private boolean isConstructorCall;
private int startLine;
Expand Down
71 changes: 54 additions & 17 deletions src/main/java/com/ibm/northstar/utils/BuildProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

import static com.ibm.northstar.utils.ProjectDirectoryScanner.classFilesStream;
Expand All @@ -17,6 +18,31 @@ public class BuildProject {
private static final String LIB_DEPS_DOWNLOAD_DIR = "_library_dependencies";
private static final String MAVEN_CMD = System.getProperty("os.name").toLowerCase().contains("windows") ? "mvn.cmd" : "mvn";
private static final String GRADLE_CMD = System.getProperty("os.name").toLowerCase().contains("windows") ? "gradlew.bat" : "gradlew";
public static Path tempInitScript;
static {
try {
tempInitScript = Files.createTempFile("gradle-init-", ".gradle");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static final String GRADLE_DEPENDENCIES_TASK = "allprojects { afterEvaluate { project -> task downloadDependencies(type: Copy) {\n" +
" def configs = project.configurations.findAll { it.canBeResolved }\n\n" +
" dependsOn configs\n" +
" from configs\n" +
" into project.hasProperty('outputDir') ? project.property('outputDir') : \"${project.buildDir}/libs\"\n\n" +
" doFirst {\n" +
" println \"Downloading dependencies for project ${project.name} to: ${destinationDir}\"\n" +
" configs.each { config ->\n" +
" println \"Configuration: ${config.name}\"\n" +
" config.resolvedConfiguration.resolvedArtifacts.each { artifact ->\n" +
" println \"\t${artifact.moduleVersion.id}:${artifact.extension}\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";

private static boolean buildWithTool(String[] buildCommand) {
Log.info("Building the project using " + buildCommand[0] + ".");
Expand All @@ -30,6 +56,7 @@ private static boolean buildWithTool(String[] buildCommand) {
Log.info(line);
}
int exitCode = process.waitFor();
process.getErrorStream().transferTo(System.err);
Log.info(buildCommand[0].toUpperCase() + " build exited with code " + exitCode);
return exitCode == 0;
} catch (IOException | InterruptedException e) {
Expand Down Expand Up @@ -73,24 +100,24 @@ private static boolean mavenBuild(String projectPath) {
return false;
}
String[] mavenCommand = {
MAVEN_CMD, "clean", "compile", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", "-Drat.skip",
"-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip",
"-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true",
"-Drat.skip=true", "-Dspotless.check.skip=true" };
MAVEN_CMD, "clean", "compile", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", "-Drat.skip",
"-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip",
"-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true",
"-Drat.skip=true", "-Dspotless.check.skip=true"};

return buildWithTool(mavenCommand);
}

public static boolean gradleBuild(String projectPath) {
// Adjust Gradle command as needed
String gradleWrapper = projectPath + File.separator + GRADLE_CMD;
String[] gradleCommand = { gradleWrapper, "clean", "compileJava", "-p", projectPath };
String[] gradleCommand = {gradleWrapper, "clean", "compileJava", "-p", projectPath};
return buildWithTool(gradleCommand);
}

private static boolean buildProject(String projectPath, String build) {
File pomFile = new File(projectPath, "pom.xml");
if (build ==null) {
if (build == null) {
return true;
} else if (build.equals("auto")) {
if (pomFile.exists()) {
Expand All @@ -100,8 +127,7 @@ private static boolean buildProject(String projectPath, String build) {
Log.info("Did not find a pom.xml in the project directory. Using Gradle to build the project.");
return gradleBuild(projectPath); // Otherwise, use Gradle
}
}
else {
} else {
// Update command with a project path
build = build.replace(MAVEN_CMD, MAVEN_CMD + " -f " + projectPath);
Log.info("Using custom build command: " + build);
Expand All @@ -127,31 +153,35 @@ public static List<Path> buildProjectAndStreamClassFiles(String projectPath, Str
* @param projectPath Path to the project under analysis
* @return true if dependency download succeeds; false otherwise
*/
public static boolean downloadLibraryDependencies(String projectPath) {
public static boolean downloadLibraryDependencies(String projectPath) throws IOException {
// created download dir if it does not exist
libDownloadPath = Paths.get(projectPath, LIB_DEPS_DOWNLOAD_DIR).toAbsolutePath();
if (!Files.exists(libDownloadPath)) {
try {
Files.createDirectory(libDownloadPath);
} catch (IOException e) {
Log.error("Error creating library dependency directory for " + projectPath + ": " +e.getMessage());
Log.error("Error creating library dependency directory for " + projectPath + ": " + e.getMessage());
return false;
}
}
File pomFile = new File(projectPath, "pom.xml");
if (pomFile.exists()) {
Log.info("Found pom.xml in the project directory. Using Maven to download dependencies.");
String[] mavenCommand = {
MAVEN_CMD, "--no-transfer-progress", "-f",
Paths.get(projectPath, "pom.xml").toString(),
"dependency:copy-dependencies",
"-DoutputDirectory=" + libDownloadPath.toString()
MAVEN_CMD, "--no-transfer-progress", "-f",
Paths.get(projectPath, "pom.xml").toString(),
"dependency:copy-dependencies",
"-DoutputDirectory=" + libDownloadPath.toString()
};
return buildWithTool(mavenCommand);
} else {
// TODO: implement for gradle
return false;
} else if (new File(projectPath, "build.gradle").exists() || new File(projectPath, "build.gradle.kts").exists()) {
Log.info("Found build.gradle[.kts] in the project directory. Using Gradle to download dependencies.");
tempInitScript = Files.writeString(tempInitScript, GRADLE_DEPENDENCIES_TASK);
String[] gradleCommand = {projectPath + File.separator + GRADLE_CMD, "--init-script", tempInitScript.toFile().getAbsolutePath(), "downloadDependencies", "-PoutputDir="+libDownloadPath.toString()};
System.out.println(Arrays.toString(gradleCommand));
return buildWithTool(gradleCommand);
}
return false;
}

public static void cleanLibraryDependencies() {
Expand All @@ -167,5 +197,12 @@ public static void cleanLibraryDependencies() {
Log.error("Error deleting library dependency directory: " + e.getMessage());
}
}
if (tempInitScript != null) {
try {
Files.delete(tempInitScript);
} catch (IOException e) {
Log.error("Error deleting temporary Gradle init script: " + e.getMessage());
}
}
}
}