1 | |
package org.apache.maven.archiva.repository.metadata; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import org.apache.archiva.checksum.ChecksumAlgorithm; |
23 | |
import org.apache.archiva.checksum.ChecksummedFile; |
24 | |
import org.apache.commons.collections.CollectionUtils; |
25 | |
import org.apache.commons.lang.StringUtils; |
26 | |
import org.apache.commons.lang.math.NumberUtils; |
27 | |
import org.apache.commons.lang.time.DateUtils; |
28 | |
import org.apache.maven.archiva.common.utils.PathUtil; |
29 | |
import org.apache.maven.archiva.common.utils.VersionComparator; |
30 | |
import org.apache.maven.archiva.common.utils.VersionUtil; |
31 | |
import org.apache.maven.archiva.configuration.ArchivaConfiguration; |
32 | |
import org.apache.maven.archiva.configuration.ConfigurationNames; |
33 | |
import org.apache.maven.archiva.configuration.FileTypes; |
34 | |
import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; |
35 | |
import org.apache.maven.archiva.model.ArchivaRepositoryMetadata; |
36 | |
import org.apache.maven.archiva.model.ArtifactReference; |
37 | |
import org.apache.maven.archiva.model.Plugin; |
38 | |
import org.apache.maven.archiva.model.ProjectReference; |
39 | |
import org.apache.maven.archiva.model.SnapshotVersion; |
40 | |
import org.apache.maven.archiva.model.VersionedReference; |
41 | |
import org.apache.maven.archiva.repository.ContentNotFoundException; |
42 | |
import org.apache.maven.archiva.repository.ManagedRepositoryContent; |
43 | |
import org.apache.maven.archiva.repository.RemoteRepositoryContent; |
44 | |
import org.apache.maven.archiva.repository.layout.LayoutException; |
45 | |
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; |
46 | |
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; |
47 | |
import org.codehaus.plexus.registry.Registry; |
48 | |
import org.codehaus.plexus.registry.RegistryListener; |
49 | |
import org.slf4j.Logger; |
50 | |
import org.slf4j.LoggerFactory; |
51 | |
|
52 | |
import java.io.File; |
53 | |
import java.io.IOException; |
54 | |
import java.text.ParseException; |
55 | |
import java.text.SimpleDateFormat; |
56 | |
import java.util.ArrayList; |
57 | |
import java.util.Calendar; |
58 | |
import java.util.Collection; |
59 | |
import java.util.Collections; |
60 | |
import java.util.Date; |
61 | |
import java.util.HashMap; |
62 | |
import java.util.HashSet; |
63 | |
import java.util.Iterator; |
64 | |
import java.util.LinkedHashSet; |
65 | |
import java.util.List; |
66 | |
import java.util.Map; |
67 | |
import java.util.Set; |
68 | |
import java.util.regex.Matcher; |
69 | |
import org.apache.commons.io.FileUtils; |
70 | |
|
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
public class MetadataTools |
79 | |
implements RegistryListener, Initializable |
80 | |
{ |
81 | 0 | private static Logger log = LoggerFactory.getLogger( MetadataTools.class ); |
82 | |
|
83 | |
public static final String MAVEN_METADATA = "maven-metadata.xml"; |
84 | |
|
85 | |
private static final char PATH_SEPARATOR = '/'; |
86 | |
|
87 | |
private static final char GROUP_SEPARATOR = '.'; |
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
private ArchivaConfiguration configuration; |
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
private FileTypes filetypes; |
98 | |
|
99 | 0 | private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 }; |
100 | |
|
101 | |
private List<String> artifactPatterns; |
102 | |
|
103 | |
private Map<String, Set<String>> proxies; |
104 | |
|
105 | 0 | private static final char NUMS[] = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; |
106 | |
|
107 | |
private SimpleDateFormat lastUpdatedFormat; |
108 | |
|
109 | |
public MetadataTools() |
110 | 0 | { |
111 | 0 | lastUpdatedFormat = new SimpleDateFormat( "yyyyMMddHHmmss" ); |
112 | 0 | lastUpdatedFormat.setTimeZone( DateUtils.UTC_TIME_ZONE ); |
113 | 0 | } |
114 | |
|
115 | |
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) |
116 | |
{ |
117 | 0 | if ( ConfigurationNames.isProxyConnector( propertyName ) ) |
118 | |
{ |
119 | 0 | initConfigVariables(); |
120 | |
} |
121 | 0 | } |
122 | |
|
123 | |
public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) |
124 | |
{ |
125 | |
|
126 | 0 | } |
127 | |
|
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
public Set<String> gatherSnapshotVersions( ManagedRepositoryContent managedRepository, VersionedReference reference ) |
136 | |
throws LayoutException, IOException, ContentNotFoundException |
137 | |
{ |
138 | 0 | Set<String> foundVersions = managedRepository.getVersions( reference ); |
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | 0 | Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() ); |
145 | |
|
146 | 0 | if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) ) |
147 | |
{ |
148 | 0 | String baseVersion = VersionUtil.getBaseVersion( reference.getVersion() ); |
149 | 0 | baseVersion = baseVersion.substring( 0, baseVersion.indexOf( VersionUtil.SNAPSHOT ) - 1 ); |
150 | |
|
151 | |
|
152 | 0 | Iterator<String> it = proxiedRepoIds.iterator(); |
153 | 0 | while ( it.hasNext() ) |
154 | |
{ |
155 | 0 | String proxyId = it.next(); |
156 | |
|
157 | 0 | ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId ); |
158 | 0 | if ( proxyMetadata == null ) |
159 | |
{ |
160 | |
|
161 | 0 | continue; |
162 | |
} |
163 | |
|
164 | |
|
165 | 0 | SnapshotVersion snapshot = proxyMetadata.getSnapshotVersion(); |
166 | 0 | if ( snapshot != null ) |
167 | |
{ |
168 | 0 | String timestamp = snapshot.getTimestamp(); |
169 | 0 | int buildNumber = snapshot.getBuildNumber(); |
170 | |
|
171 | |
|
172 | 0 | if ( StringUtils.isNotBlank( timestamp ) && ( buildNumber > 0 ) ) |
173 | |
{ |
174 | 0 | foundVersions.add( baseVersion + "-" + timestamp + "-" + buildNumber ); |
175 | |
} |
176 | |
} |
177 | 0 | } |
178 | |
} |
179 | |
|
180 | 0 | return foundVersions; |
181 | |
} |
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
public VersionedReference toVersionedReference( String path ) |
190 | |
throws RepositoryMetadataException |
191 | |
{ |
192 | 0 | if ( !path.endsWith( "/" + MAVEN_METADATA ) ) |
193 | |
{ |
194 | 0 | throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " ); |
195 | |
} |
196 | |
|
197 | 0 | VersionedReference reference = new VersionedReference(); |
198 | |
|
199 | 0 | String normalizedPath = StringUtils.replace( path, "\\", "/" ); |
200 | 0 | String pathParts[] = StringUtils.split( normalizedPath, '/' ); |
201 | |
|
202 | 0 | int versionOffset = pathParts.length - 2; |
203 | 0 | int artifactIdOffset = versionOffset - 1; |
204 | 0 | int groupIdEnd = artifactIdOffset - 1; |
205 | |
|
206 | 0 | reference.setVersion( pathParts[versionOffset] ); |
207 | |
|
208 | 0 | if ( !hasNumberAnywhere( reference.getVersion() ) ) |
209 | |
{ |
210 | |
|
211 | 0 | throw new RepositoryMetadataException( |
212 | |
"Not a versioned reference, as version id on path has no number in it." ); |
213 | |
} |
214 | |
|
215 | 0 | reference.setArtifactId( pathParts[artifactIdOffset] ); |
216 | |
|
217 | 0 | StringBuffer gid = new StringBuffer(); |
218 | 0 | for ( int i = 0; i <= groupIdEnd; i++ ) |
219 | |
{ |
220 | 0 | if ( i > 0 ) |
221 | |
{ |
222 | 0 | gid.append( "." ); |
223 | |
} |
224 | 0 | gid.append( pathParts[i] ); |
225 | |
} |
226 | |
|
227 | 0 | reference.setGroupId( gid.toString() ); |
228 | |
|
229 | 0 | return reference; |
230 | |
} |
231 | |
|
232 | |
private boolean hasNumberAnywhere( String version ) |
233 | |
{ |
234 | 0 | return StringUtils.indexOfAny( version, NUMS ) != ( -1 ); |
235 | |
} |
236 | |
|
237 | |
public ProjectReference toProjectReference( String path ) |
238 | |
throws RepositoryMetadataException |
239 | |
{ |
240 | 0 | if ( !path.endsWith( "/" + MAVEN_METADATA ) ) |
241 | |
{ |
242 | 0 | throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " ); |
243 | |
} |
244 | |
|
245 | 0 | ProjectReference reference = new ProjectReference(); |
246 | |
|
247 | 0 | String normalizedPath = StringUtils.replace( path, "\\", "/" ); |
248 | 0 | String pathParts[] = StringUtils.split( normalizedPath, '/' ); |
249 | |
|
250 | |
|
251 | |
|
252 | 0 | int artifactIdOffset = pathParts.length - 2; |
253 | 0 | int groupIdEnd = artifactIdOffset - 1; |
254 | |
|
255 | 0 | reference.setArtifactId( pathParts[artifactIdOffset] ); |
256 | |
|
257 | 0 | StringBuffer gid = new StringBuffer(); |
258 | 0 | for ( int i = 0; i <= groupIdEnd; i++ ) |
259 | |
{ |
260 | 0 | if ( i > 0 ) |
261 | |
{ |
262 | 0 | gid.append( "." ); |
263 | |
} |
264 | 0 | gid.append( pathParts[i] ); |
265 | |
} |
266 | |
|
267 | 0 | reference.setGroupId( gid.toString() ); |
268 | |
|
269 | 0 | return reference; |
270 | |
} |
271 | |
|
272 | |
public String toPath( ProjectReference reference ) |
273 | |
{ |
274 | 0 | StringBuffer path = new StringBuffer(); |
275 | |
|
276 | 0 | path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR ); |
277 | 0 | path.append( reference.getArtifactId() ).append( PATH_SEPARATOR ); |
278 | 0 | path.append( MAVEN_METADATA ); |
279 | |
|
280 | 0 | return path.toString(); |
281 | |
} |
282 | |
|
283 | |
public String toPath( VersionedReference reference ) |
284 | |
{ |
285 | 0 | StringBuffer path = new StringBuffer(); |
286 | |
|
287 | 0 | path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR ); |
288 | 0 | path.append( reference.getArtifactId() ).append( PATH_SEPARATOR ); |
289 | 0 | if ( reference.getVersion() != null ) |
290 | |
{ |
291 | |
|
292 | 0 | path.append( VersionUtil.getBaseVersion( reference.getVersion() ) ).append( PATH_SEPARATOR ); |
293 | |
} |
294 | 0 | path.append( MAVEN_METADATA ); |
295 | |
|
296 | 0 | return path.toString(); |
297 | |
} |
298 | |
|
299 | |
private String formatAsDirectory( String directory ) |
300 | |
{ |
301 | 0 | return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR ); |
302 | |
} |
303 | |
|
304 | |
|
305 | |
|
306 | |
|
307 | |
|
308 | |
|
309 | |
|
310 | |
|
311 | |
public String getRepositorySpecificName( RemoteRepositoryContent repository, String path ) |
312 | |
{ |
313 | 0 | return getRepositorySpecificName( repository.getId(), path ); |
314 | |
} |
315 | |
|
316 | |
|
317 | |
|
318 | |
|
319 | |
|
320 | |
|
321 | |
|
322 | |
|
323 | |
public String getRepositorySpecificName( String proxyId, String path ) |
324 | |
{ |
325 | 0 | StringBuffer ret = new StringBuffer(); |
326 | |
|
327 | 0 | int idx = path.lastIndexOf( "/" ); |
328 | 0 | if ( idx > 0 ) |
329 | |
{ |
330 | 0 | ret.append( path.substring( 0, idx + 1 ) ); |
331 | |
} |
332 | |
|
333 | |
|
334 | 0 | ret.append( "maven-metadata-" ).append( proxyId ).append( ".xml" ); |
335 | |
|
336 | 0 | return ret.toString(); |
337 | |
} |
338 | |
|
339 | |
public void initialize() |
340 | |
throws InitializationException |
341 | |
{ |
342 | 0 | this.artifactPatterns = new ArrayList<String>(); |
343 | 0 | this.proxies = new HashMap<String, Set<String>>(); |
344 | 0 | initConfigVariables(); |
345 | |
|
346 | 0 | configuration.addChangeListener( this ); |
347 | 0 | } |
348 | |
|
349 | |
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository, |
350 | |
ProjectReference reference, String proxyId ) |
351 | |
{ |
352 | 0 | String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) ); |
353 | 0 | File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath ); |
354 | |
|
355 | 0 | if ( !metadataFile.exists() || !metadataFile.isFile() ) |
356 | |
{ |
357 | |
|
358 | 0 | return null; |
359 | |
} |
360 | |
|
361 | |
try |
362 | |
{ |
363 | 0 | return RepositoryMetadataReader.read( metadataFile ); |
364 | |
} |
365 | 0 | catch ( RepositoryMetadataException e ) |
366 | |
{ |
367 | |
|
368 | |
|
369 | 0 | log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e ); |
370 | 0 | return null; |
371 | |
} |
372 | |
} |
373 | |
|
374 | |
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository, |
375 | |
String logicalResource, String proxyId ) |
376 | |
{ |
377 | 0 | String metadataPath = getRepositorySpecificName( proxyId, logicalResource ); |
378 | 0 | File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath ); |
379 | |
|
380 | 0 | if ( !metadataFile.exists() || !metadataFile.isFile() ) |
381 | |
{ |
382 | |
|
383 | 0 | return null; |
384 | |
} |
385 | |
|
386 | |
try |
387 | |
{ |
388 | 0 | return RepositoryMetadataReader.read( metadataFile ); |
389 | |
} |
390 | 0 | catch ( RepositoryMetadataException e ) |
391 | |
{ |
392 | |
|
393 | |
|
394 | 0 | log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e ); |
395 | 0 | return null; |
396 | |
} |
397 | |
} |
398 | |
|
399 | |
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository, |
400 | |
VersionedReference reference, String proxyId ) |
401 | |
{ |
402 | 0 | String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) ); |
403 | 0 | File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath ); |
404 | |
|
405 | 0 | if ( !metadataFile.exists() || !metadataFile.isFile() ) |
406 | |
{ |
407 | |
|
408 | 0 | return null; |
409 | |
} |
410 | |
|
411 | |
try |
412 | |
{ |
413 | 0 | return RepositoryMetadataReader.read( metadataFile ); |
414 | |
} |
415 | 0 | catch ( RepositoryMetadataException e ) |
416 | |
{ |
417 | |
|
418 | |
|
419 | 0 | log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e ); |
420 | 0 | return null; |
421 | |
} |
422 | |
} |
423 | |
|
424 | |
public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource) throws RepositoryMetadataException |
425 | |
{ |
426 | 0 | final File metadataFile = new File(managedRepository.getRepoRoot(), logicalResource); |
427 | 0 | ArchivaRepositoryMetadata metadata = null; |
428 | |
|
429 | |
|
430 | 0 | List<ArchivaRepositoryMetadata> metadatas = getMetadatasForManagedRepository(managedRepository, logicalResource); |
431 | 0 | for (ArchivaRepositoryMetadata proxiedMetadata : metadatas) |
432 | |
{ |
433 | 0 | if (metadata == null) |
434 | |
{ |
435 | 0 | metadata = proxiedMetadata; |
436 | 0 | continue; |
437 | |
} |
438 | 0 | metadata = RepositoryMetadataMerge.merge(metadata, proxiedMetadata); |
439 | |
} |
440 | |
|
441 | 0 | if (metadata == null) |
442 | |
{ |
443 | 0 | log.debug("No metadata to update for " + logicalResource); |
444 | 0 | return; |
445 | |
} |
446 | |
|
447 | 0 | Set<String> availableVersions = new HashSet<String>(); |
448 | 0 | List<String> metadataAvailableVersions = metadata.getAvailableVersions(); |
449 | 0 | if (metadataAvailableVersions != null) |
450 | |
{ |
451 | 0 | availableVersions.addAll(metadataAvailableVersions); |
452 | |
} |
453 | 0 | availableVersions = findPossibleVersions(availableVersions, metadataFile.getParentFile()); |
454 | |
|
455 | 0 | if (availableVersions.size() > 0) |
456 | |
{ |
457 | 0 | updateMetadataVersions(availableVersions, metadata); |
458 | |
} |
459 | |
|
460 | 0 | RepositoryMetadataWriter.write(metadata, metadataFile); |
461 | |
|
462 | 0 | ChecksummedFile checksum = new ChecksummedFile( metadataFile ); |
463 | 0 | checksum.fixChecksums( algorithms ); |
464 | 0 | } |
465 | |
|
466 | |
|
467 | |
|
468 | |
|
469 | |
|
470 | |
|
471 | |
|
472 | |
|
473 | |
private Set<String> findPossibleVersions(Set<String> versions, File metadataParentDirectory) |
474 | |
{ |
475 | 0 | Set<String> result = new HashSet<String>(versions); |
476 | 0 | for (File directory : metadataParentDirectory.listFiles()) |
477 | |
{ |
478 | 0 | if (directory.isDirectory()) |
479 | |
{ |
480 | 0 | for (File possiblePom : directory.listFiles()) |
481 | |
{ |
482 | 0 | if (possiblePom.getName().endsWith(".pom")) |
483 | |
{ |
484 | 0 | result.add(directory.getName()); |
485 | |
} |
486 | |
} |
487 | |
} |
488 | |
} |
489 | 0 | return result; |
490 | |
} |
491 | |
|
492 | |
private List<ArchivaRepositoryMetadata> getMetadatasForManagedRepository( ManagedRepositoryContent managedRepository, String logicalResource ) |
493 | |
{ |
494 | 0 | List<ArchivaRepositoryMetadata> metadatas = new ArrayList<ArchivaRepositoryMetadata>(); |
495 | 0 | File file = new File(managedRepository.getRepoRoot(), logicalResource); |
496 | 0 | if (file.exists()) |
497 | |
{ |
498 | |
try |
499 | |
{ |
500 | 0 | ArchivaRepositoryMetadata existingMetadata = RepositoryMetadataReader.read(file); |
501 | 0 | if (existingMetadata != null) |
502 | |
{ |
503 | 0 | metadatas.add(existingMetadata); |
504 | |
} |
505 | |
} |
506 | 0 | catch (RepositoryMetadataException e) |
507 | |
{ |
508 | 0 | log.debug("Could not read metadata at " + file.getAbsolutePath() + ". Metadata will be removed."); |
509 | 0 | FileUtils.deleteQuietly(file); |
510 | 0 | } |
511 | |
} |
512 | |
|
513 | 0 | Set<String> proxyIds = proxies.get(managedRepository.getId()); |
514 | 0 | if (proxyIds != null) |
515 | |
{ |
516 | 0 | for (String proxyId : proxyIds) |
517 | |
{ |
518 | 0 | ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, logicalResource, proxyId ); |
519 | 0 | if (proxyMetadata != null) |
520 | |
{ |
521 | 0 | metadatas.add(proxyMetadata); |
522 | |
} |
523 | 0 | } |
524 | |
} |
525 | |
|
526 | 0 | return metadatas; |
527 | |
} |
528 | |
|
529 | |
|
530 | |
|
531 | |
|
532 | |
|
533 | |
|
534 | |
|
535 | |
|
536 | |
|
537 | |
|
538 | |
|
539 | |
|
540 | |
|
541 | |
|
542 | |
|
543 | |
|
544 | |
|
545 | |
|
546 | |
|
547 | |
public void updateMetadata( ManagedRepositoryContent managedRepository, ProjectReference reference ) |
548 | |
throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException |
549 | |
{ |
550 | 0 | File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) ); |
551 | |
|
552 | 0 | long lastUpdated = getExistingLastUpdated( metadataFile ); |
553 | |
|
554 | 0 | ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata(); |
555 | 0 | metadata.setGroupId( reference.getGroupId() ); |
556 | 0 | metadata.setArtifactId( reference.getArtifactId() ); |
557 | |
|
558 | |
|
559 | 0 | Set<String> allVersions = managedRepository.getVersions( reference ); |
560 | |
|
561 | |
|
562 | |
|
563 | |
|
564 | |
Set<Plugin> allPlugins; |
565 | 0 | if ( metadataFile.exists() ) |
566 | |
{ |
567 | 0 | allPlugins = new LinkedHashSet<Plugin>( RepositoryMetadataReader.read( metadataFile ).getPlugins() ); |
568 | |
} |
569 | |
else |
570 | |
{ |
571 | 0 | allPlugins = new LinkedHashSet<Plugin>(); |
572 | |
} |
573 | |
|
574 | |
|
575 | 0 | Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() ); |
576 | |
|
577 | 0 | if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) ) |
578 | |
{ |
579 | |
|
580 | 0 | Iterator<String> it = proxiedRepoIds.iterator(); |
581 | 0 | while ( it.hasNext() ) |
582 | |
{ |
583 | 0 | String proxyId = it.next(); |
584 | |
|
585 | 0 | ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId ); |
586 | 0 | if ( proxyMetadata != null ) |
587 | |
{ |
588 | 0 | allVersions.addAll( proxyMetadata.getAvailableVersions() ); |
589 | 0 | allPlugins.addAll( proxyMetadata.getPlugins() ); |
590 | 0 | long proxyLastUpdated = getLastUpdated( proxyMetadata ); |
591 | |
|
592 | 0 | lastUpdated = Math.max( lastUpdated, proxyLastUpdated ); |
593 | |
} |
594 | 0 | } |
595 | |
} |
596 | |
|
597 | 0 | if ( !allVersions.isEmpty() ) |
598 | |
{ |
599 | 0 | updateMetadataVersions( allVersions ,metadata ); |
600 | |
} |
601 | |
else |
602 | |
{ |
603 | |
|
604 | 0 | metadata.setPlugins( new ArrayList<Plugin>( allPlugins ) ); |
605 | |
|
606 | |
|
607 | 0 | metadata.setGroupId( metadata.getGroupId() + "." + metadata.getArtifactId() ); |
608 | 0 | metadata.setArtifactId( null ); |
609 | |
} |
610 | |
|
611 | 0 | if ( lastUpdated > 0 ) |
612 | |
{ |
613 | 0 | metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) ); |
614 | |
} |
615 | |
|
616 | |
|
617 | 0 | RepositoryMetadataWriter.write( metadata, metadataFile ); |
618 | 0 | ChecksummedFile checksum = new ChecksummedFile( metadataFile ); |
619 | 0 | checksum.fixChecksums( algorithms ); |
620 | 0 | } |
621 | |
|
622 | |
private void updateMetadataVersions(Collection<String> allVersions, ArchivaRepositoryMetadata metadata) |
623 | |
{ |
624 | |
|
625 | 0 | List<String> sortedVersions = new ArrayList<String>(allVersions); |
626 | 0 | Collections.sort(sortedVersions, VersionComparator.getInstance()); |
627 | |
|
628 | |
|
629 | 0 | List<String> releasedVersions = new ArrayList<String>(); |
630 | 0 | List<String> snapshotVersions = new ArrayList<String>(); |
631 | |
|
632 | 0 | for (String version : sortedVersions) |
633 | |
{ |
634 | 0 | if (VersionUtil.isSnapshot(version)) |
635 | |
{ |
636 | 0 | snapshotVersions.add(version); |
637 | |
} |
638 | |
else |
639 | |
{ |
640 | 0 | releasedVersions.add(version); |
641 | |
} |
642 | |
} |
643 | |
|
644 | 0 | Collections.sort(releasedVersions, VersionComparator.getInstance()); |
645 | 0 | Collections.sort(snapshotVersions, VersionComparator.getInstance()); |
646 | |
|
647 | 0 | String latestVersion = sortedVersions.get(sortedVersions.size() - 1); |
648 | 0 | String releaseVersion = null; |
649 | |
|
650 | 0 | if (CollectionUtils.isNotEmpty(releasedVersions)) |
651 | |
{ |
652 | 0 | releaseVersion = releasedVersions.get(releasedVersions.size() - 1); |
653 | |
} |
654 | |
|
655 | |
|
656 | 0 | metadata.setAvailableVersions(sortedVersions); |
657 | |
|
658 | 0 | metadata.setLatestVersion(latestVersion); |
659 | 0 | metadata.setReleasedVersion(releaseVersion); |
660 | 0 | } |
661 | |
|
662 | |
private Date toLastUpdatedDate( long lastUpdated ) |
663 | |
{ |
664 | 0 | Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE ); |
665 | 0 | cal.setTimeInMillis( lastUpdated ); |
666 | |
|
667 | 0 | return cal.getTime(); |
668 | |
} |
669 | |
|
670 | |
private long toLastUpdatedLong( String timestampString ) |
671 | |
{ |
672 | |
try |
673 | |
{ |
674 | 0 | Date date = lastUpdatedFormat.parse( timestampString ); |
675 | 0 | Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE ); |
676 | 0 | cal.setTime( date ); |
677 | |
|
678 | 0 | return cal.getTimeInMillis(); |
679 | |
} |
680 | 0 | catch ( ParseException e ) |
681 | |
{ |
682 | 0 | return 0; |
683 | |
} |
684 | |
} |
685 | |
|
686 | |
private long getLastUpdated( ArchivaRepositoryMetadata metadata ) |
687 | |
{ |
688 | 0 | if ( metadata == null ) |
689 | |
{ |
690 | |
|
691 | 0 | return 0; |
692 | |
} |
693 | |
|
694 | |
try |
695 | |
{ |
696 | 0 | String lastUpdated = metadata.getLastUpdated(); |
697 | 0 | if ( StringUtils.isBlank( lastUpdated ) ) |
698 | |
{ |
699 | |
|
700 | 0 | return 0; |
701 | |
} |
702 | |
|
703 | 0 | Date lastUpdatedDate = lastUpdatedFormat.parse( lastUpdated ); |
704 | 0 | return lastUpdatedDate.getTime(); |
705 | |
} |
706 | 0 | catch ( ParseException e ) |
707 | |
{ |
708 | |
|
709 | 0 | return 0; |
710 | |
} |
711 | |
} |
712 | |
|
713 | |
private long getExistingLastUpdated( File metadataFile ) |
714 | |
{ |
715 | 0 | if ( !metadataFile.exists() ) |
716 | |
{ |
717 | |
|
718 | 0 | return 0; |
719 | |
} |
720 | |
|
721 | |
try |
722 | |
{ |
723 | 0 | ArchivaRepositoryMetadata metadata = RepositoryMetadataReader.read( metadataFile ); |
724 | |
|
725 | 0 | return getLastUpdated( metadata ); |
726 | |
} |
727 | 0 | catch ( RepositoryMetadataException e ) |
728 | |
{ |
729 | |
|
730 | 0 | return 0; |
731 | |
} |
732 | |
} |
733 | |
|
734 | |
|
735 | |
|
736 | |
|
737 | |
|
738 | |
|
739 | |
|
740 | |
|
741 | |
|
742 | |
|
743 | |
|
744 | |
|
745 | |
|
746 | |
|
747 | |
|
748 | |
|
749 | |
|
750 | |
public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference ) |
751 | |
throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException |
752 | |
{ |
753 | 0 | File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) ); |
754 | |
|
755 | 0 | long lastUpdated = getExistingLastUpdated( metadataFile ); |
756 | |
|
757 | 0 | ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata(); |
758 | 0 | metadata.setGroupId( reference.getGroupId() ); |
759 | 0 | metadata.setArtifactId( reference.getArtifactId() ); |
760 | |
|
761 | 0 | if ( VersionUtil.isSnapshot( reference.getVersion() ) ) |
762 | |
{ |
763 | |
|
764 | 0 | metadata.setVersion( VersionUtil.getBaseVersion( reference.getVersion() ) ); |
765 | |
|
766 | |
|
767 | |
|
768 | 0 | Set<String> snapshotVersions = gatherSnapshotVersions( managedRepository, reference ); |
769 | |
|
770 | 0 | if ( snapshotVersions.isEmpty() ) |
771 | |
{ |
772 | 0 | throw new ContentNotFoundException( "No snapshot versions found on reference [" |
773 | |
+ VersionedReference.toKey( reference ) + "]." ); |
774 | |
} |
775 | |
|
776 | |
|
777 | 0 | List<String> sortedVersions = new ArrayList<String>(); |
778 | 0 | sortedVersions.addAll( snapshotVersions ); |
779 | 0 | Collections.sort( sortedVersions, new VersionComparator() ); |
780 | |
|
781 | 0 | String latestVersion = sortedVersions.get( sortedVersions.size() - 1 ); |
782 | |
|
783 | 0 | if ( VersionUtil.isUniqueSnapshot( latestVersion ) ) |
784 | |
{ |
785 | |
|
786 | |
|
787 | |
|
788 | 0 | Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( latestVersion ); |
789 | 0 | if ( m.matches() ) |
790 | |
{ |
791 | 0 | metadata.setSnapshotVersion( new SnapshotVersion() ); |
792 | 0 | int buildNumber = NumberUtils.toInt( m.group( 3 ), -1 ); |
793 | 0 | metadata.getSnapshotVersion().setBuildNumber( buildNumber ); |
794 | |
|
795 | 0 | Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) ); |
796 | 0 | if ( mtimestamp.matches() ) |
797 | |
{ |
798 | 0 | String tsDate = mtimestamp.group( 1 ); |
799 | 0 | String tsTime = mtimestamp.group( 2 ); |
800 | |
|
801 | 0 | long snapshotLastUpdated = toLastUpdatedLong( tsDate + tsTime ); |
802 | |
|
803 | 0 | lastUpdated = Math.max( lastUpdated, snapshotLastUpdated ); |
804 | |
|
805 | 0 | metadata.getSnapshotVersion().setTimestamp( m.group( 2 ) ); |
806 | |
} |
807 | |
} |
808 | 0 | } |
809 | 0 | else if ( VersionUtil.isGenericSnapshot( latestVersion ) ) |
810 | |
{ |
811 | |
|
812 | |
|
813 | |
|
814 | 0 | metadata.setSnapshotVersion( new SnapshotVersion() ); |
815 | |
|
816 | |
|
817 | |
|
818 | |
|
819 | |
|
820 | |
|
821 | |
|
822 | |
|
823 | |
|
824 | |
|
825 | |
|
826 | |
|
827 | |
|
828 | |
|
829 | |
|
830 | |
|
831 | |
|
832 | |
|
833 | |
|
834 | |
|
835 | |
|
836 | |
|
837 | |
} |
838 | |
else |
839 | |
{ |
840 | 0 | throw new RepositoryMetadataException( "Unable to process snapshot version <" + latestVersion |
841 | |
+ "> reference <" + reference + ">" ); |
842 | |
} |
843 | 0 | } |
844 | |
else |
845 | |
{ |
846 | |
|
847 | 0 | metadata.setVersion( reference.getVersion() ); |
848 | |
} |
849 | |
|
850 | |
|
851 | 0 | if ( lastUpdated > 0 ) |
852 | |
{ |
853 | 0 | metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) ); |
854 | |
} |
855 | |
|
856 | |
|
857 | 0 | RepositoryMetadataWriter.write( metadata, metadataFile ); |
858 | 0 | ChecksummedFile checksum = new ChecksummedFile( metadataFile ); |
859 | 0 | checksum.fixChecksums( algorithms ); |
860 | 0 | } |
861 | |
|
862 | |
private void initConfigVariables() |
863 | |
{ |
864 | 0 | synchronized ( this.artifactPatterns ) |
865 | |
{ |
866 | 0 | this.artifactPatterns.clear(); |
867 | |
|
868 | 0 | this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) ); |
869 | 0 | } |
870 | |
|
871 | 0 | synchronized ( proxies ) |
872 | |
{ |
873 | 0 | this.proxies.clear(); |
874 | |
|
875 | 0 | List<ProxyConnectorConfiguration> proxyConfigs = configuration.getConfiguration().getProxyConnectors(); |
876 | 0 | for( ProxyConnectorConfiguration proxyConfig: proxyConfigs ) |
877 | |
{ |
878 | 0 | String key = proxyConfig.getSourceRepoId(); |
879 | |
|
880 | 0 | Set<String> remoteRepoIds = this.proxies.get( key ); |
881 | |
|
882 | 0 | if ( remoteRepoIds == null ) |
883 | |
{ |
884 | 0 | remoteRepoIds = new HashSet<String>(); |
885 | |
} |
886 | |
|
887 | 0 | remoteRepoIds.add( proxyConfig.getTargetRepoId() ); |
888 | |
|
889 | 0 | this.proxies.put( key, remoteRepoIds ); |
890 | 0 | } |
891 | 0 | } |
892 | 0 | } |
893 | |
|
894 | |
|
895 | |
|
896 | |
|
897 | |
|
898 | |
|
899 | |
|
900 | |
|
901 | |
|
902 | |
|
903 | |
|
904 | |
public ArtifactReference getFirstArtifact( ManagedRepositoryContent managedRepository, VersionedReference reference ) |
905 | |
throws LayoutException, IOException |
906 | |
{ |
907 | 0 | String path = toPath( reference ); |
908 | |
|
909 | 0 | int idx = path.lastIndexOf( '/' ); |
910 | 0 | if ( idx > 0 ) |
911 | |
{ |
912 | 0 | path = path.substring( 0, idx ); |
913 | |
} |
914 | |
|
915 | 0 | File repoDir = new File( managedRepository.getRepoRoot(), path ); |
916 | |
|
917 | 0 | if ( !repoDir.exists() ) |
918 | |
{ |
919 | 0 | throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: " |
920 | |
+ repoDir.getAbsolutePath() ); |
921 | |
} |
922 | |
|
923 | 0 | if ( !repoDir.isDirectory() ) |
924 | |
{ |
925 | 0 | throw new IOException( "Unable to gather the list of snapshot versions on a non-directory: " |
926 | |
+ repoDir.getAbsolutePath() ); |
927 | |
} |
928 | |
|
929 | 0 | File repoFiles[] = repoDir.listFiles(); |
930 | 0 | for ( int i = 0; i < repoFiles.length; i++ ) |
931 | |
{ |
932 | 0 | if ( repoFiles[i].isDirectory() ) |
933 | |
{ |
934 | |
|
935 | 0 | continue; |
936 | |
} |
937 | |
|
938 | 0 | String relativePath = PathUtil.getRelative( managedRepository.getRepoRoot(), repoFiles[i] ); |
939 | |
|
940 | 0 | if ( filetypes.matchesArtifactPattern( relativePath ) ) |
941 | |
{ |
942 | 0 | ArtifactReference artifact = managedRepository.toArtifactReference( relativePath ); |
943 | |
|
944 | 0 | return artifact; |
945 | |
} |
946 | |
} |
947 | |
|
948 | |
|
949 | 0 | return null; |
950 | |
} |
951 | |
} |