1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Provider;
24
25 import java.util.LinkedHashSet;
26 import java.util.Set;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentMap;
29
30 import org.apache.maven.SessionScoped;
31 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
32 import org.apache.maven.buildcache.checksum.MavenProjectInput;
33 import org.apache.maven.buildcache.xml.CacheConfig;
34 import org.apache.maven.buildcache.xml.build.ProjectsInputInfo;
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
37 import org.apache.maven.project.MavenProject;
38 import org.eclipse.aether.RepositorySystem;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 @SessionScoped
43 @Named
44 public class DefaultProjectInputCalculator implements ProjectInputCalculator {
45
46 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProjectInputCalculator.class);
47
48 private final Provider<MavenSession> providerSession;
49 private final RemoteCacheRepository remoteCache;
50 private final CacheConfig cacheConfig;
51 private final RepositorySystem repoSystem;
52 private final NormalizedModelProvider normalizedModelProvider;
53 private final MultiModuleSupport multiModuleSupport;
54 private final ArtifactHandlerManager artifactHandlerManager;
55
56 private final ConcurrentMap<String, ProjectsInputInfo> checkSumMap = new ConcurrentHashMap<>();
57
58 private static final ThreadLocal<Set<String>> CURRENTLY_CALCULATING = ThreadLocal.withInitial(LinkedHashSet::new);
59
60 @Inject
61 public DefaultProjectInputCalculator(
62 Provider<MavenSession> providerSession,
63 RemoteCacheRepository remoteCache,
64 CacheConfig cacheConfig,
65 RepositorySystem repoSystem,
66 NormalizedModelProvider rawModelProvider,
67 MultiModuleSupport multiModuleSupport,
68 ArtifactHandlerManager artifactHandlerManager) {
69 this.providerSession = providerSession;
70 this.remoteCache = remoteCache;
71 this.cacheConfig = cacheConfig;
72 this.repoSystem = repoSystem;
73 this.normalizedModelProvider = rawModelProvider;
74 this.multiModuleSupport = multiModuleSupport;
75 this.artifactHandlerManager = artifactHandlerManager;
76 }
77
78 @Override
79 public ProjectsInputInfo calculateInput(MavenProject project) {
80 LOGGER.info(
81 "Going to calculate checksum for project [groupId={}, artifactId={}, version={}]",
82 project.getGroupId(),
83 project.getArtifactId(),
84 project.getVersion());
85
86 String key = BuilderCommon.getKey(project);
87
88
89
90 ProjectsInputInfo projectsInputInfo = checkSumMap.get(key);
91 if (projectsInputInfo != null) {
92 return projectsInputInfo;
93 }
94 projectsInputInfo = calculateInputInternal(key, project);
95 checkSumMap.put(key, projectsInputInfo);
96 return projectsInputInfo;
97 }
98
99 private ProjectsInputInfo calculateInputInternal(String key, MavenProject project) {
100 Set<String> projectsSet = CURRENTLY_CALCULATING.get();
101
102 if (!projectsSet.add(key)) {
103 throw new IllegalStateException("Checksum for project is already calculating. "
104 + "Is there a cyclic dependencies? [project=" + key
105 + ", setOfCalculatingProjects=" + projectsSet + "]");
106 }
107 try {
108 final MavenSession mavenSession = providerSession.get();
109 final MavenProjectInput input = new MavenProjectInput(
110 project,
111 normalizedModelProvider,
112 multiModuleSupport,
113 this,
114 mavenSession,
115 cacheConfig,
116 repoSystem,
117 remoteCache,
118 artifactHandlerManager);
119 return input.calculateChecksum();
120 } catch (Exception e) {
121 throw new RuntimeException("Failed to calculate checksums for " + project.getArtifactId(), e);
122 } finally {
123 projectsSet.remove(key);
124 }
125 }
126 }