Skip to content

Commit

Permalink
Issue checkstyle#37: inject, invoke maven command, read file and clea…
Browse files Browse the repository at this point in the history
…n up
  • Loading branch information
Luolc committed Jul 13, 2017
1 parent 000ef03 commit 241fa66
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 15 deletions.
5 changes: 4 additions & 1 deletion config/findbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
<Match>
<!-- This is a false positive. It is no problem to do that cast. In fact the cast is
in JGit library. There is no reason to raise this warning. -->
<Class name="com.github.checkstyle.regression.git.DiffParser"/>
<Or>
<Class name="com.github.checkstyle.regression.git.DiffParser"/>
<Class name="com.github.checkstyle.regression.extract.CheckstyleInjector"/>
</Or>
<Or>
<Bug pattern="BC_UNCONFIRMED_CAST"/>
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/>
Expand Down
6 changes: 5 additions & 1 deletion config/import-control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<import-control pkg="com.github.checkstyle.regression">
<allow pkg="java.io"/>
<allow pkg="java.nio"/>
<allow pkg="org.apache.commons.io"/>
<allow pkg="java.util"/>
<allow pkg="com.github.checkstyle.regression.data"/>
<allow pkg="org.immutables.value"/>
Expand All @@ -13,7 +15,6 @@
<allow pkg="javax.xml"/>
<allow pkg="org.w3c.dom"/>
<allow pkg="org.xml"/>
<allow pkg="java.nio"/>
</subpackage>

<subpackage name="data">
Expand All @@ -24,6 +25,9 @@
<subpackage name="extract">
<allow pkg="com.google.gson"/>
<allow class="java.lang.reflect.Type"/>
<allow pkg="org.apache.maven.shared.invoker"/>
<!-- we need to run Git checkout command. -->
<allow pkg="org.eclipse.jgit"/>
</subpackage>

<subpackage name="git">
Expand Down
22 changes: 21 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<artifactId>maven-jxr</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-invoker</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -288,7 +293,22 @@
<regex>
<pattern>com.github.checkstyle.regression.configuration.ConfigGenerator</pattern>
<branchRate>80</branchRate>
<lineRate>91</lineRate>
<lineRate>92</lineRate>
</regex>
<regex>
<pattern>com.github.checkstyle.regression.extract.ExtractInfoProcessor</pattern>
<branchRate>100</branchRate>
<lineRate>60</lineRate>
</regex>
<regex>
<pattern>com.github.checkstyle.regression.extract.CheckstyleInjector.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>com.github.checkstyle.regression.extract.InjectException</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>com.github.checkstyle.regression.module.ModuleUtils</pattern>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

package com.github.checkstyle.regression.extract;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import org.apache.commons.io.FileUtils;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.MavenInvocationException;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;

