001package org.apache.maven.artifact; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028import java.util.regex.Matcher; 029 030import org.apache.maven.artifact.handler.ArtifactHandler; 031import org.apache.maven.artifact.metadata.ArtifactMetadata; 032import org.apache.maven.artifact.repository.ArtifactRepository; 033import org.apache.maven.artifact.resolver.filter.ArtifactFilter; 034import org.apache.maven.artifact.versioning.ArtifactVersion; 035import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 036import org.apache.maven.artifact.versioning.OverConstrainedVersionException; 037import org.apache.maven.artifact.versioning.VersionRange; 038import org.codehaus.plexus.util.StringUtils; 039 040/** 041 * @author Jason van Zyl 042 */ 043public class DefaultArtifact 044 implements Artifact 045{ 046 private String groupId; 047 048 private String artifactId; 049 050 private String baseVersion; 051 052 private final String type; 053 054 private final String classifier; 055 056 private volatile String scope; 057 058 private volatile File file; 059 060 private ArtifactRepository repository; 061 062 private String downloadUrl; 063 064 private ArtifactFilter dependencyFilter; 065 066 private ArtifactHandler artifactHandler; 067 068 private List<String> dependencyTrail; 069 070 private volatile String version; 071 072 private VersionRange versionRange; 073 074 private volatile boolean resolved; 075 076 private boolean release; 077 078 private List<ArtifactVersion> availableVersions; 079 080 private Map<Object, ArtifactMetadata> metadataMap; 081 082 private boolean optional; 083 084 public DefaultArtifact( String groupId, String artifactId, String version, String scope, String type, 085 String classifier, ArtifactHandler artifactHandler ) 086 { 087 this( groupId, artifactId, VersionRange.createFromVersion( version ), scope, type, classifier, artifactHandler, 088 false ); 089 } 090 091 public DefaultArtifact( String groupId, String artifactId, VersionRange versionRange, String scope, String type, 092 String classifier, ArtifactHandler artifactHandler ) 093 { 094 this( groupId, artifactId, versionRange, scope, type, classifier, artifactHandler, false ); 095 } 096 097 public DefaultArtifact( String groupId, String artifactId, VersionRange versionRange, String scope, String type, 098 String classifier, ArtifactHandler artifactHandler, boolean optional ) 099 { 100 this.groupId = groupId; 101 102 this.artifactId = artifactId; 103 104 this.versionRange = versionRange; 105 106 selectVersionFromNewRangeIfAvailable(); 107 108 this.artifactHandler = artifactHandler; 109 110 this.scope = scope; 111 112 this.type = type; 113 114 if ( classifier == null ) 115 { 116 classifier = artifactHandler.getClassifier(); 117 } 118 119 this.classifier = classifier; 120 121 this.optional = optional; 122 123 validateIdentity(); 124 } 125 126 private void validateIdentity() 127 { 128 if ( empty( groupId ) ) 129 { 130 throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type, 131 "The groupId cannot be empty." ); 132 } 133 134 if ( artifactId == null ) 135 { 136 throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type, 137 "The artifactId cannot be empty." ); 138 } 139 140 if ( type == null ) 141 { 142 throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type, 143 "The type cannot be empty." ); 144 } 145 146 if ( ( version == null ) && ( versionRange == null ) ) 147 { 148 throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type, 149 "The version cannot be empty." ); 150 } 151 } 152 153 private boolean empty( String value ) 154 { 155 return ( value == null ) || ( value.trim().length() < 1 ); 156 } 157 158 public String getClassifier() 159 { 160 return classifier; 161 } 162 163 public boolean hasClassifier() 164 { 165 return StringUtils.isNotEmpty( classifier ); 166 } 167 168 public String getScope() 169 { 170 return scope; 171 } 172 173 public String getGroupId() 174 { 175 return groupId; 176 } 177 178 public String getArtifactId() 179 { 180 return artifactId; 181 } 182 183 public String getVersion() 184 { 185 return version; 186 } 187 188 public void setVersion( String version ) 189 { 190 this.version = version; 191 setBaseVersionInternal( version ); 192 versionRange = null; 193 } 194 195 public String getType() 196 { 197 return type; 198 } 199 200 public void setFile( File file ) 201 { 202 this.file = file; 203 } 204 205 public File getFile() 206 { 207 return file; 208 } 209 210 public ArtifactRepository getRepository() 211 { 212 return repository; 213 } 214 215 public void setRepository( ArtifactRepository repository ) 216 { 217 this.repository = repository; 218 } 219 220 // ---------------------------------------------------------------------- 221 // 222 // ---------------------------------------------------------------------- 223 224 public String getId() 225 { 226 return getDependencyConflictId() + ":" + getBaseVersion(); 227 } 228 229 public String getDependencyConflictId() 230 { 231 StringBuilder sb = new StringBuilder( 128 ); 232 sb.append( getGroupId() ); 233 sb.append( ":" ); 234 appendArtifactTypeClassifierString( sb ); 235 return sb.toString(); 236 } 237 238 private void appendArtifactTypeClassifierString( StringBuilder sb ) 239 { 240 sb.append( getArtifactId() ); 241 sb.append( ":" ); 242 sb.append( getType() ); 243 if ( hasClassifier() ) 244 { 245 sb.append( ":" ); 246 sb.append( getClassifier() ); 247 } 248 } 249 250 public void addMetadata( ArtifactMetadata metadata ) 251 { 252 if ( metadataMap == null ) 253 { 254 metadataMap = new HashMap<Object, ArtifactMetadata>(); 255 } 256 257 ArtifactMetadata m = metadataMap.get( metadata.getKey() ); 258 if ( m != null ) 259 { 260 m.merge( metadata ); 261 } 262 else 263 { 264 metadataMap.put( metadata.getKey(), metadata ); 265 } 266 } 267 268 public Collection<ArtifactMetadata> getMetadataList() 269 { 270 if ( metadataMap == null ) 271 { 272 return Collections.emptyList(); 273 } 274 275 return metadataMap.values(); 276 } 277 278 // ---------------------------------------------------------------------- 279 // Object overrides 280 // ---------------------------------------------------------------------- 281 282 public String toString() 283 { 284 StringBuilder sb = new StringBuilder(); 285 if ( getGroupId() != null ) 286 { 287 sb.append( getGroupId() ); 288 sb.append( ":" ); 289 } 290 appendArtifactTypeClassifierString( sb ); 291 sb.append( ":" ); 292 if ( getBaseVersionInternal() != null ) 293 { 294 sb.append( getBaseVersionInternal() ); 295 } 296 else 297 { 298 sb.append( versionRange.toString() ); 299 } 300 if ( scope != null ) 301 { 302 sb.append( ":" ); 303 sb.append( scope ); 304 } 305 return sb.toString(); 306 } 307 308 public int hashCode() 309 { 310 int result = 17; 311 result = 37 * result + groupId.hashCode(); 312 result = 37 * result + artifactId.hashCode(); 313 result = 37 * result + type.hashCode(); 314 if ( version != null ) 315 { 316 result = 37 * result + version.hashCode(); 317 } 318 result = 37 * result + ( classifier != null ? classifier.hashCode() : 0 ); 319 return result; 320 } 321 322 public boolean equals( Object o ) 323 { 324 if ( o == this ) 325 { 326 return true; 327 } 328 329 if ( !( o instanceof Artifact ) ) 330 { 331 return false; 332 } 333 334 Artifact a = (Artifact) o; 335 336 if ( !a.getGroupId().equals( groupId ) ) 337 { 338 return false; 339 } 340 else if ( !a.getArtifactId().equals( artifactId ) ) 341 { 342 return false; 343 } 344 else if ( !a.getVersion().equals( version ) ) 345 { 346 return false; 347 } 348 else if ( !a.getType().equals( type ) ) 349 { 350 return false; 351 } 352 else if ( a.getClassifier() == null ? classifier != null : !a.getClassifier().equals( classifier ) ) 353 { 354 return false; 355 } 356 357 // We don't consider the version range in the comparison, just the resolved version 358 359 return true; 360 } 361 362 public String getBaseVersion() 363 { 364 if ( baseVersion == null && version != null ) 365 { 366 setBaseVersionInternal( version ); 367 } 368 369 return baseVersion; 370 } 371 372 protected String getBaseVersionInternal() 373 { 374 if ( ( baseVersion == null ) && ( version != null ) ) 375 { 376 setBaseVersionInternal( version ); 377 } 378 379 return baseVersion; 380 } 381 382 public void setBaseVersion( String baseVersion ) 383 { 384 setBaseVersionInternal( baseVersion ); 385 } 386 387 protected void setBaseVersionInternal( String baseVersion ) 388 { 389 Matcher m = VERSION_FILE_PATTERN.matcher( baseVersion ); 390 391 if ( m.matches() ) 392 { 393 this.baseVersion = m.group( 1 ) + "-" + SNAPSHOT_VERSION; 394 } 395 else 396 { 397 this.baseVersion = baseVersion; 398 } 399 } 400 401 public int compareTo( Artifact a ) 402 { 403 int result = groupId.compareTo( a.getGroupId() ); 404 if ( result == 0 ) 405 { 406 result = artifactId.compareTo( a.getArtifactId() ); 407 if ( result == 0 ) 408 { 409 result = type.compareTo( a.getType() ); 410 if ( result == 0 ) 411 { 412 if ( classifier == null ) 413 { 414 if ( a.getClassifier() != null ) 415 { 416 result = 1; 417 } 418 } 419 else 420 { 421 if ( a.getClassifier() != null ) 422 { 423 result = classifier.compareTo( a.getClassifier() ); 424 } 425 else 426 { 427 result = -1; 428 } 429 } 430 if ( result == 0 ) 431 { 432 // We don't consider the version range in the comparison, just the resolved version 433 result = new DefaultArtifactVersion( version ).compareTo( 434 new DefaultArtifactVersion( a.getVersion() ) ); 435 } 436 } 437 } 438 } 439 return result; 440 } 441 442 public void updateVersion( String version, ArtifactRepository localRepository ) 443 { 444 setResolvedVersion( version ); 445 setFile( new File( localRepository.getBasedir(), localRepository.pathOf( this ) ) ); 446 } 447 448 public String getDownloadUrl() 449 { 450 return downloadUrl; 451 } 452 453 public void setDownloadUrl( String downloadUrl ) 454 { 455 this.downloadUrl = downloadUrl; 456 } 457 458 public ArtifactFilter getDependencyFilter() 459 { 460 return dependencyFilter; 461 } 462 463 public void setDependencyFilter( ArtifactFilter artifactFilter ) 464 { 465 dependencyFilter = artifactFilter; 466 } 467 468 public ArtifactHandler getArtifactHandler() 469 { 470 return artifactHandler; 471 } 472 473 public List<String> getDependencyTrail() 474 { 475 return dependencyTrail; 476 } 477 478 public void setDependencyTrail( List<String> dependencyTrail ) 479 { 480 this.dependencyTrail = dependencyTrail; 481 } 482 483 public void setScope( String scope ) 484 { 485 this.scope = scope; 486 } 487 488 public VersionRange getVersionRange() 489 { 490 return versionRange; 491 } 492 493 public void setVersionRange( VersionRange versionRange ) 494 { 495 this.versionRange = versionRange; 496 selectVersionFromNewRangeIfAvailable(); 497 } 498 499 private void selectVersionFromNewRangeIfAvailable() 500 { 501 if ( ( versionRange != null ) && ( versionRange.getRecommendedVersion() != null ) ) 502 { 503 selectVersion( versionRange.getRecommendedVersion().toString() ); 504 } 505 else 506 { 507 version = null; 508 baseVersion = null; 509 } 510 } 511 512 public void selectVersion( String version ) 513 { 514 this.version = version; 515 setBaseVersionInternal( version ); 516 } 517 518 public void setGroupId( String groupId ) 519 { 520 this.groupId = groupId; 521 } 522 523 public void setArtifactId( String artifactId ) 524 { 525 this.artifactId = artifactId; 526 } 527 528 public boolean isSnapshot() 529 { 530 return getBaseVersion() != null 531 && ( getBaseVersion().endsWith( SNAPSHOT_VERSION ) || getBaseVersion().equals( LATEST_VERSION ) ); 532 } 533 534 public void setResolved( boolean resolved ) 535 { 536 this.resolved = resolved; 537 } 538 539 public boolean isResolved() 540 { 541 return resolved; 542 } 543 544 public void setResolvedVersion( String version ) 545 { 546 this.version = version; 547 // retain baseVersion 548 } 549 550 public void setArtifactHandler( ArtifactHandler artifactHandler ) 551 { 552 this.artifactHandler = artifactHandler; 553 } 554 555 public void setRelease( boolean release ) 556 { 557 this.release = release; 558 } 559 560 public boolean isRelease() 561 { 562 return release; 563 } 564 565 public List<ArtifactVersion> getAvailableVersions() 566 { 567 return availableVersions; 568 } 569 570 public void setAvailableVersions( List<ArtifactVersion> availableVersions ) 571 { 572 this.availableVersions = availableVersions; 573 } 574 575 public boolean isOptional() 576 { 577 return optional; 578 } 579 580 public ArtifactVersion getSelectedVersion() 581 throws OverConstrainedVersionException 582 { 583 return versionRange.getSelectedVersion( this ); 584 } 585 586 public boolean isSelectedVersionKnown() 587 throws OverConstrainedVersionException 588 { 589 return versionRange.isSelectedVersionKnown( this ); 590 } 591 592 public void setOptional( boolean optional ) 593 { 594 this.optional = optional; 595 } 596 597}