001package org.apache.archiva.web.api; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020 021import com.google.common.base.Predicate; 022import com.google.common.collect.Iterables; 023import org.apache.archiva.admin.model.RepositoryAdminException; 024import org.apache.archiva.admin.model.admin.ArchivaAdministration; 025import org.apache.archiva.admin.model.beans.ManagedRepository; 026import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 027import org.apache.archiva.metadata.model.facets.AuditEvent; 028import org.apache.archiva.checksum.ChecksumAlgorithm; 029import org.apache.archiva.checksum.ChecksummedFile; 030import org.apache.archiva.common.utils.VersionComparator; 031import org.apache.archiva.common.utils.VersionUtil; 032import org.apache.archiva.maven2.metadata.MavenMetadataReader; 033import org.apache.archiva.model.ArchivaRepositoryMetadata; 034import org.apache.archiva.model.ArtifactReference; 035import org.apache.archiva.model.SnapshotVersion; 036import org.apache.archiva.redback.components.taskqueue.TaskQueueException; 037import org.apache.archiva.repository.ManagedRepositoryContent; 038import org.apache.archiva.repository.RepositoryContentFactory; 039import org.apache.archiva.repository.RepositoryException; 040import org.apache.archiva.repository.RepositoryNotFoundException; 041import org.apache.archiva.repository.metadata.MetadataTools; 042import org.apache.archiva.repository.metadata.RepositoryMetadataException; 043import org.apache.archiva.repository.metadata.RepositoryMetadataWriter; 044import org.apache.archiva.rest.api.services.ArchivaRestServiceException; 045import org.apache.archiva.rest.services.AbstractRestService; 046import org.apache.archiva.scheduler.ArchivaTaskScheduler; 047import org.apache.archiva.scheduler.repository.model.RepositoryTask; 048import org.apache.archiva.web.model.FileMetadata; 049import org.apache.archiva.xml.XMLException; 050import org.apache.commons.io.FilenameUtils; 051import org.apache.commons.io.IOUtils; 052import org.apache.commons.lang.BooleanUtils; 053import org.apache.commons.lang.StringUtils; 054import org.apache.commons.lang.SystemUtils; 055import org.apache.cxf.jaxrs.ext.multipart.Attachment; 056import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; 057import org.apache.maven.model.Model; 058import org.apache.maven.model.io.xpp3.MavenXpp3Writer; 059import org.slf4j.Logger; 060import org.slf4j.LoggerFactory; 061import org.springframework.stereotype.Service; 062 063import javax.inject.Inject; 064import javax.inject.Named; 065import javax.servlet.http.HttpServletRequest; 066import javax.ws.rs.core.Context; 067import javax.ws.rs.core.Response; 068import java.io.File; 069import java.io.FileOutputStream; 070import java.io.FileWriter; 071import java.io.IOException; 072import java.net.URLDecoder; 073import java.nio.file.*; 074import java.text.DateFormat; 075import java.text.SimpleDateFormat; 076import java.util.ArrayList; 077import java.util.Calendar; 078import java.util.Collections; 079import java.util.Date; 080import java.util.Iterator; 081import java.util.List; 082import java.util.TimeZone; 083import java.util.concurrent.CopyOnWriteArrayList; 084 085/** 086 * @author Olivier Lamy 087 */ 088@Service("fileUploadService#rest") 089public class DefaultFileUploadService 090 extends AbstractRestService 091 implements FileUploadService 092{ 093 private Logger log = LoggerFactory.getLogger( getClass() ); 094 095 @Context 096 private HttpServletRequest httpServletRequest; 097 098 @Inject 099 private ManagedRepositoryAdmin managedRepositoryAdmin; 100 101 @Inject 102 private RepositoryContentFactory repositoryFactory; 103 104 @Inject 105 private ArchivaAdministration archivaAdministration; 106 107 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 }; 108 109 private final String FS = FileSystems.getDefault().getSeparator(); 110 111 @Inject 112 @Named(value = "archivaTaskScheduler#repository") 113 private ArchivaTaskScheduler scheduler; 114 115 private String getStringValue( MultipartBody multipartBody, String attachmentId ) 116 throws IOException 117 { 118 Attachment attachment = multipartBody.getAttachment( attachmentId ); 119 return attachment == null ? "" : 120 StringUtils.trim(URLDecoder.decode(IOUtils.toString( attachment.getDataHandler().getInputStream() ), "UTF-8")); 121 } 122 123 @Override 124 public FileMetadata post( MultipartBody multipartBody ) 125 throws ArchivaRestServiceException 126 { 127 128 try 129 { 130 131 String classifier = getStringValue( multipartBody, "classifier" ); 132 String packaging = getStringValue( multipartBody, "packaging" ); 133 134 checkParamChars( "classifier", classifier ); 135 checkParamChars( "packaging", packaging); 136 137 // skygo: http header form pomFile was once sending 1 for true and void for false 138 // leading to permanent false value for pomFile if using toBoolean(); use , "1", "" 139 140 boolean pomFile = false; 141 try 142 { 143 pomFile = BooleanUtils.toBoolean( getStringValue( multipartBody, "pomFile" ) ); 144 } 145 catch ( IllegalArgumentException ex ) 146 { 147 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad value for boolean pomFile field.", null); 148 e.setHttpErrorCode(422); 149 e.setFieldName( "pomFile" ); 150 e.setErrorKey("fileupload.malformed.pomFile"); 151 throw e; 152 } 153 154 Attachment file = multipartBody.getAttachment( "files[]" ); 155 156 //Content-Disposition: form-data; name="files[]"; filename="org.apache.karaf.features.command-2.2.2.jar" 157 String fileName = file.getContentDisposition().getParameter( "filename" ); 158 Path fileNamePath = Paths.get(fileName); 159 if (!fileName.equals(fileNamePath.getFileName().toString())) { 160 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad filename in upload content: " + fileName + " - File traversal chars (..|/) are not allowed" 161 , null); 162 e.setHttpErrorCode(422); 163 e.setErrorKey("fileupload.malformed.filename"); 164 throw e; 165 } 166 167 File tmpFile = File.createTempFile( "upload-artifact", ".tmp" ); 168 tmpFile.deleteOnExit(); 169 IOUtils.copy( file.getDataHandler().getInputStream(), new FileOutputStream( tmpFile ) ); 170 FileMetadata fileMetadata = new FileMetadata( fileName, tmpFile.length(), "theurl" ); 171 fileMetadata.setServerFileName( tmpFile.getPath() ); 172 fileMetadata.setClassifier( classifier ); 173 fileMetadata.setDeleteUrl( tmpFile.getName() ); 174 fileMetadata.setPomFile( pomFile ); 175 fileMetadata.setPackaging( packaging ); 176 177 log.info( "uploading file: {}", fileMetadata ); 178 179 List<FileMetadata> fileMetadatas = getSessionFilesList(); 180 181 fileMetadatas.add( fileMetadata ); 182 183 return fileMetadata; 184 } 185 catch ( IOException e ) 186 { 187 throw new ArchivaRestServiceException( e.getMessage(), 188 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 189 } 190 191 } 192 193 /** 194 * FIXME must be per session synchronized not globally 195 * 196 * @return 197 */ 198 protected synchronized List<FileMetadata> getSessionFilesList() 199 { 200 List<FileMetadata> fileMetadatas = 201 (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY ); 202 if ( fileMetadatas == null ) 203 { 204 fileMetadatas = new CopyOnWriteArrayList<>(); 205 httpServletRequest.getSession().setAttribute( FILES_SESSION_KEY, fileMetadatas ); 206 } 207 return fileMetadatas; 208 } 209 210 @Override 211 public Boolean deleteFile( String fileName ) 212 throws ArchivaRestServiceException 213 { 214 // we make sure, that there are no other path components in the filename: 215 String checkedFileName = Paths.get(fileName).getFileName().toString(); 216 File file = new File( SystemUtils.getJavaIoTmpDir(), checkedFileName ); 217 log.debug( "delete file:{},exists:{}", file.getPath(), file.exists() ); 218 boolean removed = getSessionFileMetadatas().remove( new FileMetadata( fileName ) ); 219 // try with full name as ui only know the file name 220 if ( !removed ) 221 { 222 removed = getSessionFileMetadatas().remove( new FileMetadata( file.getPath() ) ); 223 } 224 if (removed && file.exists() ) 225 { 226 return file.delete(); 227 } 228 return Boolean.FALSE; 229 } 230 231 @Override 232 public Boolean clearUploadedFiles() 233 throws ArchivaRestServiceException 234 { 235 List<FileMetadata> fileMetadatas = new ArrayList( getSessionFileMetadatas() ); 236 for ( FileMetadata fileMetadata : fileMetadatas ) 237 { 238 deleteFile( new File( fileMetadata.getServerFileName() ).getPath() ); 239 } 240 getSessionFileMetadatas().clear(); 241 return Boolean.TRUE; 242 } 243 244 @Override 245 public List<FileMetadata> getSessionFileMetadatas() 246 throws ArchivaRestServiceException 247 { 248 List<FileMetadata> fileMetadatas = 249 (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY ); 250 251 return fileMetadatas == null ? Collections.<FileMetadata>emptyList() : fileMetadatas; 252 } 253 254 private boolean hasValidChars(String checkString) { 255 if (checkString.contains(FS)) { 256 return false; 257 } 258 if (checkString.contains("../")) { 259 return false; 260 } 261 if (checkString.contains("/..")) { 262 return false; 263 } 264 return true; 265 } 266 267 private void checkParamChars(String param, String value) throws ArchivaRestServiceException { 268 if (!hasValidChars(value)) { 269 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad characters in " + param, null); 270 e.setHttpErrorCode(422); 271 e.setErrorKey("fileupload.malformed.param"); 272 e.setFieldName(param); 273 throw e; 274 } 275 } 276 277 @Override 278 public Boolean save( String repositoryId, String groupId, String artifactId, String version, String packaging, 279 boolean generatePom ) 280 throws ArchivaRestServiceException 281 { 282 repositoryId = StringUtils.trim( repositoryId ); 283 groupId = StringUtils.trim( groupId ); 284 artifactId = StringUtils.trim( artifactId ); 285 version = StringUtils.trim( version ); 286 packaging = StringUtils.trim( packaging ); 287 288 checkParamChars("repositoryId", repositoryId); 289 checkParamChars("groupId", groupId); 290 checkParamChars("artifactId", artifactId); 291 checkParamChars( "version", version); 292 checkParamChars("packaging", packaging); 293 294 295 List<FileMetadata> fileMetadatas = getSessionFilesList(); 296 if ( fileMetadatas == null || fileMetadatas.isEmpty() ) 297 { 298 return Boolean.FALSE; 299 } 300 301 try 302 { 303 ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository( repositoryId ); 304 305 if ( managedRepository == null ) 306 { 307 // TODO i18n ? 308 throw new ArchivaRestServiceException( "Cannot find managed repository with id " + repositoryId, 309 Response.Status.BAD_REQUEST.getStatusCode(), null ); 310 } 311 312 if ( VersionUtil.isSnapshot( version ) && !managedRepository.isSnapshots() ) 313 { 314 // TODO i18n ? 315 throw new ArchivaRestServiceException( 316 "Managed repository with id " + repositoryId + " do not accept snapshots", 317 Response.Status.BAD_REQUEST.getStatusCode(), null ); 318 } 319 } 320 catch ( RepositoryAdminException e ) 321 { 322 throw new ArchivaRestServiceException( e.getMessage(), 323 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 324 } 325 326 // get from the session file with groupId/artifactId 327 328 Iterable<FileMetadata> filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>() 329 { 330 public boolean apply( FileMetadata fileMetadata ) 331 { 332 return fileMetadata != null && !fileMetadata.isPomFile(); 333 } 334 } ); 335 Iterator<FileMetadata> iterator = filesToAdd.iterator(); 336 boolean pomGenerated = false; 337 while ( iterator.hasNext() ) 338 { 339 FileMetadata fileMetadata = iterator.next(); 340 log.debug( "fileToAdd: {}", fileMetadata ); 341 saveFile( repositoryId, fileMetadata, generatePom && !pomGenerated, groupId, artifactId, version, 342 packaging ); 343 pomGenerated = true; 344 deleteFile( fileMetadata.getServerFileName() ); 345 } 346 347 filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>() 348 { 349 @Override 350 public boolean apply( FileMetadata fileMetadata ) 351 { 352 return fileMetadata != null && fileMetadata.isPomFile(); 353 } 354 } ); 355 356 iterator = filesToAdd.iterator(); 357 while ( iterator.hasNext() ) 358 { 359 FileMetadata fileMetadata = iterator.next(); 360 log.debug( "fileToAdd: {}", fileMetadata ); 361 savePomFile( repositoryId, fileMetadata, groupId, artifactId, version, packaging ); 362 deleteFile( fileMetadata.getServerFileName() ); 363 } 364 365 return Boolean.TRUE; 366 } 367 368 protected void savePomFile( String repositoryId, FileMetadata fileMetadata, String groupId, String artifactId, 369 String version, String packaging ) 370 throws ArchivaRestServiceException 371 { 372 373 try 374 { 375 boolean fixChecksums = 376 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) ); 377 378 ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId ); 379 380 ArtifactReference artifactReference = new ArtifactReference(); 381 artifactReference.setArtifactId( artifactId ); 382 artifactReference.setGroupId( groupId ); 383 artifactReference.setVersion( version ); 384 artifactReference.setClassifier( fileMetadata.getClassifier() ); 385 artifactReference.setType( packaging ); 386 387 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId ); 388 389 String artifactPath = repository.toPath( artifactReference ); 390 391 int lastIndex = artifactPath.lastIndexOf( '/' ); 392 393 String path = artifactPath.substring( 0, lastIndex ); 394 File targetPath = new File( repoConfig.getLocation(), path ); 395 396 String pomFilename = artifactPath.substring( lastIndex + 1 ); 397 if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) ) 398 { 399 pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() ); 400 } 401 pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom"; 402 403 copyFile( new File( fileMetadata.getServerFileName() ), targetPath, pomFilename, fixChecksums ); 404 triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE ); 405 queueRepositoryTask( repoConfig.getId(), new File( targetPath, pomFilename ) ); 406 } 407 catch ( IOException ie ) 408 { 409 throw new ArchivaRestServiceException( "Error encountered while uploading pom file: " + ie.getMessage(), 410 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie ); 411 } 412 catch ( RepositoryException rep ) 413 { 414 throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(), 415 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep ); 416 } 417 catch ( RepositoryAdminException e ) 418 { 419 throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(), 420 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 421 } 422 } 423 424 protected void saveFile( String repositoryId, FileMetadata fileMetadata, boolean generatePom, String groupId, 425 String artifactId, String version, String packaging ) 426 throws ArchivaRestServiceException 427 { 428 try 429 { 430 431 ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId ); 432 433 ArtifactReference artifactReference = new ArtifactReference(); 434 artifactReference.setArtifactId( artifactId ); 435 artifactReference.setGroupId( groupId ); 436 artifactReference.setVersion( version ); 437 artifactReference.setClassifier( fileMetadata.getClassifier() ); 438 artifactReference.setType( 439 StringUtils.isEmpty( fileMetadata.getPackaging() ) ? packaging : fileMetadata.getPackaging() ); 440 441 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId ); 442 443 String artifactPath = repository.toPath( artifactReference ); 444 445 int lastIndex = artifactPath.lastIndexOf( '/' ); 446 447 String path = artifactPath.substring( 0, lastIndex ); 448 File targetPath = new File( repoConfig.getLocation(), path ); 449 450 log.debug( "artifactPath: {} found targetPath: {}", artifactPath, targetPath ); 451 452 Date lastUpdatedTimestamp = Calendar.getInstance().getTime(); 453 int newBuildNumber = -1; 454 String timestamp = null; 455 456 File versionMetadataFile = new File( targetPath, MetadataTools.MAVEN_METADATA ); 457 ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile ); 458 459 if ( VersionUtil.isSnapshot( version ) ) 460 { 461 TimeZone timezone = TimeZone.getTimeZone( "UTC" ); 462 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" ); 463 fmt.setTimeZone( timezone ); 464 timestamp = fmt.format( lastUpdatedTimestamp ); 465 if ( versionMetadata.getSnapshotVersion() != null ) 466 { 467 newBuildNumber = versionMetadata.getSnapshotVersion().getBuildNumber() + 1; 468 } 469 else 470 { 471 newBuildNumber = 1; 472 } 473 } 474 475 if ( !targetPath.exists() ) 476 { 477 targetPath.mkdirs(); 478 } 479 480 String filename = artifactPath.substring( lastIndex + 1 ); 481 if ( VersionUtil.isSnapshot( version ) ) 482 { 483 filename = filename.replaceAll( VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber ); 484 } 485 486 boolean fixChecksums = 487 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) ); 488 489 try 490 { 491 File targetFile = new File( targetPath, filename ); 492 if ( targetFile.exists() && !VersionUtil.isSnapshot( version ) && repoConfig.isBlockRedeployments() ) 493 { 494 throw new ArchivaRestServiceException( 495 "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.", 496 Response.Status.BAD_REQUEST.getStatusCode(), null ); 497 } 498 else 499 { 500 copyFile( new File( fileMetadata.getServerFileName() ), targetPath, filename, fixChecksums ); 501 triggerAuditEvent( repository.getId(), path + "/" + filename, AuditEvent.UPLOAD_FILE ); 502 queueRepositoryTask( repository.getId(), targetFile ); 503 } 504 } 505 catch ( IOException ie ) 506 { 507 log.error( "IOException copying file: {}", ie.getMessage(), ie ); 508 throw new ArchivaRestServiceException( 509 "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.", 510 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie ); 511 } 512 513 if ( generatePom ) 514 { 515 String pomFilename = filename; 516 if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) ) 517 { 518 pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() ); 519 } 520 pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom"; 521 522 try 523 { 524 File generatedPomFile = 525 createPom( targetPath, pomFilename, fileMetadata, groupId, artifactId, version, packaging ); 526 triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE ); 527 if ( fixChecksums ) 528 { 529 fixChecksums( generatedPomFile ); 530 } 531 queueRepositoryTask( repoConfig.getId(), generatedPomFile ); 532 } 533 catch ( IOException ie ) 534 { 535 throw new ArchivaRestServiceException( 536 "Error encountered while writing pom file: " + ie.getMessage(), 537 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie ); 538 } 539 } 540 541 // explicitly update only if metadata-updater consumer is not enabled! 542 if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) ) 543 { 544 updateProjectMetadata( targetPath.getAbsolutePath(), lastUpdatedTimestamp, timestamp, newBuildNumber, 545 fixChecksums, fileMetadata, groupId, artifactId, version, packaging ); 546 547 if ( VersionUtil.isSnapshot( version ) ) 548 { 549 updateVersionMetadata( versionMetadata, versionMetadataFile, lastUpdatedTimestamp, timestamp, 550 newBuildNumber, fixChecksums, fileMetadata, groupId, artifactId, version, 551 packaging ); 552 } 553 } 554 } 555 catch ( RepositoryNotFoundException re ) 556 { 557 throw new ArchivaRestServiceException( "Target repository cannot be found: " + re.getMessage(), 558 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), re ); 559 } 560 catch ( RepositoryException rep ) 561 { 562 throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(), 563 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep ); 564 } 565 catch ( RepositoryAdminException e ) 566 { 567 throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(), 568 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 569 } 570 } 571 572 private ArchivaRepositoryMetadata getMetadata( File metadataFile ) 573 throws RepositoryMetadataException 574 { 575 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata(); 576 if ( metadataFile.exists() ) 577 { 578 try 579 { 580 metadata = MavenMetadataReader.read( metadataFile ); 581 } 582 catch ( XMLException e ) 583 { 584 throw new RepositoryMetadataException( e.getMessage(), e ); 585 } 586 } 587 return metadata; 588 } 589 590 private File createPom( File targetPath, String filename, FileMetadata fileMetadata, String groupId, 591 String artifactId, String version, String packaging ) 592 throws IOException 593 { 594 Model projectModel = new Model(); 595 projectModel.setModelVersion( "4.0.0" ); 596 projectModel.setGroupId( groupId ); 597 projectModel.setArtifactId( artifactId ); 598 projectModel.setVersion( version ); 599 projectModel.setPackaging( packaging ); 600 601 File pomFile = new File( targetPath, filename ); 602 MavenXpp3Writer writer = new MavenXpp3Writer(); 603 604 try (FileWriter w = new FileWriter( pomFile )) 605 { 606 writer.write( w, projectModel ); 607 } 608 609 return pomFile; 610 } 611 612 private void fixChecksums( File file ) 613 { 614 ChecksummedFile checksum = new ChecksummedFile( file ); 615 checksum.fixChecksums( algorithms ); 616 } 617 618 private void queueRepositoryTask( String repositoryId, File localFile ) 619 { 620 RepositoryTask task = new RepositoryTask(); 621 task.setRepositoryId( repositoryId ); 622 task.setResourceFile( localFile ); 623 task.setUpdateRelatedArtifacts( true ); 624 task.setScanAll( false ); 625 626 try 627 { 628 scheduler.queueTask( task ); 629 } 630 catch ( TaskQueueException e ) 631 { 632 log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName() 633 + "']." ); 634 } 635 } 636 637 private void copyFile( File sourceFile, File targetPath, String targetFilename, boolean fixChecksums ) 638 throws IOException 639 { 640 641 Files.copy( sourceFile.toPath(), new File( targetPath, targetFilename ).toPath(), StandardCopyOption.REPLACE_EXISTING, 642 StandardCopyOption.COPY_ATTRIBUTES ); 643 644 if ( fixChecksums ) 645 { 646 fixChecksums( new File( targetPath, targetFilename ) ); 647 } 648 } 649 650 /** 651 * Update artifact level metadata. If it does not exist, create the metadata and fix checksums if necessary. 652 */ 653 private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber, 654 boolean fixChecksums, FileMetadata fileMetadata, String groupId, 655 String artifactId, String version, String packaging ) 656 throws RepositoryMetadataException 657 { 658 List<String> availableVersions = new ArrayList<>(); 659 String latestVersion = version; 660 661 File projectDir = new File( targetPath ).getParentFile(); 662 File projectMetadataFile = new File( projectDir, MetadataTools.MAVEN_METADATA ); 663 664 ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile ); 665 666 if ( projectMetadataFile.exists() ) 667 { 668 availableVersions = projectMetadata.getAvailableVersions(); 669 670 Collections.sort( availableVersions, VersionComparator.getInstance() ); 671 672 if ( !availableVersions.contains( version ) ) 673 { 674 availableVersions.add( version ); 675 } 676 677 latestVersion = availableVersions.get( availableVersions.size() - 1 ); 678 } 679 else 680 { 681 availableVersions.add( version ); 682 683 projectMetadata.setGroupId( groupId ); 684 projectMetadata.setArtifactId( artifactId ); 685 } 686 687 if ( projectMetadata.getGroupId() == null ) 688 { 689 projectMetadata.setGroupId( groupId ); 690 } 691 692 if ( projectMetadata.getArtifactId() == null ) 693 { 694 projectMetadata.setArtifactId( artifactId ); 695 } 696 697 projectMetadata.setLatestVersion( latestVersion ); 698 projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp ); 699 projectMetadata.setAvailableVersions( availableVersions ); 700 701 if ( !VersionUtil.isSnapshot( version ) ) 702 { 703 projectMetadata.setReleasedVersion( latestVersion ); 704 } 705 706 RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile ); 707 708 if ( fixChecksums ) 709 { 710 fixChecksums( projectMetadataFile ); 711 } 712 } 713 714 /** 715 * Update version level metadata for snapshot artifacts. If it does not exist, create the metadata and fix checksums 716 * if necessary. 717 */ 718 private void updateVersionMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, 719 Date lastUpdatedTimestamp, String timestamp, int buildNumber, 720 boolean fixChecksums, FileMetadata fileMetadata, String groupId, 721 String artifactId, String version, String packaging ) 722 throws RepositoryMetadataException 723 { 724 if ( !metadataFile.exists() ) 725 { 726 metadata.setGroupId( groupId ); 727 metadata.setArtifactId( artifactId ); 728 metadata.setVersion( version ); 729 } 730 731 if ( metadata.getSnapshotVersion() == null ) 732 { 733 metadata.setSnapshotVersion( new SnapshotVersion() ); 734 } 735 736 metadata.getSnapshotVersion().setBuildNumber( buildNumber ); 737 metadata.getSnapshotVersion().setTimestamp( timestamp ); 738 metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp ); 739 740 RepositoryMetadataWriter.write( metadata, metadataFile ); 741 742 if ( fixChecksums ) 743 { 744 fixChecksums( metadataFile ); 745 } 746 } 747 748 749}