aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGautam Shah <gautams@amdocs.com>2018-06-05 18:50:13 +0530
committerAvi Gaffa <avi.gaffa@amdocs.com>2018-06-06 06:27:18 +0000
commit719e3bb7d4f6b31c178abaeff9b8124ce7703662 (patch)
treedb69388be45dfb58c781f78c9907ae1b4ca2d9ed
parent16ecda5c6ebb673636e7c74e5501f9f2c8ae00b0 (diff)
Onboarding backend build optimization.
Enhancing Test RUN/NO-RUN Logic, adding identifiers for local build state repo Change-Id: Ie0a541f216c16ddc40605111981d7a2fa045c39d Issue-ID: SDC-1189 Signed-off-by: GAUTAMS <gautams@amdocs.com>
-rw-r--r--onboarding/pom.xml1
-rw-r--r--openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java5
-rw-r--r--openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java7
-rw-r--r--openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java24
-rw-r--r--openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java15
-rw-r--r--openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java16
-rw-r--r--openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java9
-rw-r--r--openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java19
-rw-r--r--openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java6
-rw-r--r--openecomp-be/tools/snapshot-signature-plugin/pom.xml40
-rw-r--r--openecomp-be/tools/snapshot-signature-plugin/src/main/java/org/openecomp/sdc/onboarding/SnapshotSignature.java194
11 files changed, 309 insertions, 27 deletions
diff --git a/onboarding/pom.xml b/onboarding/pom.xml
index b1e6bd36bb..4bc0217280 100644
--- a/onboarding/pom.xml
+++ b/onboarding/pom.xml
@@ -19,6 +19,7 @@
<module>../common</module>
<module>../openecomp-be</module>
<module>../openecomp-be/tools/build-data-installer</module>
+ <module>../openecomp-be/tools/snapshot-signature-plugin</module>
<module>../openecomp-ui</module>
</modules>
diff --git a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java
index f51a8aae60..f5bbbd605a 100644
--- a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java
@@ -49,6 +49,7 @@ public class ArtifactHelper {
private static File unicornMetaLocation = null;
private File tempLocation = Paths.get(System.getProperties().getProperty("java.io.tmpdir")).toFile();
private static int snapshotBuildNumber = 0;
+ private static final String HYPHEN = "-";
void init(String terminalModuleCoordinate) {
setUnicornMetaLocation(getUnicornRootFile(unicornRoot.substring(0, unicornRoot.indexOf('/')), project));
@@ -141,11 +142,13 @@ public class ArtifactHelper {
try (InputStream is = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(is)) {
dataStore = HashMap.class.cast(ois.readObject());
dataStore.put("shutdownTime", (System.currentTimeMillis() / 1000) * 1000 + snapshotBuildNumber);
+ dataStore.put("version", project.getVersion());
}
try (OutputStream os = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(dataStore);
}
- Files.copy(file.toPath(), Paths.get(tempLocation.getAbsolutePath(), file.getName()),
+ Files.copy(file.toPath(),
+ Paths.get(tempLocation.getAbsolutePath(), file.getName() + HYPHEN + project.getVersion()),
StandardCopyOption.REPLACE_EXISTING);
}
}
diff --git a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java
index 6fa9b0e365..9585057524 100644
--- a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java
@@ -67,6 +67,11 @@ public class InitializationHelperMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (System.getProperties().containsKey(UNICORN_INITIALIZED)) {
+ try {
+ artifactHelper.shutDown(project);
+ } catch (IOException | ClassNotFoundException e) {
+ throw new MojoExecutionException("Unexpected Error Occured during shutdown activities", e);
+ }
return;
}
artifactHelper.init(groupId + ":" + artifactId);
@@ -105,7 +110,7 @@ public class InitializationHelperMojo extends AbstractMojo {
byte[] data = fetchContents(repo.getUrl(), artifactId, timestamp + "-" + buildNumber);
artifactHelper.store(artifactId, data);
getLog().info(artifactId + " Version to be copied is " + timestamp + "-" + buildNumber);
- artifactHelper.setSnapshotBuildNumber(Integer.parseInt(buildNumber));
+ ArtifactHelper.setSnapshotBuildNumber(Integer.parseInt(buildNumber));
return timestamp + "-" + buildNumber;
}
} catch (IOException e) {
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
index 8f20f221d9..d9767fdd1d 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
@@ -19,7 +19,9 @@ package org.openecomp.sdc.onboarding;
import static org.openecomp.sdc.onboarding.Constants.CHECKSUM;
import static org.openecomp.sdc.onboarding.Constants.COLON;
import static org.openecomp.sdc.onboarding.Constants.DOT;
+import static org.openecomp.sdc.onboarding.Constants.JAR;
import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
+import static org.openecomp.sdc.onboarding.Constants.SHA1;
import static org.openecomp.sdc.onboarding.Constants.UNICORN;
import java.io.ByteArrayInputStream;
@@ -67,14 +69,26 @@ class BuildHelper {
}
try {
signature = new String(fetchSnapshotSignature(snapshotFile, version));
+ if (version.equals(signature)) {
+ signature = getSHA1For(snapshotFile, Paths.get(snapshotFile.getParentFile().getAbsolutePath(),
+ moduleCoordinate.substring(moduleCoordinate.indexOf(':') + 1) + "-" + version + DOT + JAR + DOT
+ + SHA1).toFile());
+ }
store.put(key, signature);
return signature;
- } catch (IOException ioe) {
+ } catch (IOException | NoSuchAlgorithmException e) {
return version;
}
}
+ private static String getSHA1For(File file, File signatureFile) throws IOException, NoSuchAlgorithmException {
+ if (signatureFile.exists()) {
+ return new String(Files.readAllBytes(signatureFile.toPath()));
+ }
+ return getSourceChecksum(Files.readAllBytes(file.toPath()), SHA1);
+ }
+
static long getChecksum(File file, String fileType) {
try {
return readSources(file, fileType).hashCode();
@@ -84,8 +98,12 @@ class BuildHelper {
}
static String getSourceChecksum(String data, String hashType) throws NoSuchAlgorithmException {
+ return getSourceChecksum(data.getBytes(), hashType);
+ }
+
+ static String getSourceChecksum(byte[] data, String hashType) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(hashType);
- md.update(data.getBytes());
+ md.update(data);
byte[] hashBytes = md.digest();
StringBuilder buffer = new StringBuilder();
@@ -197,7 +215,7 @@ class BuildHelper {
JarInputStream jis = new JarInputStream(bais)) {
JarEntry entry = null;
while ((entry = jis.getNextJarEntry()) != null) {
- if (entry.getName().equals(UNICORN + DOT + CHECKSUM)) {
+ if (entry.getName().endsWith(UNICORN + DOT + CHECKSUM)) {
byte[] sigStore = new byte[1024];
return new String(sigStore, 0, jis.read(sigStore, 0, 1024)).getBytes();
}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
index 68557a9609..c8177989a5 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
@@ -48,6 +48,7 @@ import org.apache.maven.project.MavenProject;
public class BuildState {
private static final String SHUTDOWN_TIME = "shutdownTime";
+ private static final String VERSION = "version";
private static Map<String, Map> compileDataStore = new HashMap<>();
private static Map<String, Object> moduleBuildData = new HashMap<>();
@@ -66,6 +67,11 @@ public class BuildState {
initializeStore();
Optional<HashMap> masterStore = readState("compile.dat", HashMap.class);
compileDataStore = masterStore.isPresent() ? masterStore.get() : compileDataStore;
+ String version = String.class.cast(compileDataStore.get(VERSION));
+ if (version != null) {
+ stateFileLocation = new File(Paths.get(System.getProperties().getProperty("java.io.tmpdir")).toFile(),
+ "compileState.dat-" + version);
+ }
if (stateFileLocation.exists()) {
HashMap dat = loadState(stateFileLocation);
if (swapStates((HashMap<?, ?>) compileDataStore, dat)) {
@@ -282,11 +288,16 @@ public class BuildState {
private static boolean swapStates(HashMap repo, HashMap last) {
Long repoTime = repo.get(SHUTDOWN_TIME) == null ? 0 : (Long) repo.get(SHUTDOWN_TIME);
Long lastTime = last.get(SHUTDOWN_TIME) == null ? 0 : (Long) last.get(SHUTDOWN_TIME);
- long repoBuildNumber = repoTime / 1000;
- long lastBuildNumber = lastTime / 1000;
+ String repoVersion = repo.get(VERSION) == null ? "" : (String) repo.get(VERSION);
+ String lastVersion = last.get(VERSION) == null ? "" : (String) last.get(VERSION);
+ long repoBuildNumber = repoTime % 1000;
+ long lastBuildNumber = lastTime % 1000;
if (repoBuildNumber != lastBuildNumber) {
return false;
}
+ if (!repoVersion.equals(lastVersion)) {
+ return false;
+ }
return Long.compare(repoTime, lastTime) < 0;
}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
index 195b356377..c6603a7497 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
@@ -21,22 +21,26 @@ public class Constants {
public static final String UNICORN = "unicorn";
public static final String EMPTY_STRING = "";
- public static final String PREFIX = System.getProperties().contains(UNICORN) ? EMPTY_STRING : UNICORN;
public static final String JACOCO_SKIP = "jacoco.skip";
+ public static final String JACOCO_BUILD = Boolean.toString(
+ System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
+ System.getProperties().getProperty(JACOCO_SKIP))));
+ public static final String JACOCO = Boolean.valueOf(JACOCO_BUILD) ? UNICORN : EMPTY_STRING;
+ public static final String PREFIX = System.getProperties().contains(UNICORN) ? EMPTY_STRING : UNICORN;
public static final String FORK_COUNT = "fork.count";
public static final String FORK_MODE = "fork.mode";
public static final String SKIP_PMD = "skipPMD";
public static final String JAVA_EXT = ".java";
public static final String ANY_EXT = "*";
- public static final String SKIP_TEST_RUN = PREFIX + "skipTestRun";
+ public static final String SKIP_TEST_RUN = PREFIX + JACOCO + "skipTestRun";
public static final String SKIP_TESTS = "skipTests";
public static final String MAIN = "main";
public static final String TEST = "test";
public static final String RESOURCES_CHANGED = "resourcesChanged";
public static final String ANSI_YELLOW = "\u001B[43m";
public static final String ANSI_COLOR_RESET = "\u001B[0m";
- public static final String SKIP_MAIN_SOURCE_COMPILE = PREFIX + "skipMainSourceCompile";
- public static final String SKIP_TEST_SOURCE_COMPILE = PREFIX + "skipTestSourceCompile";
+ public static final String SKIP_MAIN_SOURCE_COMPILE = PREFIX + JACOCO + "skipMainSourceCompile";
+ public static final String SKIP_TEST_SOURCE_COMPILE = PREFIX + JACOCO + "skipTestSourceCompile";
public static final String MAIN_CHECKSUM = "mainChecksum";
public static final String CHECKSUM = "checksum";
public static final String TEST_CHECKSUM = "testChecksum";
@@ -60,8 +64,8 @@ public class Constants {
public static final String RESOURCE_WITH_TEST_ONLY = "resourceWithTestOnly";
public static final String INSTRUMENT_ONLY = "instrumentOnly";
public static final String TEST_ONLY = "testOnly";
- public static final String SKIP_RESOURCE_COLLECTION = PREFIX + "skipResourceCollection";
- public static final String SKIP_INSTALL = PREFIX + "skipInstall";
+ public static final String SKIP_RESOURCE_COLLECTION = PREFIX + JACOCO + "skipResourceCollection";
+ public static final String SKIP_INSTALL = PREFIX + JACOCO + "skipInstall";
private Constants() {
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
index 6c1d2be28e..552ae6ada1 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
@@ -18,7 +18,8 @@ package org.openecomp.sdc.onboarding;
import static org.openecomp.sdc.onboarding.Constants.FORK_COUNT;
import static org.openecomp.sdc.onboarding.Constants.FORK_MODE;
-import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP;
+import static org.openecomp.sdc.onboarding.Constants.JACOCO;
+import static org.openecomp.sdc.onboarding.Constants.JACOCO_BUILD;
import static org.openecomp.sdc.onboarding.Constants.PREFIX;
import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
import static org.openecomp.sdc.onboarding.Constants.UNICORN;
@@ -45,15 +46,13 @@ public class InitializationHelperMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- if (PREFIX == UNICORN) {
+ if (PREFIX == UNICORN || JACOCO == UNICORN) {
System.getProperties().setProperty(UNICORN, Boolean.TRUE.toString());
}
if (project.getPackaging().equals(excludePackaging)) {
return;
}
- project.getProperties().setProperty("skipGet", Boolean.FALSE.toString());
- if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
- System.getProperties().getProperty(JACOCO_SKIP)))) {
+ if (Boolean.valueOf(JACOCO_BUILD)) {
project.getProperties().setProperty(FORK_COUNT, "1");
project.getProperties().setProperty(FORK_MODE, "once");
} else {
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
index e97b172b84..3b51398bc7 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
@@ -349,16 +349,19 @@ public class PreCompileHelperMojo extends AbstractMojo {
return moduleBuildData;
}
for (Artifact dependency : project.getArtifacts()) {
- String version = dependency.isSnapshot() ? getSnapshotSignature(dependency.getFile(),
- dependency.getGroupId() + COLON + dependency.getArtifactId(), dependency.getVersion()) :
- dependency.getVersion();
- if (excludeDependencies.contains(dependency.getScope())) {
- HashMap.class.cast(moduleBuildData.get(TEST))
+ if (JAR.equals(dependency.getType())) {
+ String version = dependency.isSnapshot() || dependency.getFile().getName().contains("SNAPSHOT") ?
+ getSnapshotSignature(dependency.getFile(),
+ dependency.getGroupId() + COLON + dependency.getArtifactId(),
+ dependency.getVersion()) : dependency.getVersion();
+ if (excludeDependencies.contains(dependency.getScope())) {
+ HashMap.class.cast(moduleBuildData.get(TEST))
+ .put(dependency.getGroupId() + COLON + dependency.getArtifactId(), version);
+ continue;
+ }
+ HashMap.class.cast(moduleBuildData.get(MAIN))
.put(dependency.getGroupId() + COLON + dependency.getArtifactId(), version);
- continue;
}
- HashMap.class.cast(moduleBuildData.get(MAIN))
- .put(dependency.getGroupId() + COLON + dependency.getArtifactId(), version);
}
return moduleBuildData;
}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java
index c80951ff50..9e783d9ed4 100644
--- a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java
@@ -128,7 +128,11 @@ public class VerifyHelperMojo extends AbstractMojo {
private void removeProcessFiles() {
if (moduleCoordinates.equals(persistingModuleCoordinates) && pmdStateFile.exists()) {
- pmdStateFile.delete();
+ for (File file : pmdStateFile.getParentFile().listFiles()) {
+ if (file.isFile()) {
+ file.delete();
+ }
+ }
}
if (pmdTargetLocation.exists()) {
pmdTargetLocation.delete();
diff --git a/openecomp-be/tools/snapshot-signature-plugin/pom.xml b/openecomp-be/tools/snapshot-signature-plugin/pom.xml
new file mode 100644
index 0000000000..96ecbae828
--- /dev/null
+++ b/openecomp-be/tools/snapshot-signature-plugin/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>snapshot-signature-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <parent>
+ <artifactId>sdc-onboarding</artifactId>
+ <groupId>org.openecomp.sdc</groupId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../../../onboarding</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven-core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>${maven-plugin-annotations.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>${maven-plugin-plugin.version}</version>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project> \ No newline at end of file
diff --git a/openecomp-be/tools/snapshot-signature-plugin/src/main/java/org/openecomp/sdc/onboarding/SnapshotSignature.java b/openecomp-be/tools/snapshot-signature-plugin/src/main/java/org/openecomp/sdc/onboarding/SnapshotSignature.java
new file mode 100644
index 0000000000..f4a03ed47a
--- /dev/null
+++ b/openecomp-be/tools/snapshot-signature-plugin/src/main/java/org/openecomp/sdc/onboarding/SnapshotSignature.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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 a "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 org.openecomp.sdc.onboarding;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveTask;
+import java.util.stream.Collectors;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+
+@Mojo(name = "generate-signature", threadSafe = true, defaultPhase = LifecyclePhase.COMPILE,
+ requiresDependencyResolution = ResolutionScope.NONE)
+public class SnapshotSignature extends AbstractMojo {
+
+ public static final String JAVA_EXT = ".java";
+ public static final String UNICORN = "unicorn";
+ public static final String CHECKSUM = "checksum";
+ public static final String DOT = ".";
+ public static final String SHA1 = "sha1";
+ public static final String COLON = ":";
+ public static final String ANY_EXT = "*";
+ public static final String SNAPSHOT = "SNAPSHOT";
+ public static final String JAR = "jar";
+
+ @Parameter
+ private File mainSourceLocation;
+ @Parameter
+ private File mainResourceLocation;
+ @Parameter(defaultValue = "${project}")
+ private MavenProject project;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (!JAR.equals(project.getPackaging())) {
+ return;
+ }
+ init();
+ long resourceChecksum = getChecksum(mainResourceLocation, ANY_EXT);
+ long mainChecksum = getChecksum(mainSourceLocation, JAVA_EXT);
+ byte[] sourceChecksum = calculateChecksum(mainChecksum, resourceChecksum).getBytes();
+ generateSignature(sourceChecksum);
+ }
+
+ private void init() {
+ if (mainSourceLocation == null) {
+ mainSourceLocation = Paths.get(project.getBuild().getSourceDirectory()).toFile();
+ }
+ if (mainResourceLocation == null) {
+ mainResourceLocation = Paths.get(project.getBuild().getResources().get(0).getDirectory()).toFile();
+ }
+ }
+
+ private long getChecksum(File file, String fileType) {
+ try {
+ return readSources(file, fileType).hashCode();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private Map<String, List<String>> readSources(File file, String fileType) throws IOException {
+ Map<String, List<String>> source = new HashMap<>();
+ if (file.exists()) {
+ List<File> list = Files.walk(Paths.get(file.getAbsolutePath()))
+ .filter(JAVA_EXT.equals(fileType) ? this::isRegularJavaFile : Files::isRegularFile)
+ .map(Path::toFile).collect(Collectors.toList());
+ source.putAll(ForkJoinPool.commonPool()
+ .invoke(new FileReadTask(list.toArray(new File[0]), file.getAbsolutePath())));
+ }
+ return source;
+ }
+
+ private boolean isRegularJavaFile(Path path) {
+ File file = path.toFile();
+ return file.isFile() && file.getName().endsWith(JAVA_EXT);
+ }
+
+ private class FileReadTask extends RecursiveTask<Map<String, List<String>>> {
+
+ private Map<String, List<String>> store = new HashMap<>();
+ File[] files;
+ String pathPrefix;
+ private static final int MAX_FILES = 10;
+
+ FileReadTask(File[] files, String pathPrefix) {
+ this.files = files;
+ this.pathPrefix = pathPrefix;
+ }
+
+ private List<String> getData(File file) throws IOException {
+ List<String> coll = Files.readAllLines(file.toPath(), StandardCharsets.ISO_8859_1);
+ if (file.getAbsolutePath().contains(File.separator + "generated-sources" + File.separator)) {
+ Iterator<String> itr = coll.iterator();
+ while (itr.hasNext()) {
+ String s = itr.next();
+ if (s == null || s.trim().startsWith("/") || s.trim().startsWith("*")) {
+ itr.remove();
+ }
+ }
+ }
+ return coll;
+ }
+
+
+ @Override
+ protected Map<String, List<String>> compute() {
+ if (files.length > MAX_FILES) {
+ FileReadTask task1 = new FileReadTask(Arrays.copyOfRange(files, 0, files.length / 2), pathPrefix);
+ FileReadTask task2 =
+ new FileReadTask(Arrays.copyOfRange(files, files.length / 2, files.length), pathPrefix);
+ task1.fork();
+ task2.fork();
+ store.putAll(task1.join());
+ store.putAll(task2.join());
+ } else {
+ for (File toRead : files) {
+ try {
+ store.put(toRead.getAbsolutePath().substring(pathPrefix.length())
+ .replace(File.separatorChar, '.'), getData(toRead));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ }
+
+ return store;
+ }
+ }
+
+ private void generateSignature(byte[] sourceChecksum) {
+ try {
+ Paths.get(project.getBuild().getOutputDirectory()).toFile().mkdirs();
+ Files.write(Paths.get(project.getBuild().getOutputDirectory(), UNICORN + DOT + CHECKSUM), sourceChecksum,
+ StandardOpenOption.CREATE);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private String calculateChecksum(long mainChecksum, long resourceChecksum) throws MojoExecutionException {
+ try {
+ return getSourceChecksum(mainChecksum + COLON + resourceChecksum, SHA1);
+ } catch (NoSuchAlgorithmException e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+ }
+
+ private String getSourceChecksum(String data, String hashType) throws NoSuchAlgorithmException {
+ MessageDigest md = MessageDigest.getInstance(hashType);
+ md.update(data.getBytes());
+ byte[] hashBytes = md.digest();
+
+ StringBuilder buffer = new StringBuilder();
+ for (byte hashByte : hashBytes) {
+ buffer.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
+ }
+ return buffer.toString();
+ }
+}