diff options
author | Gautam Shah <gautams@amdocs.com> | 2018-04-21 16:18:37 +0530 |
---|---|---|
committer | GAUTAMS <gautams@amdocs.com> | 2018-04-26 17:47:29 +0530 |
commit | 3de22e1c6c2711072ce996335e7250445a39d320 (patch) | |
tree | c7a528bee3166b3262eef9977b0f87923df0e99f /openecomp-be/tools | |
parent | d71a8de8c7b688eabb250e524dc4f6000b3233b6 (diff) |
Reducing onboarding backend maven build time
Reducing onboarding backend maven build time
Change-Id: Id0178cbf010e46f741f4bff11e14b0801f14d4b8
Issue-ID: SDC-1189
Signed-off-by: GAUTAMS <gautams@amdocs.com>
Diffstat (limited to 'openecomp-be/tools')
10 files changed, 881 insertions, 85 deletions
diff --git a/openecomp-be/tools/build-helper/pom.xml b/openecomp-be/tools/build-helper/pom.xml deleted file mode 100644 index bcdf52a79e..0000000000 --- a/openecomp-be/tools/build-helper/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?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>build-helper</artifactId> - - <parent> - <artifactId>sdc-onboarding</artifactId> - <groupId>org.openecomp.sdc</groupId> - <version>1.2.0-SNAPSHOT</version> - <relativePath>../../../onboarding</relativePath> - </parent> - - <properties> - <jacoco.skip>true</jacoco.skip> - <pmd.skip>true</pmd.skip> - </properties> - - <dependencies> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>${junit.version}</version> - <scope>provided</scope> - </dependency> - </dependencies> - - -</project> diff --git a/openecomp-be/tools/build-helper/src/main/java/org/openecomp/onboarding/build/test/StaleCodeDetectionTest.java b/openecomp-be/tools/build-helper/src/main/java/org/openecomp/onboarding/build/test/StaleCodeDetectionTest.java deleted file mode 100644 index 69f77357ae..0000000000 --- a/openecomp-be/tools/build-helper/src/main/java/org/openecomp/onboarding/build/test/StaleCodeDetectionTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2016-2017 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.onboarding.build.test; - -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; - -public class StaleCodeDetectionTest { - - private static final String JAVA_EXT = ".java"; - private static final String CLASS_EXT = ".class"; - - @Test - public void checkIfStale() { - - String moduleLocation = System.getProperty("basedir"); - if (isStale(moduleLocation + File.separator + "target" + File.separator + "test-classes", - moduleLocation + File.separator + "src" + File.separator + "test" + File.separator + "java")) { - Assert.fail("****** Please remove 'target' directory manually under path " + moduleLocation); - } - } - - private boolean isStale(String compiledCodeLocation, String javaSourceLocation) { - File compiledFiles = new File(compiledCodeLocation); - File[] list = compiledFiles.listFiles((dir, file) -> file.endsWith(CLASS_EXT) && file.indexOf('$') == -1); - if (list == null || list.length == 0) { - return false; - } - File candidate = Collections.min(Arrays.asList(list), - (file1, file2) -> file1.lastModified() >= file2.lastModified() ? 1 : -1); - String sourceFilePath = javaSourceLocation + candidate.getAbsolutePath().replace(compiledCodeLocation, "") - .replace(CLASS_EXT, JAVA_EXT); - return !Paths.get(sourceFilePath).toFile().exists(); - } -} diff --git a/openecomp-be/tools/compile-helper-plugin/pom.xml b/openecomp-be/tools/compile-helper-plugin/pom.xml new file mode 100644 index 0000000000..3891558b66 --- /dev/null +++ b/openecomp-be/tools/compile-helper-plugin/pom.xml @@ -0,0 +1,41 @@ +<?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> + + <groupId>org.openecomp.sdc.onboarding</groupId> + <artifactId>compile-helper-plugin</artifactId> + <packaging>maven-plugin</packaging> + + <parent> + <artifactId>sdc-onboarding</artifactId> + <groupId>org.openecomp.sdc</groupId> + <version>1.2.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/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<String, Long> fullBuildData = new HashMap<>(); + private static Map<String, Long> fullResourceBuildData = new HashMap<>(); + private static Map<String, Object> moduleBuildData = new HashMap<>(); + private static Map<String, Object> 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<String, MavenProject, File> 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<String, Object> 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<String, Object> readResourceBuildData() { + return readBuildData(resourceBuildDataFile); + } + + private Map<String, Object> 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<String> dependencies) { + return isMust(this::getBuildTime, moduleCoordinates, dependencies); + } + + boolean isTestMust(String moduleCoordinates, Collection<String> dependencies) { + return isMust(this::getResourceBuildTime, moduleCoordinates, dependencies); + } + + private boolean isMust(Function<String, Long> funct, String moduleCoordinates, Collection<String> 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<String> lines = Files.lines(file.toPath()); + Iterator<String> 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<String> 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<File> 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<String, Object> resourceBuildData = getCurrentResourceBuildData(); + Map<String, Object> 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<File> 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<String, Object> getCurrentResourceBuildData() { + HashMap<String, Object> 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<String, Long> readResources(File file) throws IOException { + Map<String, Long> resources = new HashMap<>(); + if (file.exists()) { + List<Path> 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<String, String> getDependencies() { + Map<String, String> 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<String> 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<String, Object> moduleBuildData = getCurrentModuleBuildData(); + Map<String, Object> 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<String> dependencyCoordinates, boolean isFirstBuild, + boolean buildDataSame) { + return isFirstBuild || !buildDataSame || buildState.isCompileMust(moduleCoordinates, dependencyCoordinates); + } + + private Map<String, Object> getCurrentModuleBuildData() { + Map<String, Object> moduleBuildData = new HashMap<>(); + moduleBuildData.put(MAIN, new HashMap<String, String>()); + moduleBuildData.put(TEST, new HashMap<String, String>()); + 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()); + } + } +} |