Skip to content

Tutorial 10. ProjectService Explained

Linghui Luo edited this page Jun 1, 2020 · 3 revisions

The idea behind a ProjectService is to provide a reusable service that provides frequently used methods for a certain project type. Typically a ProjectService provides these services for a specific language.

Currently MagpieBridge already provides an AndroidProjectService and a JavaProjectService that can automatically determine the ProjectType (Maven, Gradle, Bazel, EclipseJava) by searching and processing the configuration files for these types of projects. Furthermore, it can determine the classPath and libraryPath that are determined by the project type and the dependencies defined in the configuration files (e.g. pom.xml, build.gradle, .classpath).

This project service can be provided to your analysis by passing it to the MagpieServer instance:

  MagpieServer server = ...
  server.addProjectService("java", new JavaProjectService());

and can be retrieved by your analysis by calling

   server.getProjectService("java");

Life-Cycle

When the MagpieServer instance is initialized with information about the project by the client, it will call the method setRootPath(Path rootPath) for every project service registered via addProjectService.

Provide your own Project Service

To show you how you can provide your own project service, we will go through the process of creating a new ProjectService for an entirely different language:

Example NpmProjectService

We want to create a service, that can determine the dependency structure for npm projects. To start, we will try to determine, if the current project contains a package.json:

 if (Files.exists(rootPath) && Files.isDirectory(rootPath)) {
   Path packageJsonPath = path.resolve("package.json");
   if (Files.exists(packageJsonPath)) {
     this.packageJson = Optional.of(packageJsonPath);
   }
}

Then we will check if the dependeny folder exists:

 if (Files.exists(rootPath) && Files.isDirectory(rootPath)) {
   ...
   Path node_modules = path.resolve("node_modules");
   if (Files.exists(node_modules)) {
     dependencyPath = Optional.of(node_modules);
   }
}

Once we have determined these paths, we can offer the following services:

Service-Method Description
Optional<Path> getPackageJson() Path to the package.json if it exists
Optional<NpmPackage> getProjectPackage() Information about the project parsed from the package.json
Optional<Path> getDependencyPath() Path to the node_modules folder
Optional<NpmPackage> getDependency(String name) resolves a single dependency if it exists
List<NpmPackage> getDependencies() lists all dependencies (including transient dependencies)
Optional<List<NpmPackage>> getDirectDependencies() lists all direct dependencies (excluding transient dependencies)

The finished NpmProjectService can be found here.

Clone this wiki locally