/**
* Injects files to checkstyle repository, which would be invoked by maven command
* to generate module extract info.
* @author LuoLiangchen
*/
final class CheckstyleInjector implements Closeable {
/** The path to checkstyle repository. */
private final String repoPath;

/** The name of PR branch. */
private final String branch;

/** The checkstyle repository. */
private final Repository repository;

/**
* Creates a new instance of CheckstyleInjector.
* @param repoPath the path to checkstyle repository
* @param branch the name of PR branch
*/
CheckstyleInjector(String repoPath, String branch) {
this.repoPath = repoPath;
this.branch = branch;

final File gitDir = new File(repoPath, ".git");
final Repository repo;
try {
repo = new FileRepositoryBuilder().setGitDir(gitDir)
.readEnvironment().findGitDir().build();
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
repository = repo;
}

/**
* Generates the module extract info file.
* @return the module extract info file
* @throws InjectException failure of generation
*/
public File generateExtractInfoFile() throws InjectException {
try {
checkoutToPrBranch();
copyInjectFilesToCheckstyleRepo();
invokeMavenCommand();
return new File(repoPath, "checkstyle_modules.json");
}
catch (IOException | GitAPIException ex) {
throw new InjectException("unable to generate extract info file", ex);
}
}

/**
* Clears the injected files and the generated info file in checkstyle repository.
* @throws InjectException failure of clearing
*/
public void clearInjections() throws InjectException {
final Git git = new Git(repository);

try {
git.clean().setCleanDirectories(true).call();
}
catch (GitAPIException ex) {
throw new InjectException("unable to clear injections", ex);
}
finally {
git.close();
}
}

/** Closes the repository resource. */
@Override
public void close() {
repository.close();
}

/**
* Invokes Maven command to generate the extract info file in checkstyle repository.
* @throws InjectException failure of invoking Maven
*/
private void invokeMavenCommand() throws InjectException {
final InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile(new File(repoPath, "pom.xml"));
request.setGoals(Arrays.asList(
"test", "-Dtest=ExtractInfoGeneratorTest#generateExtractInfoFile"));
final Invoker invoker = new DefaultInvoker();
try {
final InvocationResult result = invoker.execute(request);
if (result.getExitCode() != 0) {
throw new InjectException("maven process exit with code: " + result.getExitCode());
}
}
catch (MavenInvocationException ex) {
throw new InjectException("maven invocation failed", ex);
}
}

/**
* Copies the injection files to checkstyle repository.
* @throws IOException failure of copying
*/
private void copyInjectFilesToCheckstyleRepo() throws IOException {
final File srcDir =
new File("src/main/resources/com/github/checkstyle/regression/extract/");
final File destDir = new File(repoPath, "src/test/java/com/puppycrawl/tools/checkstyle/");
final String[] injections = {"ExtractInfoGeneratorTest.java", "JsonUtil.java"};
for (String injection : injections) {
final File srcFile = new File(srcDir, injection);
final File destFile = new File(destDir, injection);
FileUtils.copyFile(srcFile, destFile);
}
}

/**
* Checkouts to the PR branch in the given repository.
* @throws GitAPIException JGit library exception
*/
private void checkoutToPrBranch()
throws GitAPIException {
final Git git = new Git(repository);

try {
git.checkout().setName(branch).call();
}
finally {
git.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@

package com.github.checkstyle.regression.extract;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
Expand Down Expand Up @@ -57,13 +62,48 @@ private ExtractInfoProcessor() {
GSON = gsonBuilder.create();
}

/**
* Gets the module extract info map from the given branch of checkstyle repository.
* @param repoPath the path of checkstyle repository
* @param branch the given branch on which to generate the extract info
* @return the full qualified name to module extract info map
* @throws InjectException failure when making injection
*/
public static Map<String, ModuleExtractInfo> getModuleExtractInfos(
String repoPath, String branch) throws InjectException {
final Map<String, ModuleExtractInfo> returnValue;
final CheckstyleInjector injector = new CheckstyleInjector(repoPath, branch);

try {
final File file = injector.generateExtractInfoFile();

try {
final Reader reader = new InputStreamReader(
new FileInputStream(file), Charset.forName("UTF-8"));
returnValue = getModuleExtractInfosFromReader(reader);
}
catch (FileNotFoundException ex) {
throw new InjectException(
"unable to find the generated module extract info file", ex);
}
finally {
injector.clearInjections();
}
}
finally {
injector.close();
}

return returnValue;
}

/**
* Gets the module extract info map from the given reader. Map key is the
* fully qualified module name.
* @param reader the given reader
* @return the full qualified name to module extract info map
*/
public static Map<String, ModuleExtractInfo> getModuleExtractInfosFromReader(
private static Map<String, ModuleExtractInfo> getModuleExtractInfosFromReader(
Reader reader) {
final List<ModuleExtractInfo> modules;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

package com.github.checkstyle.regression.extract;

/**
* Signals that an exception occurs when injecting.
* The cause could be a Git exception, IO exception of creating/copying/reading operation
* or non-zero exit code of Maven result.
* @author LuoLiangchen
*/
public class InjectException extends Exception {
private static final long serialVersionUID = 1042082793270688141L;

/**
* Constructs an InjectException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
* @param message the String that contains a detailed message
*/
public InjectException(String message) {
super(message);
}

/**
* Constructs a new exception with the specified detail message and cause.
* @param message the detail message (which is saved for later retrieval
* by the {@link Throwable#getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method). (A <tt>null</tt> value
* is permitted, and indicates that the cause is nonexistent or
* unknown.)
*/
public InjectException(String message, Throwable cause) {
super(message, cause);
}
}
Loading

0 comments on commit 241fa66

Please sign in to comment.