All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.subchen.maven.plugin.javafmt.JavaFormatterMojo Maven / Gradle / Ivy
/**
* Copyright 2018-2019 Guoqiang Chen, Shanghai, China. All rights reserved.
*
* Author: Guoqiang Chen
* Email: [email protected]
* WebURL: https://github.com/subchen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.subchen.maven.plugin.javafmt;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.val;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.components.io.fileselectors.FileSelector;
import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
import org.codehaus.plexus.components.io.resources.PlexusIoFileResource;
import org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Java Formatter for maven plugin
*
* @author guoqiang.chen
*/
@Mojo(name = "format", defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true)
public final class JavaFormatterMojo extends AbstractMojo {
private static final String[] DEFAULT_INCLUDES = new String[] { "**/*.java" };
private static final String[] DEFAULT_EXCLUDES = new String[] { "**/generated/**" };
private static final String MD5_CACHE_FILENAME = "java-formatter-cache.md5";
/**
* Project's base directory.
*/
@Parameter(property = "basedir", defaultValue = "${basedir}", readonly = true)
private File basedir;
/**
* Project's target directory as specified in the POM.
*/
@Parameter(property = "targetDirectory", defaultValue = "${project.build.directory}", readonly = true)
private File targetDirectory;
/**
* The file encoding used to read and write source files. When not specified and
* sourceEncoding also not set, default is platform file encoding.
*/
@Parameter(property = "sourceEncoding", defaultValue = "${project.build.sourceEncoding}")
private String sourceEncoding;
/**
* Java compiler source version.
*/
@Parameter(property = "compilerSource", defaultValue = "${maven.compiler.source}")
private String compilerSource;
@Override
public void execute() {
long startClock = System.currentTimeMillis();
val fileList = collectJavaSourceFileList();
if (fileList.isEmpty()) {
getLog().info("No java source found");
return;
}
val md5Cache = loadMd5Cache();
val javaFormatter = new JavaFormatter(basedir, compilerSource);
val rc = new ResultCollector();
fileList.forEach(file -> {
val originalCode = readFileToString(file, Charset.forName(sourceEncoding));
val originalMd5 = DigestUtils.md5Hex(originalCode);
if (md5Cache.contains(originalMd5)) {
rc.skippedCount.increment();
return;
}
// format
String formattedCode;
try {
formattedCode = javaFormatter.format(originalCode);
} catch (Exception e) {
getLog().warn("Code cannot be formatted: " + file, e);
rc.failCount.increment();
return;
}
val formattedMd5 = DigestUtils.md5Hex(formattedCode);
// update cache
md5Cache.add(formattedMd5);
if (Objects.equals(formattedMd5, originalMd5)) {
rc.skippedCount.increment();
return;
}
writeStringToFile(file, formattedCode, Charset.forName(sourceEncoding));
rc.successCount.increment();
});
if (rc.successCount.intValue() > 0) {
saveMd5Cache(md5Cache);
}
getLog().info("Successfully formatted: " + rc.successCount.intValue() + " file(s)");
getLog().info("Fail to format : " + rc.failCount.intValue() + " file(s)");
getLog().info("Skipped : " + rc.skippedCount.intValue() + " file(s)");
getLog().info("Approximate time taken: " + ((System.currentTimeMillis() - startClock) / 1000) + " (s)");
}
@SneakyThrows
private List collectJavaSourceFileList() {
val search = new PlexusIoFileResourceCollection();
// includes & excludes
search.setIncludingEmptyDirectories(false);
search.setIncludes(DEFAULT_INCLUDES);
search.setExcludes(DEFAULT_EXCLUDES);
IncludeExcludeFileSelector fileSelector = new IncludeExcludeFileSelector();
fileSelector.setIncludes(DEFAULT_INCLUDES);
fileSelector.setExcludes(DEFAULT_EXCLUDES);
search.setFileSelectors(new FileSelector[] { fileSelector });
// source base dir
search.setBaseDir(new File(basedir, "src"));
// get search results
val resources = search.getResources();
val files = new ArrayList(128);
while (resources.hasNext()) {
val resource = (PlexusIoFileResource) resources.next();
files.add(resource.getFile());
}
getLog().info("Number of files to be formatted: " + files.size());
return files;
}
private Set loadMd5Cache() {
val file = new File(targetDirectory, MD5_CACHE_FILENAME);
if (!file.exists()) {
return new HashSet<>(128);
}
val lines = readFileToString(file, StandardCharsets.UTF_8);
return Stream.of(lines.split("\n")).collect(Collectors.toSet());
}
@SneakyThrows
private void saveMd5Cache(Set md5Cache) {
val file = new File(targetDirectory, MD5_CACHE_FILENAME);
val lines = String.join("\n", md5Cache);
writeStringToFile(file, lines, StandardCharsets.UTF_8);
}
@SneakyThrows
private static String readFileToString(File file, Charset encoding) {
return FileUtils.readFileToString(file, encoding);
}
@SneakyThrows
private static void writeStringToFile(File file, String data, Charset encoding) {
FileUtils.writeStringToFile(file, data, encoding);
}
@Getter
static class ResultCollector {
final MutableInt skippedCount = new MutableInt();
final MutableInt successCount = new MutableInt();
final MutableInt failCount = new MutableInt();
}
}