You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefaultFileUploadService.java 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. package org.apache.archiva.web.api;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. import com.google.common.base.Predicate;
  21. import com.google.common.collect.Iterables;
  22. import org.apache.archiva.admin.model.RepositoryAdminException;
  23. import org.apache.archiva.admin.model.admin.ArchivaAdministration;
  24. import org.apache.archiva.admin.model.beans.ManagedRepository;
  25. import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
  26. import org.apache.archiva.audit.AuditEvent;
  27. import org.apache.archiva.checksum.ChecksumAlgorithm;
  28. import org.apache.archiva.checksum.ChecksummedFile;
  29. import org.apache.archiva.common.utils.VersionComparator;
  30. import org.apache.archiva.common.utils.VersionUtil;
  31. import org.apache.archiva.maven2.metadata.MavenMetadataReader;
  32. import org.apache.archiva.model.ArchivaRepositoryMetadata;
  33. import org.apache.archiva.model.ArtifactReference;
  34. import org.apache.archiva.model.SnapshotVersion;
  35. import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
  36. import org.apache.archiva.repository.ManagedRepositoryContent;
  37. import org.apache.archiva.repository.RepositoryContentFactory;
  38. import org.apache.archiva.repository.RepositoryException;
  39. import org.apache.archiva.repository.RepositoryNotFoundException;
  40. import org.apache.archiva.repository.metadata.MetadataTools;
  41. import org.apache.archiva.repository.metadata.RepositoryMetadataException;
  42. import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
  43. import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
  44. import org.apache.archiva.rest.services.AbstractRestService;
  45. import org.apache.archiva.scheduler.ArchivaTaskScheduler;
  46. import org.apache.archiva.scheduler.repository.model.RepositoryTask;
  47. import org.apache.archiva.web.model.FileMetadata;
  48. import org.apache.archiva.xml.XMLException;
  49. import org.apache.commons.io.FilenameUtils;
  50. import org.apache.commons.io.IOUtils;
  51. import org.apache.commons.lang.BooleanUtils;
  52. import org.apache.commons.lang.StringUtils;
  53. import org.apache.commons.lang.SystemUtils;
  54. import org.apache.cxf.jaxrs.ext.multipart.Attachment;
  55. import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
  56. import org.apache.maven.model.Model;
  57. import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
  58. import org.slf4j.Logger;
  59. import org.slf4j.LoggerFactory;
  60. import org.springframework.stereotype.Service;
  61. import javax.inject.Inject;
  62. import javax.inject.Named;
  63. import javax.servlet.http.HttpServletRequest;
  64. import javax.ws.rs.core.Context;
  65. import javax.ws.rs.core.Response;
  66. import java.io.File;
  67. import java.io.FileInputStream;
  68. import java.io.FileOutputStream;
  69. import java.io.FileWriter;
  70. import java.io.IOException;
  71. import java.text.DateFormat;
  72. import java.text.SimpleDateFormat;
  73. import java.util.ArrayList;
  74. import java.util.Calendar;
  75. import java.util.Collections;
  76. import java.util.Date;
  77. import java.util.Iterator;
  78. import java.util.List;
  79. import java.util.TimeZone;
  80. import java.util.concurrent.CopyOnWriteArrayList;
  81. /**
  82. * @author Olivier Lamy
  83. */
  84. @Service("fileUploadService#rest")
  85. public class DefaultFileUploadService
  86. extends AbstractRestService
  87. implements FileUploadService
  88. {
  89. private Logger log = LoggerFactory.getLogger( getClass() );
  90. @Context
  91. private HttpServletRequest httpServletRequest;
  92. @Inject
  93. private ManagedRepositoryAdmin managedRepositoryAdmin;
  94. @Inject
  95. private RepositoryContentFactory repositoryFactory;
  96. @Inject
  97. private ArchivaAdministration archivaAdministration;
  98. private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
  99. @Inject
  100. @Named(value = "archivaTaskScheduler#repository")
  101. private ArchivaTaskScheduler scheduler;
  102. private String getStringValue( MultipartBody multipartBody, String attachmentId )
  103. throws IOException
  104. {
  105. Attachment attachment = multipartBody.getAttachment( attachmentId );
  106. return attachment == null ? "" : IOUtils.toString( attachment.getDataHandler().getInputStream() );
  107. }
  108. public FileMetadata post( MultipartBody multipartBody )
  109. throws ArchivaRestServiceException
  110. {
  111. try
  112. {
  113. String classifier = getStringValue( multipartBody, "classifier" );
  114. String packaging = getStringValue( multipartBody, "packaging" );
  115. // skygo: http header form pomFile was once sending 1 for true and void for false
  116. // leading to permanent false value for pomFile if using toBoolean(); use , "1", ""
  117. boolean pomFile = BooleanUtils.toBoolean( getStringValue( multipartBody, "pomFile" ) );
  118. Attachment file = multipartBody.getAttachment( "files[]" );
  119. //Content-Disposition: form-data; name="files[]"; filename="org.apache.karaf.features.command-2.2.2.jar"
  120. String fileName = file.getContentDisposition().getParameter( "filename" );
  121. File tmpFile = File.createTempFile( "upload-artifact", ".tmp" );
  122. tmpFile.deleteOnExit();
  123. IOUtils.copy( file.getDataHandler().getInputStream(), new FileOutputStream( tmpFile ) );
  124. FileMetadata fileMetadata = new FileMetadata( fileName, tmpFile.length(), "theurl" );
  125. fileMetadata.setServerFileName( tmpFile.getPath() );
  126. fileMetadata.setClassifier( classifier );
  127. fileMetadata.setDeleteUrl( tmpFile.getName() );
  128. fileMetadata.setPomFile( pomFile );
  129. fileMetadata.setPackaging( packaging );
  130. log.info( "uploading file: {}", fileMetadata );
  131. List<FileMetadata> fileMetadatas = getSessionFilesList();
  132. fileMetadatas.add( fileMetadata );
  133. return fileMetadata;
  134. }
  135. catch ( IOException e )
  136. {
  137. throw new ArchivaRestServiceException( e.getMessage(),
  138. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  139. }
  140. }
  141. /**
  142. * FIXME must be per session synchronized not globally
  143. *
  144. * @return
  145. */
  146. protected synchronized List<FileMetadata> getSessionFilesList()
  147. {
  148. List<FileMetadata> fileMetadatas =
  149. (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY );
  150. if ( fileMetadatas == null )
  151. {
  152. fileMetadatas = new CopyOnWriteArrayList<FileMetadata>();
  153. httpServletRequest.getSession().setAttribute( FILES_SESSION_KEY, fileMetadatas );
  154. }
  155. return fileMetadatas;
  156. }
  157. public Boolean deleteFile( String fileName )
  158. throws ArchivaRestServiceException
  159. {
  160. File file = new File( SystemUtils.getJavaIoTmpDir(), fileName );
  161. log.debug( "delete file:{},exists:{}", file.getPath(), file.exists() );
  162. boolean removed = getSessionFileMetadatas().remove( new FileMetadata( fileName ) );
  163. // try with full name as ui only know the file name
  164. if ( !removed )
  165. {
  166. removed = getSessionFileMetadatas().remove( new FileMetadata( file.getPath() ) );
  167. }
  168. if ( file.exists() )
  169. {
  170. return file.delete();
  171. }
  172. return Boolean.FALSE;
  173. }
  174. public Boolean clearUploadedFiles()
  175. throws ArchivaRestServiceException
  176. {
  177. List<FileMetadata> fileMetadatas = new ArrayList( getSessionFileMetadatas() );
  178. for ( FileMetadata fileMetadata : fileMetadatas )
  179. {
  180. deleteFile( new File( fileMetadata.getServerFileName() ).getPath() );
  181. }
  182. getSessionFileMetadatas().clear();
  183. return Boolean.TRUE;
  184. }
  185. public List<FileMetadata> getSessionFileMetadatas()
  186. throws ArchivaRestServiceException
  187. {
  188. List<FileMetadata> fileMetadatas =
  189. (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY );
  190. return fileMetadatas == null ? Collections.<FileMetadata>emptyList() : fileMetadatas;
  191. }
  192. public Boolean save( String repositoryId, String groupId, String artifactId, String version, String packaging,
  193. boolean generatePom )
  194. throws ArchivaRestServiceException
  195. {
  196. repositoryId = StringUtils.trim( repositoryId );
  197. groupId = StringUtils.trim( groupId );
  198. artifactId = StringUtils.trim( artifactId );
  199. version = StringUtils.trim( version );
  200. packaging = StringUtils.trim( packaging );
  201. List<FileMetadata> fileMetadatas = getSessionFilesList();
  202. if ( fileMetadatas == null || fileMetadatas.isEmpty() )
  203. {
  204. return Boolean.FALSE;
  205. }
  206. try
  207. {
  208. ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository( repositoryId );
  209. if ( managedRepository == null )
  210. {
  211. // TODO i18n ?
  212. throw new ArchivaRestServiceException( "Cannot find managed repository with id " + repositoryId,
  213. Response.Status.BAD_REQUEST.getStatusCode(), null );
  214. }
  215. if ( VersionUtil.isSnapshot( version ) && !managedRepository.isSnapshots() )
  216. {
  217. // TODO i18n ?
  218. throw new ArchivaRestServiceException(
  219. "Managed repository with id " + repositoryId + " do not accept snapshots",
  220. Response.Status.BAD_REQUEST.getStatusCode(), null );
  221. }
  222. }
  223. catch ( RepositoryAdminException e )
  224. {
  225. throw new ArchivaRestServiceException( e.getMessage(),
  226. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  227. }
  228. // get from the session file with groupId/artifactId
  229. Iterable<FileMetadata> filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>()
  230. {
  231. public boolean apply( FileMetadata fileMetadata )
  232. {
  233. return fileMetadata != null && !fileMetadata.isPomFile();
  234. }
  235. } );
  236. Iterator<FileMetadata> iterator = filesToAdd.iterator();
  237. boolean pomGenerated = false;
  238. while ( iterator.hasNext() )
  239. {
  240. FileMetadata fileMetadata = iterator.next();
  241. log.debug( "fileToAdd: {}", fileMetadata );
  242. saveFile( repositoryId, fileMetadata, generatePom && !pomGenerated, groupId, artifactId, version,
  243. packaging );
  244. pomGenerated = true;
  245. deleteFile( fileMetadata.getServerFileName() );
  246. }
  247. filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>()
  248. {
  249. public boolean apply( FileMetadata fileMetadata )
  250. {
  251. return fileMetadata != null && fileMetadata.isPomFile();
  252. }
  253. } );
  254. iterator = filesToAdd.iterator();
  255. while ( iterator.hasNext() )
  256. {
  257. FileMetadata fileMetadata = iterator.next();
  258. log.debug( "fileToAdd: {}", fileMetadata );
  259. savePomFile( repositoryId, fileMetadata, groupId, artifactId, version, packaging );
  260. deleteFile( fileMetadata.getServerFileName() );
  261. }
  262. return Boolean.TRUE;
  263. }
  264. protected void savePomFile( String repositoryId, FileMetadata fileMetadata, String groupId, String artifactId,
  265. String version, String packaging )
  266. throws ArchivaRestServiceException
  267. {
  268. try
  269. {
  270. boolean fixChecksums =
  271. !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
  272. ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
  273. ArtifactReference artifactReference = new ArtifactReference();
  274. artifactReference.setArtifactId( artifactId );
  275. artifactReference.setGroupId( groupId );
  276. artifactReference.setVersion( version );
  277. artifactReference.setClassifier( fileMetadata.getClassifier() );
  278. artifactReference.setType( packaging );
  279. ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
  280. String artifactPath = repository.toPath( artifactReference );
  281. int lastIndex = artifactPath.lastIndexOf( '/' );
  282. String path = artifactPath.substring( 0, lastIndex );
  283. File targetPath = new File( repoConfig.getLocation(), path );
  284. String pomFilename = artifactPath.substring( lastIndex + 1 );
  285. if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) )
  286. {
  287. pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() );
  288. }
  289. pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
  290. copyFile( new File( fileMetadata.getServerFileName() ), targetPath, pomFilename, fixChecksums );
  291. triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE );
  292. queueRepositoryTask( repoConfig.getId(), new File( targetPath, pomFilename ) );
  293. }
  294. catch ( IOException ie )
  295. {
  296. throw new ArchivaRestServiceException( "Error encountered while uploading pom file: " + ie.getMessage(),
  297. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
  298. }
  299. catch ( RepositoryException rep )
  300. {
  301. throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(),
  302. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep );
  303. }
  304. catch ( RepositoryAdminException e )
  305. {
  306. throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(),
  307. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  308. }
  309. }
  310. protected void saveFile( String repositoryId, FileMetadata fileMetadata, boolean generatePom, String groupId,
  311. String artifactId, String version, String packaging )
  312. throws ArchivaRestServiceException
  313. {
  314. try
  315. {
  316. ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
  317. ArtifactReference artifactReference = new ArtifactReference();
  318. artifactReference.setArtifactId( artifactId );
  319. artifactReference.setGroupId( groupId );
  320. artifactReference.setVersion( version );
  321. artifactReference.setClassifier( fileMetadata.getClassifier() );
  322. artifactReference.setType(
  323. StringUtils.isEmpty( fileMetadata.getPackaging() ) ? packaging : fileMetadata.getPackaging() );
  324. ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
  325. String artifactPath = repository.toPath( artifactReference );
  326. int lastIndex = artifactPath.lastIndexOf( '/' );
  327. String path = artifactPath.substring( 0, lastIndex );
  328. File targetPath = new File( repoConfig.getLocation(), path );
  329. log.debug( "artifactPath: {} found targetPath: {}", artifactPath, targetPath );
  330. Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
  331. int newBuildNumber = -1;
  332. String timestamp = null;
  333. File versionMetadataFile = new File( targetPath, MetadataTools.MAVEN_METADATA );
  334. ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile );
  335. if ( VersionUtil.isSnapshot( version ) )
  336. {
  337. TimeZone timezone = TimeZone.getTimeZone( "UTC" );
  338. DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
  339. fmt.setTimeZone( timezone );
  340. timestamp = fmt.format( lastUpdatedTimestamp );
  341. if ( versionMetadata.getSnapshotVersion() != null )
  342. {
  343. newBuildNumber = versionMetadata.getSnapshotVersion().getBuildNumber() + 1;
  344. }
  345. else
  346. {
  347. newBuildNumber = 1;
  348. }
  349. }
  350. if ( !targetPath.exists() )
  351. {
  352. targetPath.mkdirs();
  353. }
  354. String filename = artifactPath.substring( lastIndex + 1 );
  355. if ( VersionUtil.isSnapshot( version ) )
  356. {
  357. filename = filename.replaceAll( VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber );
  358. }
  359. boolean fixChecksums =
  360. !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
  361. try
  362. {
  363. File targetFile = new File( targetPath, filename );
  364. if ( targetFile.exists() && !VersionUtil.isSnapshot( version ) && repoConfig.isBlockRedeployments() )
  365. {
  366. throw new ArchivaRestServiceException(
  367. "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
  368. Response.Status.BAD_REQUEST.getStatusCode(), null );
  369. }
  370. else
  371. {
  372. copyFile( new File( fileMetadata.getServerFileName() ), targetPath, filename, fixChecksums );
  373. triggerAuditEvent( repository.getId(), path + "/" + filename, AuditEvent.UPLOAD_FILE );
  374. queueRepositoryTask( repository.getId(), targetFile );
  375. }
  376. }
  377. catch ( IOException ie )
  378. {
  379. log.error( "IOException copying file: {}", ie.getMessage(), ie );
  380. throw new ArchivaRestServiceException(
  381. "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
  382. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
  383. }
  384. if ( generatePom )
  385. {
  386. String pomFilename = filename;
  387. if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) )
  388. {
  389. pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() );
  390. }
  391. pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
  392. try
  393. {
  394. File generatedPomFile =
  395. createPom( targetPath, pomFilename, fileMetadata, groupId, artifactId, version, packaging );
  396. triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE );
  397. if ( fixChecksums )
  398. {
  399. fixChecksums( generatedPomFile );
  400. }
  401. queueRepositoryTask( repoConfig.getId(), generatedPomFile );
  402. }
  403. catch ( IOException ie )
  404. {
  405. throw new ArchivaRestServiceException(
  406. "Error encountered while writing pom file: " + ie.getMessage(),
  407. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
  408. }
  409. }
  410. // explicitly update only if metadata-updater consumer is not enabled!
  411. if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) )
  412. {
  413. updateProjectMetadata( targetPath.getAbsolutePath(), lastUpdatedTimestamp, timestamp, newBuildNumber,
  414. fixChecksums, fileMetadata, groupId, artifactId, version, packaging );
  415. if ( VersionUtil.isSnapshot( version ) )
  416. {
  417. updateVersionMetadata( versionMetadata, versionMetadataFile, lastUpdatedTimestamp, timestamp,
  418. newBuildNumber, fixChecksums, fileMetadata, groupId, artifactId, version,
  419. packaging );
  420. }
  421. }
  422. }
  423. catch ( RepositoryNotFoundException re )
  424. {
  425. throw new ArchivaRestServiceException( "Target repository cannot be found: " + re.getMessage(),
  426. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), re );
  427. }
  428. catch ( RepositoryException rep )
  429. {
  430. throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(),
  431. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep );
  432. }
  433. catch ( RepositoryAdminException e )
  434. {
  435. throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(),
  436. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  437. }
  438. }
  439. private ArchivaRepositoryMetadata getMetadata( File metadataFile )
  440. throws RepositoryMetadataException
  441. {
  442. ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
  443. if ( metadataFile.exists() )
  444. {
  445. try
  446. {
  447. metadata = MavenMetadataReader.read( metadataFile );
  448. }
  449. catch ( XMLException e )
  450. {
  451. throw new RepositoryMetadataException( e.getMessage(), e );
  452. }
  453. }
  454. return metadata;
  455. }
  456. private File createPom( File targetPath, String filename, FileMetadata fileMetadata, String groupId,
  457. String artifactId, String version, String packaging )
  458. throws IOException
  459. {
  460. Model projectModel = new Model();
  461. projectModel.setModelVersion( "4.0.0" );
  462. projectModel.setGroupId( groupId );
  463. projectModel.setArtifactId( artifactId );
  464. projectModel.setVersion( version );
  465. projectModel.setPackaging( packaging );
  466. File pomFile = new File( targetPath, filename );
  467. MavenXpp3Writer writer = new MavenXpp3Writer();
  468. FileWriter w = new FileWriter( pomFile );
  469. try
  470. {
  471. writer.write( w, projectModel );
  472. }
  473. finally
  474. {
  475. IOUtils.closeQuietly( w );
  476. }
  477. return pomFile;
  478. }
  479. private void fixChecksums( File file )
  480. {
  481. ChecksummedFile checksum = new ChecksummedFile( file );
  482. checksum.fixChecksums( algorithms );
  483. }
  484. private void queueRepositoryTask( String repositoryId, File localFile )
  485. {
  486. RepositoryTask task = new RepositoryTask();
  487. task.setRepositoryId( repositoryId );
  488. task.setResourceFile( localFile );
  489. task.setUpdateRelatedArtifacts( true );
  490. task.setScanAll( false );
  491. try
  492. {
  493. scheduler.queueTask( task );
  494. }
  495. catch ( TaskQueueException e )
  496. {
  497. log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName()
  498. + "']." );
  499. }
  500. }
  501. private void copyFile( File sourceFile, File targetPath, String targetFilename, boolean fixChecksums )
  502. throws IOException
  503. {
  504. FileOutputStream out = null;
  505. FileInputStream input = null;
  506. try
  507. {
  508. out = new FileOutputStream( new File( targetPath, targetFilename ) );
  509. input = new FileInputStream( sourceFile );
  510. IOUtils.copy( input, out );
  511. }
  512. finally
  513. {
  514. IOUtils.closeQuietly( out );
  515. IOUtils.closeQuietly( input );
  516. }
  517. if ( fixChecksums )
  518. {
  519. fixChecksums( new File( targetPath, targetFilename ) );
  520. }
  521. }
  522. /**
  523. * Update artifact level metadata. If it does not exist, create the metadata and fix checksums if necessary.
  524. */
  525. private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
  526. boolean fixChecksums, FileMetadata fileMetadata, String groupId,
  527. String artifactId, String version, String packaging )
  528. throws RepositoryMetadataException
  529. {
  530. List<String> availableVersions = new ArrayList<>();
  531. String latestVersion = version;
  532. File projectDir = new File( targetPath ).getParentFile();
  533. File projectMetadataFile = new File( projectDir, MetadataTools.MAVEN_METADATA );
  534. ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
  535. if ( projectMetadataFile.exists() )
  536. {
  537. availableVersions = projectMetadata.getAvailableVersions();
  538. Collections.sort( availableVersions, VersionComparator.getInstance() );
  539. if ( !availableVersions.contains( version ) )
  540. {
  541. availableVersions.add( version );
  542. }
  543. latestVersion = availableVersions.get( availableVersions.size() - 1 );
  544. }
  545. else
  546. {
  547. availableVersions.add( version );
  548. projectMetadata.setGroupId( groupId );
  549. projectMetadata.setArtifactId( artifactId );
  550. }
  551. if ( projectMetadata.getGroupId() == null )
  552. {
  553. projectMetadata.setGroupId( groupId );
  554. }
  555. if ( projectMetadata.getArtifactId() == null )
  556. {
  557. projectMetadata.setArtifactId( artifactId );
  558. }
  559. projectMetadata.setLatestVersion( latestVersion );
  560. projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
  561. projectMetadata.setAvailableVersions( availableVersions );
  562. if ( !VersionUtil.isSnapshot( version ) )
  563. {
  564. projectMetadata.setReleasedVersion( latestVersion );
  565. }
  566. RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile );
  567. if ( fixChecksums )
  568. {
  569. fixChecksums( projectMetadataFile );
  570. }
  571. }
  572. /**
  573. * Update version level metadata for snapshot artifacts. If it does not exist, create the metadata and fix checksums
  574. * if necessary.
  575. */
  576. private void updateVersionMetadata( ArchivaRepositoryMetadata metadata, File metadataFile,
  577. Date lastUpdatedTimestamp, String timestamp, int buildNumber,
  578. boolean fixChecksums, FileMetadata fileMetadata, String groupId,
  579. String artifactId, String version, String packaging )
  580. throws RepositoryMetadataException
  581. {
  582. if ( !metadataFile.exists() )
  583. {
  584. metadata.setGroupId( groupId );
  585. metadata.setArtifactId( artifactId );
  586. metadata.setVersion( version );
  587. }
  588. if ( metadata.getSnapshotVersion() == null )
  589. {
  590. metadata.setSnapshotVersion( new SnapshotVersion() );
  591. }
  592. metadata.getSnapshotVersion().setBuildNumber( buildNumber );
  593. metadata.getSnapshotVersion().setTimestamp( timestamp );
  594. metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
  595. RepositoryMetadataWriter.write( metadata, metadataFile );
  596. if ( fixChecksums )
  597. {
  598. fixChecksums( metadataFile );
  599. }
  600. }
  601. }