1 package org.apache.archiva.web.api;
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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
21 import com.google.common.base.Predicate;
22 import com.google.common.collect.Iterables;
23 import org.apache.archiva.admin.model.RepositoryAdminException;
24 import org.apache.archiva.admin.model.admin.ArchivaAdministration;
25 import org.apache.archiva.admin.model.beans.ManagedRepository;
26 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
27 import org.apache.archiva.checksum.ChecksumAlgorithm;
28 import org.apache.archiva.checksum.ChecksumUtil;
29 import org.apache.archiva.checksum.ChecksummedFile;
30 import org.apache.archiva.common.utils.VersionComparator;
31 import org.apache.archiva.common.utils.VersionUtil;
32 import org.apache.archiva.configuration.ArchivaConfiguration;
33 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
34 import org.apache.archiva.metadata.model.facets.AuditEvent;
35 import org.apache.archiva.model.ArchivaRepositoryMetadata;
36 import org.apache.archiva.model.ArtifactReference;
37 import org.apache.archiva.model.SnapshotVersion;
38 import org.apache.archiva.components.taskqueue.TaskQueueException;
39 import org.apache.archiva.repository.Repository;
40 import org.apache.archiva.repository.RepositoryException;
41 import org.apache.archiva.repository.RepositoryNotFoundException;
42 import org.apache.archiva.repository.RepositoryRegistry;
43 import org.apache.archiva.repository.RepositoryType;
44 import org.apache.archiva.repository.content.base.ArtifactUtil;
45 import org.apache.archiva.repository.metadata.MetadataReader;
46 import org.apache.archiva.repository.metadata.base.MetadataTools;
47 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
48 import org.apache.archiva.repository.metadata.base.RepositoryMetadataWriter;
49 import org.apache.archiva.repository.storage.StorageAsset;
50 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
51 import org.apache.archiva.rest.services.AbstractRestService;
52 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
53 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
54 import org.apache.archiva.web.model.FileMetadata;
55 import org.apache.archiva.xml.XMLException;
56 import org.apache.commons.io.FilenameUtils;
57 import org.apache.commons.io.IOUtils;
58 import org.apache.commons.lang3.BooleanUtils;
59 import org.apache.commons.lang3.StringUtils;
60 import org.apache.commons.lang3.SystemUtils;
61 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
62 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
63 import org.apache.maven.model.Model;
64 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67 import org.springframework.stereotype.Service;
69 import javax.annotation.PostConstruct;
70 import javax.inject.Inject;
71 import javax.inject.Named;
72 import javax.servlet.http.HttpServletRequest;
73 import javax.servlet.http.HttpSession;
74 import javax.ws.rs.core.Context;
75 import javax.ws.rs.core.Response;
77 import java.net.URLDecoder;
78 import java.nio.file.*;
79 import java.text.DateFormat;
80 import java.text.SimpleDateFormat;
82 import java.util.concurrent.CopyOnWriteArrayList;
86 * Service for uploading files to the repository.
88 * @author Olivier Lamy
89 * @author Martin Stockhammer
91 @Service("fileUploadService#rest")
92 public class DefaultFileUploadService
93 extends AbstractRestService
94 implements FileUploadService {
95 private Logger log = LoggerFactory.getLogger(getClass());
98 private HttpServletRequest httpServletRequest;
101 private ManagedRepositoryAdmin managedRepositoryAdmin;
104 private ArtifactUtil artifactUtil;
107 private ArchivaAdministration archivaAdministration;
110 ArchivaConfiguration configuration;
112 private List<ChecksumAlgorithm> algorithms;
114 private final String FS = FileSystems.getDefault().getSeparator();
117 @Named(value = "archivaTaskScheduler#repository")
118 private ArchivaTaskScheduler<RepositoryTask> scheduler;
121 private RepositoryRegistry repositoryRegistry;
123 private String getStringValue(MultipartBody multipartBody, String attachmentId)
125 Attachment attachment = multipartBody.getAttachment(attachmentId);
126 return attachment == null ? "" :
127 StringUtils.trim(URLDecoder.decode(IOUtils.toString(attachment.getDataHandler().getInputStream(), "UTF-8"), "UTF-8"));
131 private void initialize() {
132 algorithms = ChecksumUtil.getAlgorithms(configuration.getConfiguration().getArchivaRuntimeConfiguration().getChecksumTypes());
136 public FileMetadata post(MultipartBody multipartBody)
137 throws ArchivaRestServiceException {
141 String classifier = getStringValue(multipartBody, "classifier");
142 String packaging = getStringValue(multipartBody, "packaging");
144 checkParamChars("classifier", classifier);
145 checkParamChars("packaging", packaging);
147 // skygo: http header form pomFile was once sending 1 for true and void for false
148 // leading to permanent false value for pomFile if using toBoolean(); use , "1", ""
150 boolean pomFile = false;
152 pomFile = BooleanUtils.toBoolean(getStringValue(multipartBody, "pomFile"));
153 } catch (IllegalArgumentException ex) {
154 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad value for boolean pomFile field.", null);
155 e.setHttpErrorCode(422);
156 e.setFieldName("pomFile");
157 e.setErrorKey("fileupload.malformed.pomFile");
161 Attachment file = multipartBody.getAttachment("files[]");
163 //Content-Disposition: form-data; name="files[]"; filename="org.apache.karaf.features.command-2.2.2.jar"
164 String fileName = file.getContentDisposition().getParameter("filename");
165 Path fileNamePath = Paths.get(fileName);
166 if (!fileName.equals(fileNamePath.getFileName().toString())) {
167 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad filename in upload content: " + fileName + " - File traversal chars (..|/) are not allowed"
169 e.setHttpErrorCode(422);
170 e.setErrorKey("fileupload.malformed.filename");
174 Path tmpFile = Files.createTempFile("upload-artifact", ".tmp");
175 tmpFile.toFile().deleteOnExit();
176 IOUtils.copy(file.getDataHandler().getInputStream(), new FileOutputStream(tmpFile.toFile()));
177 FileMetadata fileMetadata = new FileMetadata(fileName, Files.size(tmpFile), "theurl");
178 fileMetadata.setServerFileName(tmpFile.toString());
179 fileMetadata.setClassifier(classifier);
180 fileMetadata.setDeleteUrl(tmpFile.getFileName().toString());
181 fileMetadata.setPomFile(pomFile);
182 fileMetadata.setPackaging(packaging);
184 log.info("uploading file: {}", fileMetadata);
186 List<FileMetadata> fileMetadatas = getSessionFilesList();
188 fileMetadatas.add(fileMetadata);
191 } catch (IOException e) {
192 throw new ArchivaRestServiceException(e.getMessage(),
193 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
199 * @return The file list from the session.
201 @SuppressWarnings("unchecked")
202 protected List<FileMetadata> getSessionFilesList() {
203 final HttpSession session = httpServletRequest.getSession();
204 List<FileMetadata> fileMetadata = (List<FileMetadata>) session.getAttribute(FILES_SESSION_KEY);
205 // Double check with synchronization, we assume, that httpServletRequest is
206 // fully initialized (no volatile)
207 if (fileMetadata == null) {
208 synchronized (session) {
209 fileMetadata = (List<FileMetadata>) session.getAttribute(FILES_SESSION_KEY);
210 if (fileMetadata == null) {
211 fileMetadata = new CopyOnWriteArrayList<>();
212 session.setAttribute(FILES_SESSION_KEY, fileMetadata);
220 public Boolean deleteFile(String fileName)
221 throws ArchivaRestServiceException {
222 log.debug("Deleting file {}", fileName);
223 // we make sure, that there are no other path components in the filename:
224 String checkedFileName = Paths.get(fileName).getFileName().toString();
225 Path file = SystemUtils.getJavaIoTmpDir().toPath().resolve(checkedFileName);
226 log.debug("delete file:{},exists:{}", file, Files.exists(file));
227 boolean removed = getSessionFileMetadatas().remove(new FileMetadata(fileName));
228 // try with full name as ui only know the file name
230 removed = getSessionFileMetadatas().remove(new FileMetadata(file.toString()));
234 Files.deleteIfExists(file);
236 } catch (IOException e) {
237 log.error("Could not delete file {}: {}", file, e.getMessage(), e);
240 return Boolean.FALSE;
244 public Boolean clearUploadedFiles()
245 throws ArchivaRestServiceException {
246 List<FileMetadata> fileMetadatas = new ArrayList<>(getSessionFileMetadatas());
247 for (FileMetadata fileMetadata : fileMetadatas) {
248 deleteFile(Paths.get(fileMetadata.getServerFileName()).toString());
250 getSessionFileMetadatas().clear();
255 public List<FileMetadata> getSessionFileMetadatas()
256 throws ArchivaRestServiceException {
257 return getSessionFilesList();
261 private boolean hasValidChars(String checkString) {
262 if (checkString.contains(FS)) {
265 if (checkString.contains("../")) {
268 if (checkString.contains("/..")) {
274 private void checkParamChars(String param, String value) throws ArchivaRestServiceException {
275 if (!hasValidChars(value)) {
276 ArchivaRestServiceException e = new ArchivaRestServiceException("Bad characters in " + param, null);
277 e.setHttpErrorCode(422);
278 e.setErrorKey("fileupload.malformed.param");
279 e.setFieldName(param);
285 public Boolean save(String repositoryId, String groupId, String artifactId, String version, String packaging,
287 throws ArchivaRestServiceException {
288 repositoryId = StringUtils.trim(repositoryId);
289 groupId = StringUtils.trim(groupId);
290 artifactId = StringUtils.trim(artifactId);
291 version = StringUtils.trim(version);
292 packaging = StringUtils.trim(packaging);
294 checkParamChars("repositoryId", repositoryId);
295 checkParamChars("groupId", groupId);
296 checkParamChars("artifactId", artifactId);
297 checkParamChars("version", version);
298 checkParamChars("packaging", packaging);
301 List<FileMetadata> fileMetadatas = getSessionFilesList();
302 if (fileMetadatas == null || fileMetadatas.isEmpty()) {
303 return Boolean.FALSE;
307 ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository(repositoryId);
309 if (managedRepository == null) {
311 throw new ArchivaRestServiceException("Cannot find managed repository with id " + repositoryId,
312 Response.Status.BAD_REQUEST.getStatusCode(), null);
315 if (VersionUtil.isSnapshot(version) && !managedRepository.isSnapshots()) {
317 throw new ArchivaRestServiceException(
318 "Managed repository with id " + repositoryId + " do not accept snapshots",
319 Response.Status.BAD_REQUEST.getStatusCode(), null);
321 } catch (RepositoryAdminException e) {
322 throw new ArchivaRestServiceException(e.getMessage(),
323 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
326 // get from the session file with groupId/artifactId
328 Iterable<FileMetadata> filesToAdd = Iterables.filter(fileMetadatas, new Predicate<FileMetadata>() {
329 public boolean apply(FileMetadata fileMetadata) {
330 return fileMetadata != null && !fileMetadata.isPomFile();
333 Iterator<FileMetadata> iterator = filesToAdd.iterator();
334 boolean pomGenerated = false;
335 while (iterator.hasNext()) {
336 FileMetadata fileMetadata = iterator.next();
337 log.debug("fileToAdd: {}", fileMetadata);
338 saveFile(repositoryId, fileMetadata, generatePom && !pomGenerated, groupId, artifactId, version,
341 deleteFile(fileMetadata.getServerFileName());
344 filesToAdd = Iterables.filter(fileMetadatas, new Predicate<FileMetadata>() {
346 public boolean apply(FileMetadata fileMetadata) {
347 return fileMetadata != null && fileMetadata.isPomFile();
351 iterator = filesToAdd.iterator();
352 while (iterator.hasNext()) {
353 FileMetadata fileMetadata = iterator.next();
354 log.debug("fileToAdd: {}", fileMetadata);
355 savePomFile(repositoryId, fileMetadata, groupId, artifactId, version, packaging);
356 deleteFile(fileMetadata.getServerFileName());
362 protected void savePomFile(String repositoryId, FileMetadata fileMetadata, String groupId, String artifactId,
363 String version, String packaging)
364 throws ArchivaRestServiceException {
366 log.debug("Saving POM");
368 boolean fixChecksums =
369 !(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
371 org.apache.archiva.repository.ManagedRepository repoConfig = repositoryRegistry.getManagedRepository(repositoryId);
373 ArtifactReference artifactReference = createArtifactRef(fileMetadata, groupId, artifactId, version);
374 artifactReference.setType(packaging);
376 StorageAsset pomPath = artifactUtil.getArtifactAsset(repoConfig, artifactReference);
377 StorageAsset targetPath = pomPath.getParent();
379 String pomFilename = pomPath.getName();
380 if (StringUtils.isNotEmpty(fileMetadata.getClassifier())) {
381 pomFilename = StringUtils.remove(pomFilename, "-" + fileMetadata.getClassifier());
383 pomFilename = FilenameUtils.removeExtension(pomFilename) + ".pom";
385 copyFile(Paths.get(fileMetadata.getServerFileName()), targetPath, pomFilename, fixChecksums);
386 triggerAuditEvent(repoConfig.getId(), targetPath.resolve(pomFilename).toString(), AuditEvent.UPLOAD_FILE);
387 queueRepositoryTask(repoConfig.getId(), targetPath.resolve(pomFilename));
388 log.debug("Finished Saving POM");
389 } catch (IOException ie) {
390 log.error("IOException for POM {}", ie.getMessage());
391 throw new ArchivaRestServiceException("Error encountered while uploading pom file: " + ie.getMessage(),
392 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
393 } catch (RepositoryException rep) {
394 log.error("RepositoryException for POM {}", rep.getMessage());
395 throw new ArchivaRestServiceException("Repository exception: " + rep.getMessage(),
396 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep);
397 } catch (RepositoryAdminException e) {
398 log.error("RepositoryAdminException for POM {}", e.getMessage());
399 throw new ArchivaRestServiceException("RepositoryAdmin exception: " + e.getMessage(),
400 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
404 protected void saveFile(String repositoryId, FileMetadata fileMetadata, boolean generatePom, String groupId,
405 String artifactId, String version, String packaging)
406 throws ArchivaRestServiceException {
407 log.debug("Saving file");
410 org.apache.archiva.repository.ManagedRepository repoConfig = repositoryRegistry.getManagedRepository(repositoryId);
412 ArtifactReference artifactReference = createArtifactRef(fileMetadata, groupId, artifactId, version);
413 artifactReference.setType(
414 StringUtils.isEmpty(fileMetadata.getPackaging()) ? packaging : fileMetadata.getPackaging());
416 StorageAsset artifactPath = artifactUtil.getArtifactAsset(repoConfig, artifactReference);
417 StorageAsset targetPath = artifactPath.getParent();
419 log.debug("artifactPath: {} found targetPath: {}", artifactPath, targetPath);
421 Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
422 int newBuildNumber = -1;
423 String timestamp = null;
425 StorageAsset versionMetadataFile = targetPath.resolve(MetadataTools.MAVEN_METADATA);
426 ArchivaRepositoryMetadata versionMetadata = getMetadata(versionMetadataFile);
428 if (VersionUtil.isSnapshot(version)) {
429 TimeZone timezone = TimeZone.getTimeZone("UTC");
430 DateFormat fmt = new SimpleDateFormat("yyyyMMdd.HHmmss");
431 fmt.setTimeZone(timezone);
432 timestamp = fmt.format(lastUpdatedTimestamp);
433 if (versionMetadata.getSnapshotVersion() != null) {
434 newBuildNumber = versionMetadata.getSnapshotVersion().getBuildNumber() + 1;
440 if (!targetPath.exists()) {
444 String filename = artifactPath.getName().toString();
445 if (VersionUtil.isSnapshot(version)) {
446 filename = filename.replaceAll(VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber);
449 // We always fix checksums for newly uploaded files, even if the content consumer is active.
450 boolean fixChecksums = true;
451 // !(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
454 StorageAsset targetFile = targetPath.resolve(filename);
455 if (targetFile.exists() && !VersionUtil.isSnapshot(version) && repoConfig.blocksRedeployments()) {
456 throw new ArchivaRestServiceException(
457 "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
458 Response.Status.BAD_REQUEST.getStatusCode(), null);
460 copyFile(Paths.get(fileMetadata.getServerFileName()), targetPath, filename, fixChecksums);
461 triggerAuditEvent(repoConfig.getId(), artifactPath.toString(), AuditEvent.UPLOAD_FILE);
462 queueRepositoryTask(repoConfig.getId(), targetFile);
464 } catch (IOException ie) {
465 log.error("IOException copying file: {}", ie.getMessage(), ie);
466 throw new ArchivaRestServiceException(
467 "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
468 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
472 String pomFilename = filename;
473 if (StringUtils.isNotEmpty(fileMetadata.getClassifier())) {
474 pomFilename = StringUtils.remove(pomFilename, "-" + fileMetadata.getClassifier());
476 pomFilename = FilenameUtils.removeExtension(pomFilename) + ".pom";
479 StorageAsset generatedPomFile =
480 createPom(targetPath, pomFilename, fileMetadata, groupId, artifactId, version, packaging);
481 triggerAuditEvent(repoConfig.getId(), targetPath.resolve(pomFilename).toString(), AuditEvent.UPLOAD_FILE);
483 fixChecksums(generatedPomFile);
485 queueRepositoryTask(repoConfig.getId(), generatedPomFile);
486 } catch (IOException ie) {
487 throw new ArchivaRestServiceException(
488 "Error encountered while writing pom file: " + ie.getMessage(),
489 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
493 // explicitly update only if metadata-updater consumer is not enabled!
494 if (!archivaAdministration.getKnownContentConsumers().contains("metadata-updater")) {
495 updateProjectMetadata(targetPath, lastUpdatedTimestamp, timestamp, newBuildNumber,
496 fixChecksums, fileMetadata, groupId, artifactId, version, packaging);
498 if (VersionUtil.isSnapshot(version)) {
499 updateVersionMetadata(versionMetadata, versionMetadataFile, lastUpdatedTimestamp, timestamp,
500 newBuildNumber, fixChecksums, fileMetadata, groupId, artifactId, version,
504 } catch (RepositoryNotFoundException re) {
505 log.error("RepositoryNotFoundException during save {}", re.getMessage());
506 re.printStackTrace();
507 throw new ArchivaRestServiceException("Target repository cannot be found: " + re.getMessage(),
508 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), re);
509 } catch (RepositoryException rep) {
510 log.error("RepositoryException during save {}", rep.getMessage());
511 throw new ArchivaRestServiceException("Repository exception: " + rep.getMessage(),
512 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep);
513 } catch (RepositoryAdminException e) {
514 log.error("RepositoryAdminException during save {}", e.getMessage());
515 throw new ArchivaRestServiceException("RepositoryAdmin exception: " + e.getMessage(),
516 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
517 } catch (IOException e) {
518 log.error("IOException during save {}", e.getMessage());
519 throw new ArchivaRestServiceException("Repository exception " + e.getMessage(),
520 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
524 private ArtifactReference createArtifactRef(FileMetadata fileMetadata, String groupId, String artifactId, String version) {
525 ArtifactReference artifactReference = new ArtifactReference();
526 artifactReference.setArtifactId(artifactId);
527 artifactReference.setGroupId(groupId);
528 artifactReference.setVersion(version);
529 artifactReference.setClassifier(fileMetadata.getClassifier());
530 return artifactReference;
533 private ArchivaRepositoryMetadata getMetadata(StorageAsset metadataFile)
534 throws RepositoryMetadataException {
535 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
536 if (metadataFile.exists()) {
537 Repository repo = repositoryRegistry.getRepositoryOfAsset( metadataFile );
538 RepositoryType type = repo == null ? RepositoryType.MAVEN : repo.getType( );
539 MetadataReader metadataReader = repositoryRegistry.getMetadataReader( type );
540 metadata = metadataReader.read(metadataFile);
545 private StorageAsset createPom(StorageAsset targetPath, String filename, FileMetadata fileMetadata, String groupId,
546 String artifactId, String version, String packaging)
548 Model projectModel = new Model();
549 projectModel.setModelVersion("4.0.0");
550 projectModel.setGroupId(groupId);
551 projectModel.setArtifactId(artifactId);
552 projectModel.setVersion(version);
553 projectModel.setPackaging(packaging);
555 StorageAsset pomFile = targetPath.resolve(filename);
556 MavenXpp3Writer writer = new MavenXpp3Writer();
558 try (Writer w = new OutputStreamWriter(pomFile.getWriteStream(true))) {
559 writer.write(w, projectModel);
565 private void fixChecksums(StorageAsset file) {
566 ChecksummedFile checksum = new ChecksummedFile(file.getFilePath());
567 checksum.fixChecksums(algorithms);
570 private void queueRepositoryTask(String repositoryId, StorageAsset localFile) {
571 RepositoryTask task = new RepositoryTask();
572 task.setRepositoryId(repositoryId);
573 task.setResourceFile(localFile);
574 task.setUpdateRelatedArtifacts(true);
575 task.setScanAll(false);
578 scheduler.queueTask(task);
579 } catch (TaskQueueException e) {
580 log.error("Unable to queue repository task to execute consumers on resource file ['{}"
581 + "'].", localFile.getName());
585 private void copyFile(Path sourceFile, StorageAsset targetPath, String targetFilename, boolean fixChecksums)
588 targetPath.resolve(targetFilename).replaceDataFromFile(sourceFile);
591 fixChecksums(targetPath.resolve(targetFilename));
596 * Update artifact level metadata. If it does not exist, create the metadata and fix checksums if necessary.
598 private void updateProjectMetadata(StorageAsset targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
599 boolean fixChecksums, FileMetadata fileMetadata, String groupId,
600 String artifactId, String version, String packaging)
601 throws RepositoryMetadataException {
602 List<String> availableVersions = new ArrayList<>();
603 String latestVersion = version;
605 StorageAsset projectDir = targetPath.getParent();
606 StorageAsset projectMetadataFile = projectDir.resolve(MetadataTools.MAVEN_METADATA);
608 ArchivaRepositoryMetadata projectMetadata = getMetadata(projectMetadataFile);
610 if (projectMetadataFile.exists()) {
611 availableVersions = projectMetadata.getAvailableVersions();
613 Collections.sort(availableVersions, VersionComparator.getInstance());
615 if (!availableVersions.contains(version)) {
616 availableVersions.add(version);
619 latestVersion = availableVersions.get(availableVersions.size() - 1);
621 availableVersions.add(version);
623 projectMetadata.setGroupId(groupId);
624 projectMetadata.setArtifactId(artifactId);
627 if (projectMetadata.getGroupId() == null) {
628 projectMetadata.setGroupId(groupId);
631 if (projectMetadata.getArtifactId() == null) {
632 projectMetadata.setArtifactId(artifactId);
635 projectMetadata.setLatestVersion(latestVersion);
636 projectMetadata.setLastUpdatedTimestamp(lastUpdatedTimestamp);
637 projectMetadata.setAvailableVersions(availableVersions);
639 if (!VersionUtil.isSnapshot(version)) {
640 projectMetadata.setReleasedVersion(latestVersion);
643 RepositoryMetadataWriter.write(projectMetadata, projectMetadataFile);
646 fixChecksums(projectMetadataFile);
651 * Update version level metadata for snapshot artifacts. If it does not exist, create the metadata and fix checksums
654 private void updateVersionMetadata(ArchivaRepositoryMetadata metadata, StorageAsset metadataFile,
655 Date lastUpdatedTimestamp, String timestamp, int buildNumber,
656 boolean fixChecksums, FileMetadata fileMetadata, String groupId,
657 String artifactId, String version, String packaging)
658 throws RepositoryMetadataException {
659 if (!metadataFile.exists()) {
660 metadata.setGroupId(groupId);
661 metadata.setArtifactId(artifactId);
662 metadata.setVersion(version);
665 if (metadata.getSnapshotVersion() == null) {
666 metadata.setSnapshotVersion(new SnapshotVersion());
669 metadata.getSnapshotVersion().setBuildNumber(buildNumber);
670 metadata.getSnapshotVersion().setTimestamp(timestamp);
671 metadata.setLastUpdatedTimestamp(lastUpdatedTimestamp);
673 RepositoryMetadataWriter.write(metadata, metadataFile);
676 fixChecksums(metadataFile);