From 3de22e1c6c2711072ce996335e7250445a39d320 Mon Sep 17 00:00:00 2001 From: Gautam Shah Date: Sat, 21 Apr 2018 16:18:37 +0530 Subject: Reducing onboarding backend maven build time Reducing onboarding backend maven build time Change-Id: Id0178cbf010e46f741f4bff11e14b0801f14d4b8 Issue-ID: SDC-1189 Signed-off-by: GAUTAMS --- .../org/openecomp/sdc/onboarding/BuildState.java | 238 +++++++++++++++++++++ .../org/openecomp/sdc/onboarding/Constants.java | 15 ++ .../sdc/onboarding/InitializationHelperMojo.java | 59 +++++ .../sdc/onboarding/PostCompileHelperMojo.java | 235 ++++++++++++++++++++ .../sdc/onboarding/PostTestRunHelperMojo.java | 61 ++++++ .../sdc/onboarding/PreCompileHelperMojo.java | 142 ++++++++++++ .../sdc/onboarding/PreTestCompileHelperMojo.java | 90 ++++++++ 7 files changed, 840 insertions(+) create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java create mode 100644 openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java (limited to 'openecomp-be/tools/compile-helper-plugin/src') 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 new file mode 100644 index 0000000000..888622f959 --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java @@ -0,0 +1,238 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.maven.project.MavenProject; + +public class BuildState { + + private static Map fullBuildData = new HashMap<>(); + private static Map fullResourceBuildData = new HashMap<>(); + private static Map moduleBuildData = new HashMap<>(); + private static Map resourceBuildData = new HashMap<>(); + + private static File buildStateFile; + private static File resourceStateFile; + private File moduleBuildDataFile; + private File resourceBuildDataFile; + private MavenProject project; + private String buildStateFilePath; + private String resourceStateFilePath; + + private void readFullBuildState() { + buildStateFile = initialize(this::getBuildStateFile, fullBuildData, + buildStateFilePath.substring(0, buildStateFilePath.indexOf('/')), project); + } + + private void readResourceBuildState() { + resourceStateFile = initialize(this::getResourceStateFile, fullResourceBuildData, + resourceStateFilePath.substring(0, resourceStateFilePath.indexOf('/')), project); + + } + + private File initialize(BiFunction funct, Map store, String moduleCoordinate, + MavenProject proj) { + File file = funct.apply(moduleCoordinate, proj); + file.getParentFile().mkdirs(); + try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis);) { + if (store.isEmpty()) { + store.putAll(HashMap.class.cast(ois.readObject())); + } + } catch (Exception e) { + store.clear(); + } + return file; + } + + private void writeFullBuildState() throws IOException { + writeState(buildStateFile, fullBuildData); + } + + private void writeFullResourceBuildState() throws IOException { + writeState(resourceStateFile, fullResourceBuildData); + } + + private void writeState(File file, Map store) throws IOException { + try (FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos)) { + oos.writeObject(store); + } + } + + private File getBuildStateFile(String moduleCoordinate, MavenProject proj) { + return getStateFile(moduleCoordinate, proj, buildStateFilePath); + } + + private File getResourceStateFile(String moduleCoordinate, MavenProject proj) { + return getStateFile(moduleCoordinate, proj, resourceStateFilePath); + } + + private File getStateFile(String moduleCoordinate, MavenProject proj, String filePath) { + return new File(getTopParentProject(moduleCoordinate, proj).getBasedir(), + filePath.substring(filePath.indexOf('/') + 1)); + } + + private MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) { + if (getModuleCoordinate(proj).equals(moduleCoordinate) || proj.getParent() == null) { + return proj; + } else { + return getTopParentProject(moduleCoordinate, proj.getParent()); + } + } + + private String getModuleCoordinate(MavenProject project) { + return project.getGroupId() + ":" + project.getArtifactId(); + } + + void addModuleBuildTime(String moduleCoordinates, Long buildTime) { + Long lastTime = fullBuildData.put(moduleCoordinates, buildTime); + try { + if (lastTime == null || !lastTime.equals(buildTime)) { + writeFullBuildState(); + } + } catch (IOException ignored) { + // ignored. No need to handle. System will take care. + } + } + + void addResourceBuildTime(String moduleCoordinates, Long buildTime) { + if (project.getProperties().containsKey(RESOURCES_CHANGED)) { + Long lastTime = fullResourceBuildData.put(moduleCoordinates, buildTime); + try { + writeFullResourceBuildState(); + } catch (IOException ignored) { + // ignored. No need to handle. System will take care. + } + } + } + + void addModuleBuildData(String moduleCoordinates, Map moduleBuildDependencies) { + moduleBuildData.put(moduleCoordinates, moduleBuildDependencies); + } + + Map readModuleBuildData() { + return readBuildData(moduleBuildDataFile); + } + + void saveModuleBuildData(String moduleCoordinate) { + saveBuildData(moduleBuildDataFile, moduleBuildData.get(moduleCoordinate)); + } + + void saveResourceBuildData(String moduleCoordinate) { + saveBuildData(resourceBuildDataFile, resourceBuildData.get(moduleCoordinate)); + } + + private void saveBuildData(File file, Object dataToSave) { + file.getParentFile().mkdirs(); + if (dataToSave != null) { + try (FileOutputStream fos = new FileOutputStream(file); + ObjectOutputStream ois = new ObjectOutputStream(fos)) { + ois.writeObject(dataToSave); + } catch (IOException ignored) { + //ignored. do nothing. system will take care. + } + } + } + + Map readResourceBuildData() { + return readBuildData(resourceBuildDataFile); + } + + private Map readBuildData(File file) { + try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) { + return HashMap.class.cast(ois.readObject()); + } catch (Exception e) { + return new HashMap<>(); + } + } + + void addResourceBuildData(String moduleCoordinates, Map currentModuleResourceBuildData) { + resourceBuildData.put(moduleCoordinates, currentModuleResourceBuildData); + } + + Long getBuildTime(String moduleCoordinates) { + if (fullBuildData.isEmpty()) { + readFullBuildState(); + readResourceBuildState(); + } + Long buildTime = fullBuildData.get(moduleCoordinates); + return buildTime == null ? 0 : buildTime; + } + + Long getResourceBuildTime(String moduleCoordinates) { + Long resourceBuildTime = fullResourceBuildData.get(moduleCoordinates); + return resourceBuildTime == null ? 0 : resourceBuildTime; + } + + boolean isCompileMust(String moduleCoordinates, Collection dependencies) { + return isMust(this::getBuildTime, moduleCoordinates, dependencies); + } + + boolean isTestMust(String moduleCoordinates, Collection dependencies) { + return isMust(this::getResourceBuildTime, moduleCoordinates, dependencies); + } + + private boolean isMust(Function funct, String moduleCoordinates, Collection dependencies) { + Long time = funct.apply(moduleCoordinates); + if (time == null || time == 0) { + return true; + } + for (String module : dependencies) { + Long buildTime = funct.apply(module); + if (buildTime >= time) { + return true; + } + } + return false; + } + + void markModuleDirty(File file) throws IOException { + if (file.exists()) { + Stream lines = Files.lines(file.toPath()); + Iterator itr = lines.iterator(); + while (itr.hasNext()) { + String line = itr.next(); + Path path = Paths.get(line); + if (path.toFile().exists()) { + if (path.toFile().setLastModified(System.currentTimeMillis())) { + break; + } else { + continue; + } + } + } + } + } + +} 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 new file mode 100644 index 0000000000..96abc47882 --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java @@ -0,0 +1,15 @@ +package org.openecomp.sdc.onboarding; + +public class Constants { + + public static final String JACOCO_SKIP = "jacoco.skip"; + public static final String FORK_COUNT = "fork.count"; + public static final String JAVA_EXT = ".java"; + public static final String CLASS_EXT = ".class"; + public static final String SKIP_TEST_RUN = "skipTestRun"; + public static final String MAIN = "main"; + public static final String TEST = "test"; + public static final String JAVA = "java"; + public static final String RESOURCES_CHANGED = "resourcesChanged"; + public static final String UNICORN = "unicorn"; +} 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 new file mode 100644 index 0000000000..cbf6f69c8a --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java @@ -0,0 +1,59 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.FORK_COUNT; +import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP; +import static org.openecomp.sdc.onboarding.Constants.UNICORN; + +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 = "init-helper", threadSafe = true, defaultPhase = LifecyclePhase.PRE_CLEAN, + requiresDependencyResolution = ResolutionScope.NONE) +public class InitializationHelperMojo extends AbstractMojo { + + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + + public void execute() throws MojoExecutionException, MojoFailureException { + + if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf( + System.getProperties().getProperty(JACOCO_SKIP)))) { + project.getProperties().setProperty(FORK_COUNT, "1"); + } else { + project.getProperties().setProperty(FORK_COUNT, "0"); + } + + if (System.getProperties().containsKey(UNICORN)) { + project.getProperties().setProperty("classes", "classes/**/*.class"); + project.getProperties().setProperty("testClasses", "test-classes/**/*.class"); + project.getProperties().setProperty("mavenStatus", "maven-status/**"); + project.getProperties().setProperty("pmd", "pmd/**"); + project.getProperties().setProperty("customGeneratedSources", "generated-sources/custom/**"); + + } + + } + +} diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java new file mode 100644 index 0000000000..9ab373509e --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java @@ -0,0 +1,235 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.CLASS_EXT; +import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT; +import static org.openecomp.sdc.onboarding.Constants.MAIN; +import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED; +import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN; +import static org.openecomp.sdc.onboarding.Constants.UNICORN; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +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 = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES, + requiresDependencyResolution = ResolutionScope.TEST) +public class PostCompileHelperMojo extends AbstractMojo { + + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}") + private String moduleCoordinates; + @Parameter + private Long staleThreshold; + @Parameter + private String excludePackaging; + @Parameter + private List excludeDependencies; + @Parameter + private File mainSourceLocation; + @Parameter + private File testSourceLocation; + @Parameter + private File mainCompiledLocation; + @Parameter + private File testCompiledLocation; + @Parameter + private File inputSourceFilesList; + @Parameter + private File inputTestFilesList; + @Parameter + private BuildState buildState; + @Parameter + private File mainResourceLocation; + @Parameter + private File testResourceLocation; + @Parameter + private File compiledTestFilesList; + + + private File[] getCompiledClasses(File compiledFiles) { + if (!compiledFiles.exists()) { + return new File[0]; + } + File[] list = null; + try { + list = Files.walk(Paths.get(compiledFiles.getAbsolutePath())) + .filter(p -> p.toFile().getAbsolutePath().endsWith(CLASS_EXT)).map(p -> p.toFile()) + .sorted(this::compare).collect(Collectors.toList()).toArray(new File[0]); + } catch (IOException e) { + e.printStackTrace(); + } + if (list == null || list.length == 0) { + return new File[0]; + } + return list; + } + + private int compare(File file1, File file2) { + if (file1.lastModified() > file2.lastModified()) { + return 1; + } + if (file1.lastModified() < file2.lastModified()) { + return -1; + } + return 0; + } + + private File[] getStaleCompiledClasses(File[] compiledClasses, File javaSourceLocation) { + List staleFiles = new ArrayList<>(); + for (File file : compiledClasses) { + String classLocation = file.getAbsolutePath().replace( + project.getBasedir().getAbsolutePath() + File.separator + "target" + File.separator, ""); + String classLocationWithPackageOnly = + classLocation.substring(classLocation.indexOf(File.separatorChar) + 1); + String sourceFilePath = javaSourceLocation.getAbsolutePath() + File.separator + classLocationWithPackageOnly + .replace(CLASS_EXT, + JAVA_EXT); + if (Paths.get(sourceFilePath).toFile().exists()) { + return staleFiles.toArray(new File[0]); + } else { + staleFiles.add(file); + } + } + return staleFiles.toArray(new File[0]); + } + + private boolean deleteAll(File[] files) { + for (File file : files) { + if (!file.delete()) { + return false; + } + } + return true; + } + + public void execute() throws MojoExecutionException { + if (!System.getProperties().containsKey(UNICORN)) { + return; + } + if (project.getPackaging().equals(excludePackaging)) { + return; + } + String moduleLocation = project.getBasedir().getAbsolutePath(); + + File[] mainClasses = getCompiledClasses(mainCompiledLocation); + processStaleClassesIfAny(mainClasses, mainSourceLocation, inputSourceFilesList); + + File[] testClasses = getCompiledClasses(testCompiledLocation); + processStaleClassesIfAny(testClasses, testSourceLocation, inputTestFilesList); + + if (mainClasses.length == 0 && testClasses.length == 0) { + return; + } + buildState.addModuleBuildTime(project.getGroupId() + ":" + project.getArtifactId(), + mainClasses.length > 0 ? mainClasses[mainClasses.length - 1].lastModified() : + testClasses.length > 0 ? testClasses[testClasses.length - 1].lastModified() : 0); + buildState.saveModuleBuildData(moduleCoordinates); + Map resourceBuildData = getCurrentResourceBuildData(); + Map lastTimeResourceBuildData = buildState.readResourceBuildData(); + boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData); + if (!resourceDataSame) { + buildState.addResourceBuildData(moduleCoordinates, resourceBuildData); + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } + boolean resourceMainBuildDataSameWithPreviousBuild = + lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData.get(MAIN) + .equals(lastTimeResourceBuildData + .get(MAIN)); + if (!resourceMainBuildDataSameWithPreviousBuild) { + project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString()); + } + if (!project.getProperties().containsKey(SKIP_TEST_RUN)) { + if (compiledTestFilesList.exists() + && compiledTestFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) { + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } + } + } + + private void processStaleClassesIfAny(File[] classes, File sourceLocation, File listFile) + throws MojoExecutionException { + if (classes.length > 0) { + List list = new ArrayList<>(Arrays.asList(classes)); + File[] staleClasses = null; + boolean allStale = listFile.isFile() && listFile.length() == 0; + if (allStale) { + staleClasses = classes; + listFile.delete(); + } else { + list.removeIf(f -> f.lastModified() > classes[classes.length - 1].lastModified() - staleThreshold); + staleClasses = getStaleCompiledClasses(list.toArray(new File[0]), sourceLocation); + } + if (!deleteAll(staleClasses)) { + throw new MojoExecutionException( + "****** Please remove 'target' directory manually under path " + project.getBasedir() + .getAbsolutePath()); + } + } + } + + private Map getCurrentResourceBuildData() { + HashMap resourceBuildStateData = new HashMap<>(); + try { + resourceBuildStateData.put("main", readResources(mainResourceLocation)); + resourceBuildStateData.put("test", readResources(testResourceLocation)); + resourceBuildStateData.put("dependency", getDependencies()); + } catch (IOException ioException) { + throw new UncheckedIOException(ioException); + } + return resourceBuildStateData; + } + + private Map readResources(File file) throws IOException { + Map resources = new HashMap<>(); + if (file.exists()) { + List list = Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile) + .collect(Collectors.toList()); + for (Path path : list) { + resources.put(path.toFile().getAbsolutePath(), path.toFile().lastModified()); + } + } + return resources; + } + + private Map getDependencies() { + Map dependencies = new HashMap<>(); + for (Artifact d : project.getArtifacts()) { + dependencies.put(d.getGroupId() + ":" + d.getArtifactId(), d.getVersion()); + } + return dependencies; + } +} diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java new file mode 100644 index 0000000000..5b326f3ddf --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java @@ -0,0 +1,61 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN; +import static org.openecomp.sdc.onboarding.Constants.UNICORN; + +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 = "post-test-run-helper", threadSafe = true, defaultPhase = LifecyclePhase.TEST, + requiresDependencyResolution = ResolutionScope.NONE) +public class PostTestRunHelperMojo extends AbstractMojo { + + @Parameter + private BuildState buildState; + @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}") + private String moduleCoordinates; + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + @Parameter + private String excludePackaging; + + + public void execute() throws MojoExecutionException, MojoFailureException { + if (!System.getProperties().containsKey(UNICORN)) { + return; + } + if (project.getPackaging().equals(excludePackaging)) { + return; + } + buildState.saveResourceBuildData(moduleCoordinates); + if (project.getProperties().containsKey(SKIP_TEST_RUN) && !Boolean.valueOf( + project.getProperties().getProperty(SKIP_TEST_RUN))) { + if (!System.getProperties().containsKey("skipTests")) { + buildState.addResourceBuildTime(moduleCoordinates, System.currentTimeMillis()); + } + } + + } +} 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 new file mode 100644 index 0000000000..faa3167e37 --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java @@ -0,0 +1,142 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.MAIN; +import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN; +import static org.openecomp.sdc.onboarding.Constants.TEST; +import static org.openecomp.sdc.onboarding.Constants.UNICORN; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +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 = "pre-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_SOURCES, + requiresDependencyResolution = ResolutionScope.TEST) +public class PreCompileHelperMojo extends AbstractMojo { + + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}") + private String moduleCoordinates; + @Parameter + private String excludePackaging; + @Parameter + private List excludeDependencies; + @Parameter + private File mainCompiledLocation; + @Parameter + private File testCompiledLocation; + @Parameter + private File inputSourceFilesList; + @Parameter + private File inputTestFilesList; + @Parameter + private BuildState buildState; + + public void execute() throws MojoExecutionException { + if (!System.getProperties().containsKey(UNICORN)) { + return; + } + if (project.getPackaging().equals(excludePackaging)) { + return; + } + + Map moduleBuildData = getCurrentModuleBuildData(); + Map lastTimeModuleBuildData = buildState.readModuleBuildData(); + + boolean buildDataSameWithPreviousBuild = lastTimeModuleBuildData.get(MAIN) != null && moduleBuildData.get(MAIN) + .equals(lastTimeModuleBuildData + .get(MAIN)); + boolean isFirstBuild = buildState.getBuildTime(moduleCoordinates) == 0; + + if (isCompileNeeded(HashMap.class.cast(moduleBuildData.get(MAIN)).keySet(), isFirstBuild, + buildDataSameWithPreviousBuild)) { + try { + buildState.markModuleDirty(inputSourceFilesList); + buildState.markModuleDirty(inputTestFilesList); + project.getProperties().setProperty(SKIP_TEST_RUN, "false"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + if (!moduleBuildData.get(TEST).equals(lastTimeModuleBuildData.get(TEST))) { + try { + buildState.markModuleDirty(inputTestFilesList); + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + if (!moduleBuildData.equals(lastTimeModuleBuildData)) { + buildState.addModuleBuildData(moduleCoordinates, moduleBuildData); + } + + if (inputSourceFilesList.isFile() && inputSourceFilesList.length() == 0) { + if (!inputSourceFilesList.delete()) { + throw new MojoExecutionException( + "****** Please remove 'target' directory manually under path " + project.getBasedir() + .getAbsolutePath()); + } + } + if (inputTestFilesList.isFile() && inputTestFilesList.length() == 0) { + if (!inputTestFilesList.delete()) { + throw new MojoExecutionException( + "****** Please remove 'target' directory manually under path " + project.getBasedir() + .getAbsolutePath()); + } + } + } + + private boolean isCompileNeeded(Collection dependencyCoordinates, boolean isFirstBuild, + boolean buildDataSame) { + return isFirstBuild || !buildDataSame || buildState.isCompileMust(moduleCoordinates, dependencyCoordinates); + } + + private Map getCurrentModuleBuildData() { + Map moduleBuildData = new HashMap<>(); + moduleBuildData.put(MAIN, new HashMap()); + moduleBuildData.put(TEST, new HashMap()); + if (project.getArtifacts() == null || project.getArtifacts().isEmpty()) { + return moduleBuildData; + } + for (Artifact dependency : project.getArtifacts()) { + if (excludeDependencies.contains(dependency.getScope())) { + HashMap.class.cast(moduleBuildData.get(TEST)) + .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion()); + continue; + } + HashMap.class.cast(moduleBuildData.get(MAIN)) + .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion()); + } + return moduleBuildData; + } +} diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java new file mode 100644 index 0000000000..e711cb0ae7 --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java @@ -0,0 +1,90 @@ +/* + * 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 static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP; +import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN; +import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED; +import static org.openecomp.sdc.onboarding.Constants.UNICORN; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +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 = "pre-test-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_TEST_RESOURCES, + requiresDependencyResolution = ResolutionScope.TEST) +public class PreTestCompileHelperMojo extends AbstractMojo { + + @Parameter + private File compiledFilesList; + @Parameter + private Long staleThreshold; + @Parameter + private File inputTestFilesList; + @Parameter + private BuildState buildState; + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}") + private String moduleCoordinates; + @Parameter + private String excludePackaging; + + + public void execute() throws MojoExecutionException, MojoFailureException { + if (!System.getProperties().containsKey(UNICORN)) { + return; + } + if (project.getPackaging().equals(excludePackaging)) { + return; + } + if (compiledFilesList.exists() + && compiledFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) { + try { + buildState.markModuleDirty(inputTestFilesList); + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + boolean isTestMust = buildState.isTestMust(moduleCoordinates, + project.getDependencies().stream().map(d -> d.getGroupId() + ":" + d.getArtifactId()) + .collect(Collectors.toList())); + if (isTestMust) { + project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString()); + if (!project.getProperties().containsKey(SKIP_TEST_RUN)) { + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } + } + if (!project.getProperties().containsKey(SKIP_TEST_RUN)) { + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.TRUE.toString()); + } + if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf( + System.getProperties().getProperty(JACOCO_SKIP)))) { + project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString()); + } + } +} -- cgit 1.2.3-korg