1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.legacy;
20
21 import java.io.File;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.Properties;
25
26 import org.apache.maven.artifact.Artifact;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
29 import org.apache.maven.artifact.repository.Authentication;
30 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
31 import org.apache.maven.repository.Proxy;
32 import org.codehaus.plexus.component.annotations.Component;
33 import org.codehaus.plexus.component.annotations.Requirement;
34 import org.codehaus.plexus.logging.AbstractLogEnabled;
35 import org.codehaus.plexus.logging.Logger;
36 import org.eclipse.aether.internal.impl.TrackingFileManager;
37
38
39
40
41 @Component(role = UpdateCheckManager.class)
42 public class DefaultUpdateCheckManager extends AbstractLogEnabled implements UpdateCheckManager {
43 @Requirement
44 private TrackingFileManager trackingFileManager;
45
46 private static final String ERROR_KEY_SUFFIX = ".error";
47
48 public DefaultUpdateCheckManager() {
49
50 }
51
52
53
54
55 public DefaultUpdateCheckManager(Logger logger, TrackingFileManager trackingFileManager) {
56 enableLogging(logger);
57 this.trackingFileManager = trackingFileManager;
58 }
59
60 public static final String LAST_UPDATE_TAG = ".lastUpdated";
61
62 private static final String TOUCHFILE_NAME = "resolver-status.properties";
63
64 public boolean isUpdateRequired(Artifact artifact, ArtifactRepository repository) {
65 File file = artifact.getFile();
66
67 ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
68
69 if (!policy.isEnabled()) {
70 if (getLogger().isDebugEnabled()) {
71 getLogger()
72 .debug("Skipping update check for " + artifact + " (" + file + ") from " + repository.getId()
73 + " (" + repository.getUrl() + ")");
74 }
75
76 return false;
77 }
78
79 if (getLogger().isDebugEnabled()) {
80 getLogger()
81 .debug("Determining update check for " + artifact + " (" + file + ") from " + repository.getId()
82 + " (" + repository.getUrl() + ")");
83 }
84
85 if (file == null) {
86
87 return true;
88 }
89
90 Date lastCheckDate;
91
92 if (file.exists()) {
93 lastCheckDate = new Date(file.lastModified());
94 } else {
95 File touchfile = getTouchfile(artifact);
96 lastCheckDate = readLastUpdated(touchfile, getRepositoryKey(repository));
97 }
98
99 return (lastCheckDate == null) || policy.checkOutOfDate(lastCheckDate);
100 }
101
102 public boolean isUpdateRequired(RepositoryMetadata metadata, ArtifactRepository repository, File file) {
103
104
105
106
107
108
109 ArtifactRepositoryPolicy policy = metadata.getPolicy(repository);
110
111 if (!policy.isEnabled()) {
112 if (getLogger().isDebugEnabled()) {
113 getLogger()
114 .debug("Skipping update check for " + metadata.getKey() + " (" + file + ") from "
115 + repository.getId() + " (" + repository.getUrl() + ")");
116 }
117
118 return false;
119 }
120
121 if (getLogger().isDebugEnabled()) {
122 getLogger()
123 .debug("Determining update check for " + metadata.getKey() + " (" + file + ") from "
124 + repository.getId() + " (" + repository.getUrl() + ")");
125 }
126
127 if (file == null) {
128
129 return true;
130 }
131
132 Date lastCheckDate = readLastUpdated(metadata, repository, file);
133
134 return (lastCheckDate == null) || policy.checkOutOfDate(lastCheckDate);
135 }
136
137 private Date readLastUpdated(RepositoryMetadata metadata, ArtifactRepository repository, File file) {
138 File touchfile = getTouchfile(metadata, file);
139
140 String key = getMetadataKey(repository, file);
141
142 return readLastUpdated(touchfile, key);
143 }
144
145 public String getError(Artifact artifact, ArtifactRepository repository) {
146 File touchFile = getTouchfile(artifact);
147 return getError(touchFile, getRepositoryKey(repository));
148 }
149
150 public void touch(Artifact artifact, ArtifactRepository repository, String error) {
151 File file = artifact.getFile();
152
153 File touchfile = getTouchfile(artifact);
154
155 if (file.exists()) {
156 trackingFileManager.delete(touchfile);
157 } else {
158 writeLastUpdated(touchfile, getRepositoryKey(repository), error);
159 }
160 }
161
162 public void touch(RepositoryMetadata metadata, ArtifactRepository repository, File file) {
163 File touchfile = getTouchfile(metadata, file);
164
165 String key = getMetadataKey(repository, file);
166
167 writeLastUpdated(touchfile, key, null);
168 }
169
170 String getMetadataKey(ArtifactRepository repository, File file) {
171 return repository.getId() + '.' + file.getName() + LAST_UPDATE_TAG;
172 }
173
174 String getRepositoryKey(ArtifactRepository repository) {
175 StringBuilder buffer = new StringBuilder(256);
176
177 Proxy proxy = repository.getProxy();
178 if (proxy != null) {
179 if (proxy.getUserName() != null) {
180 int hash = (proxy.getUserName() + proxy.getPassword()).hashCode();
181 buffer.append(hash).append('@');
182 }
183 buffer.append(proxy.getHost()).append(':').append(proxy.getPort()).append('>');
184 }
185
186
187 Authentication auth = repository.getAuthentication();
188 if (auth != null) {
189 int hash = (auth.getUsername() + auth.getPassword()).hashCode();
190 buffer.append(hash).append('@');
191 }
192
193
194 buffer.append(repository.getUrl());
195
196 return buffer.toString();
197 }
198
199 private void writeLastUpdated(File touchfile, String key, String error) {
200 HashMap<String, String> update = new HashMap<>();
201 update.put(key, Long.toString(System.currentTimeMillis()));
202 update.put(key + ERROR_KEY_SUFFIX, error);
203 trackingFileManager.update(touchfile, update);
204 }
205
206 Date readLastUpdated(File touchfile, String key) {
207 getLogger().debug("Searching for " + key + " in resolution tracking file.");
208
209 Properties props = read(touchfile);
210 if (props != null) {
211 String rawVal = props.getProperty(key);
212 if (rawVal != null) {
213 try {
214 return new Date(Long.parseLong(rawVal));
215 } catch (NumberFormatException e) {
216 getLogger().debug("Cannot parse lastUpdated date: \'" + rawVal + "\'. Ignoring.", e);
217 }
218 }
219 }
220 return null;
221 }
222
223 private String getError(File touchFile, String key) {
224 Properties props = read(touchFile);
225 if (props != null) {
226 return props.getProperty(key + ERROR_KEY_SUFFIX);
227 }
228 return null;
229 }
230
231 private Properties read(File touchfile) {
232 return trackingFileManager.read(touchfile);
233 }
234
235 File getTouchfile(Artifact artifact) {
236 StringBuilder sb = new StringBuilder(128);
237 sb.append(artifact.getArtifactId());
238 sb.append('-').append(artifact.getBaseVersion());
239 if (artifact.getClassifier() != null) {
240 sb.append('-').append(artifact.getClassifier());
241 }
242 sb.append('.').append(artifact.getType()).append(LAST_UPDATE_TAG);
243 return new File(artifact.getFile().getParentFile(), sb.toString());
244 }
245
246 File getTouchfile(RepositoryMetadata metadata, File file) {
247 return new File(file.getParent(), TOUCHFILE_NAME);
248 }
249 }