2 * Copyright © 2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on a "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.onboarding;
19 import static org.openecomp.sdc.onboarding.Constants.CLASS_EXT;
20 import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
21 import static org.openecomp.sdc.onboarding.Constants.MAIN;
22 import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
23 import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
24 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
27 import java.io.IOException;
28 import java.io.UncheckedIOException;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
37 import java.util.stream.Collectors;
38 import org.apache.maven.artifact.Artifact;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugins.annotations.LifecyclePhase;
42 import org.apache.maven.plugins.annotations.Mojo;
43 import org.apache.maven.plugins.annotations.Parameter;
44 import org.apache.maven.plugins.annotations.ResolutionScope;
45 import org.apache.maven.project.MavenProject;
47 @Mojo(name = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
48 requiresDependencyResolution = ResolutionScope.TEST)
49 public class PostCompileHelperMojo extends AbstractMojo {
51 @Parameter(defaultValue = "${project}", readonly = true)
52 private MavenProject project;
53 @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
54 private String moduleCoordinates;
56 private Long staleThreshold;
58 private String excludePackaging;
60 private List<String> excludeDependencies;
62 private File mainSourceLocation;
64 private File testSourceLocation;
66 private File mainCompiledLocation;
68 private File testCompiledLocation;
70 private File inputSourceFilesList;
72 private File inputTestFilesList;
74 private BuildState buildState;
76 private File mainResourceLocation;
78 private File testResourceLocation;
80 private File compiledTestFilesList;
83 private File[] getCompiledClasses(File compiledFiles) {
84 if (!compiledFiles.exists()) {
89 list = Files.walk(Paths.get(compiledFiles.getAbsolutePath()))
90 .filter(p -> p.toFile().getAbsolutePath().endsWith(CLASS_EXT)).map(p -> p.toFile())
91 .sorted(this::compare).collect(Collectors.toList()).toArray(new File[0]);
92 } catch (IOException e) {
95 if (list == null || list.length == 0) {
101 private int compare(File file1, File file2) {
102 if (file1.lastModified() > file2.lastModified()) {
105 if (file1.lastModified() < file2.lastModified()) {
111 private File[] getStaleCompiledClasses(File[] compiledClasses, File javaSourceLocation) {
112 List<File> staleFiles = new ArrayList<>();
113 for (File file : compiledClasses) {
114 String classLocation = file.getAbsolutePath().replace(
115 project.getBasedir().getAbsolutePath() + File.separator + "target" + File.separator, "");
116 String classLocationWithPackageOnly =
117 classLocation.substring(classLocation.indexOf(File.separatorChar) + 1);
118 String sourceFilePath = javaSourceLocation.getAbsolutePath() + File.separator + classLocationWithPackageOnly
121 if (Paths.get(sourceFilePath).toFile().exists()) {
122 return staleFiles.toArray(new File[0]);
124 staleFiles.add(file);
127 return staleFiles.toArray(new File[0]);
130 private boolean deleteAll(File[] files) {
131 for (File file : files) {
132 if (!file.delete()) {
139 public void execute() throws MojoExecutionException {
140 if (!System.getProperties().containsKey(UNICORN)) {
143 if (project.getPackaging().equals(excludePackaging)) {
146 String moduleLocation = project.getBasedir().getAbsolutePath();
148 File[] mainClasses = getCompiledClasses(mainCompiledLocation);
149 processStaleClassesIfAny(mainClasses, mainSourceLocation, inputSourceFilesList);
151 File[] testClasses = getCompiledClasses(testCompiledLocation);
152 processStaleClassesIfAny(testClasses, testSourceLocation, inputTestFilesList);
154 if (mainClasses.length == 0 && testClasses.length == 0) {
157 buildState.addModuleBuildTime(project.getGroupId() + ":" + project.getArtifactId(),
158 mainClasses.length > 0 ? mainClasses[mainClasses.length - 1].lastModified() :
159 testClasses.length > 0 ? testClasses[testClasses.length - 1].lastModified() : 0);
160 buildState.saveModuleBuildData(moduleCoordinates);
161 Map<String, Object> resourceBuildData = getCurrentResourceBuildData();
162 Map<String, Object> lastTimeResourceBuildData = buildState.readResourceBuildData();
163 boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData);
164 if (!resourceDataSame) {
165 buildState.addResourceBuildData(moduleCoordinates, resourceBuildData);
166 project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
168 boolean resourceMainBuildDataSameWithPreviousBuild =
169 lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData.get(MAIN)
170 .equals(lastTimeResourceBuildData
172 if (!resourceMainBuildDataSameWithPreviousBuild) {
173 project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
175 if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
176 if (compiledTestFilesList.exists()
177 && compiledTestFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) {
178 project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
183 private void processStaleClassesIfAny(File[] classes, File sourceLocation, File listFile)
184 throws MojoExecutionException {
185 if (classes.length > 0) {
186 List<File> list = new ArrayList<>(Arrays.asList(classes));
187 File[] staleClasses = null;
188 boolean allStale = listFile.isFile() && listFile.length() == 0;
190 staleClasses = classes;
193 list.removeIf(f -> f.lastModified() > classes[classes.length - 1].lastModified() - staleThreshold);
194 staleClasses = getStaleCompiledClasses(list.toArray(new File[0]), sourceLocation);
196 if (!deleteAll(staleClasses)) {
197 throw new MojoExecutionException(
198 "****** Please remove 'target' directory manually under path " + project.getBasedir()
204 private Map<String, Object> getCurrentResourceBuildData() {
205 HashMap<String, Object> resourceBuildStateData = new HashMap<>();
207 resourceBuildStateData.put("main", readResources(mainResourceLocation));
208 resourceBuildStateData.put("test", readResources(testResourceLocation));
209 resourceBuildStateData.put("dependency", getDependencies());
210 } catch (IOException ioException) {
211 throw new UncheckedIOException(ioException);
213 return resourceBuildStateData;
216 private Map<String, Long> readResources(File file) throws IOException {
217 Map<String, Long> resources = new HashMap<>();
219 List<Path> list = Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile)
220 .collect(Collectors.toList());
221 for (Path path : list) {
222 resources.put(path.toFile().getAbsolutePath(), path.toFile().lastModified());
228 private Map<String, String> getDependencies() {
229 Map<String, String> dependencies = new HashMap<>();
230 for (Artifact d : project.getArtifacts()) {
231 dependencies.put(d.getGroupId() + ":" + d.getArtifactId(), d.getVersion());