blob: a3f8c09135892129b497f08dad4703dee7746144 [file] [log] [blame]
package org.apache.archiva.web.api;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.admin.ArchivaAdministration;
import org.apache.archiva.admin.model.beans.ManagedRepository;
import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksumUtil;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.maven2.metadata.MavenMetadataReader;
import org.apache.archiva.metadata.model.facets.AuditEvent;
import org.apache.archiva.model.ArchivaRepositoryMetadata;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.SnapshotVersion;
import org.apache.archiva.components.taskqueue.TaskQueueException;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryNotFoundException;
import org.apache.archiva.repository.content.base.ArtifactUtil;
import org.apache.archiva.repository.metadata.base.MetadataTools;
import org.apache.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.archiva.repository.metadata.base.RepositoryMetadataWriter;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.rest.services.AbstractRestService;
import org.apache.archiva.scheduler.ArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.model.RepositoryTask;
import org.apache.archiva.web.model.FileMetadata;
import org.apache.archiva.xml.XMLException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.*;
import java.net.URLDecoder;
import java.nio.file.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
*
* Service for uploading files to the repository.
*
* @author Olivier Lamy
* @author Martin Stockhammer
*/
@Service("fileUploadService#rest")
public class DefaultFileUploadService
extends AbstractRestService
implements FileUploadService {
private Logger log = LoggerFactory.getLogger(getClass());
@Context
private HttpServletRequest httpServletRequest;
@Inject
private ManagedRepositoryAdmin managedRepositoryAdmin;
@Inject
private ArtifactUtil artifactUtil;
@Inject
private ArchivaAdministration archivaAdministration;
@Inject
ArchivaConfiguration configuration;
private List<ChecksumAlgorithm> algorithms;
private final String FS = FileSystems.getDefault().getSeparator();
@Inject
@Named(value = "archivaTaskScheduler#repository")
private ArchivaTaskScheduler<RepositoryTask> scheduler;
private String getStringValue(MultipartBody multipartBody, String attachmentId)
throws IOException {
Attachment attachment = multipartBody.getAttachment(attachmentId);
return attachment == null ? "" :
StringUtils.trim(URLDecoder.decode(IOUtils.toString(attachment.getDataHandler().getInputStream(), "UTF-8"), "UTF-8"));
}
@PostConstruct
private void initialize() {
algorithms = ChecksumUtil.getAlgorithms(configuration.getConfiguration().getArchivaRuntimeConfiguration().getChecksumTypes());
}
@Override
public FileMetadata post(MultipartBody multipartBody)
throws ArchivaRestServiceException {
try {
String classifier = getStringValue(multipartBody, "classifier");
String packaging = getStringValue(multipartBody, "packaging");
checkParamChars("classifier", classifier);
checkParamChars("packaging", packaging);
// skygo: http header form pomFile was once sending 1 for true and void for false
// leading to permanent false value for pomFile if using toBoolean(); use , "1", ""
boolean pomFile = false;
try {
pomFile = BooleanUtils.toBoolean(getStringValue(multipartBody, "pomFile"));
} catch (IllegalArgumentException ex) {
ArchivaRestServiceException e = new ArchivaRestServiceException("Bad value for boolean pomFile field.", null);
e.setHttpErrorCode(422);
e.setFieldName("pomFile");
e.setErrorKey("fileupload.malformed.pomFile");
throw e;
}
Attachment file = multipartBody.getAttachment("files[]");
//Content-Disposition: form-data; name="files[]"; filename="org.apache.karaf.features.command-2.2.2.jar"
String fileName = file.getContentDisposition().getParameter("filename");
Path fileNamePath = Paths.get(fileName);
if (!fileName.equals(fileNamePath.getFileName().toString())) {
ArchivaRestServiceException e = new ArchivaRestServiceException("Bad filename in upload content: " + fileName + " - File traversal chars (..|/) are not allowed"
, null);
e.setHttpErrorCode(422);
e.setErrorKey("fileupload.malformed.filename");
throw e;
}
Path tmpFile = Files.createTempFile("upload-artifact", ".tmp");
tmpFile.toFile().deleteOnExit();
IOUtils.copy(file.getDataHandler().getInputStream(), new FileOutputStream(tmpFile.toFile()));
FileMetadata fileMetadata = new FileMetadata(fileName, Files.size(tmpFile), "theurl");
fileMetadata.setServerFileName(tmpFile.toString());
fileMetadata.setClassifier(classifier);
fileMetadata.setDeleteUrl(tmpFile.getFileName().toString());
fileMetadata.setPomFile(pomFile);
fileMetadata.setPackaging(packaging);
log.info("uploading file: {}", fileMetadata);
List<FileMetadata> fileMetadatas = getSessionFilesList();
fileMetadatas.add(fileMetadata);
return fileMetadata;
} catch (IOException e) {
throw new ArchivaRestServiceException(e.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
}
}
/**
* @return The file list from the session.
*/
@SuppressWarnings("unchecked")
protected List<FileMetadata> getSessionFilesList() {
final HttpSession session = httpServletRequest.getSession();
List<FileMetadata> fileMetadata = (List<FileMetadata>) session.getAttribute(FILES_SESSION_KEY);
// Double check with synchronization, we assume, that httpServletRequest is
// fully initialized (no volatile)
if (fileMetadata == null) {
synchronized (session) {
fileMetadata = (List<FileMetadata>) session.getAttribute(FILES_SESSION_KEY);
if (fileMetadata == null) {
fileMetadata = new CopyOnWriteArrayList<>();
session.setAttribute(FILES_SESSION_KEY, fileMetadata);
}
}
}
return fileMetadata;
}
@Override
public Boolean deleteFile(String fileName)
throws ArchivaRestServiceException {
log.debug("Deleting file {}", fileName);
// we make sure, that there are no other path components in the filename:
String checkedFileName = Paths.get(fileName).getFileName().toString();
Path file = SystemUtils.getJavaIoTmpDir().toPath().resolve(checkedFileName);
log.debug("delete file:{},exists:{}", file, Files.exists(file));
boolean removed = getSessionFileMetadatas().remove(new FileMetadata(fileName));
// try with full name as ui only know the file name
if (!removed) {
removed = getSessionFileMetadatas().remove(new FileMetadata(file.toString()));
}
if (removed) {
try {
Files.deleteIfExists(file);
return Boolean.TRUE;
} catch (IOException e) {
log.error("Could not delete file {}: {}", file, e.getMessage(), e);
}
}
return Boolean.FALSE;
}
@Override
public Boolean clearUploadedFiles()
throws ArchivaRestServiceException {
List<FileMetadata> fileMetadatas = new ArrayList<>(getSessionFileMetadatas());
for (FileMetadata fileMetadata : fileMetadatas) {
deleteFile(Paths.get(fileMetadata.getServerFileName()).toString());
}
getSessionFileMetadatas().clear();
return Boolean.TRUE;
}
@Override
public List<FileMetadata> getSessionFileMetadatas()
throws ArchivaRestServiceException {
return getSessionFilesList();
}
private boolean hasValidChars(String checkString) {
if (checkString.contains(FS)) {
return false;
}
if (checkString.contains("../")) {
return false;
}
if (checkString.contains("/..")) {
return false;
}
return true;
}
private void checkParamChars(String param, String value) throws ArchivaRestServiceException {
if (!hasValidChars(value)) {
ArchivaRestServiceException e = new ArchivaRestServiceException("Bad characters in " + param, null);
e.setHttpErrorCode(422);
e.setErrorKey("fileupload.malformed.param");
e.setFieldName(param);
throw e;
}
}
@Override
public Boolean save(String repositoryId, String groupId, String artifactId, String version, String packaging,
boolean generatePom)
throws ArchivaRestServiceException {
repositoryId = StringUtils.trim(repositoryId);
groupId = StringUtils.trim(groupId);
artifactId = StringUtils.trim(artifactId);
version = StringUtils.trim(version);
packaging = StringUtils.trim(packaging);
checkParamChars("repositoryId", repositoryId);
checkParamChars("groupId", groupId);
checkParamChars("artifactId", artifactId);
checkParamChars("version", version);
checkParamChars("packaging", packaging);
List<FileMetadata> fileMetadatas = getSessionFilesList();
if (fileMetadatas == null || fileMetadatas.isEmpty()) {
return Boolean.FALSE;
}
try {
ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository(repositoryId);
if (managedRepository == null) {
// TODO i18n ?
throw new ArchivaRestServiceException("Cannot find managed repository with id " + repositoryId,
Response.Status.BAD_REQUEST.getStatusCode(), null);
}
if (VersionUtil.isSnapshot(version) && !managedRepository.isSnapshots()) {
// TODO i18n ?
throw new ArchivaRestServiceException(
"Managed repository with id " + repositoryId + " do not accept snapshots",
Response.Status.BAD_REQUEST.getStatusCode(), null);
}
} catch (RepositoryAdminException e) {
throw new ArchivaRestServiceException(e.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
}
// get from the session file with groupId/artifactId
Iterable<FileMetadata> filesToAdd = Iterables.filter(fileMetadatas, new Predicate<FileMetadata>() {
public boolean apply(FileMetadata fileMetadata) {
return fileMetadata != null && !fileMetadata.isPomFile();
}
});
Iterator<FileMetadata> iterator = filesToAdd.iterator();
boolean pomGenerated = false;
while (iterator.hasNext()) {
FileMetadata fileMetadata = iterator.next();
log.debug("fileToAdd: {}", fileMetadata);
saveFile(repositoryId, fileMetadata, generatePom && !pomGenerated, groupId, artifactId, version,
packaging);
pomGenerated = true;
deleteFile(fileMetadata.getServerFileName());
}
filesToAdd = Iterables.filter(fileMetadatas, new Predicate<FileMetadata>() {
@Override
public boolean apply(FileMetadata fileMetadata) {
return fileMetadata != null && fileMetadata.isPomFile();
}
});
iterator = filesToAdd.iterator();
while (iterator.hasNext()) {
FileMetadata fileMetadata = iterator.next();
log.debug("fileToAdd: {}", fileMetadata);
savePomFile(repositoryId, fileMetadata, groupId, artifactId, version, packaging);
deleteFile(fileMetadata.getServerFileName());
}
return Boolean.TRUE;
}
protected void savePomFile(String repositoryId, FileMetadata fileMetadata, String groupId, String artifactId,
String version, String packaging)
throws ArchivaRestServiceException {
log.debug("Saving POM");
try {
boolean fixChecksums =
!(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
org.apache.archiva.repository.ManagedRepository repoConfig = repositoryRegistry.getManagedRepository(repositoryId);
ArtifactReference artifactReference = createArtifactRef(fileMetadata, groupId, artifactId, version);
artifactReference.setType(packaging);
StorageAsset pomPath = artifactUtil.getArtifactAsset(repoConfig, artifactReference);
StorageAsset targetPath = pomPath.getParent();
String pomFilename = pomPath.getName();
if (StringUtils.isNotEmpty(fileMetadata.getClassifier())) {
pomFilename = StringUtils.remove(pomFilename, "-" + fileMetadata.getClassifier());
}
pomFilename = FilenameUtils.removeExtension(pomFilename) + ".pom";
copyFile(Paths.get(fileMetadata.getServerFileName()), targetPath, pomFilename, fixChecksums);
triggerAuditEvent(repoConfig.getId(), targetPath.resolve(pomFilename).toString(), AuditEvent.UPLOAD_FILE);
queueRepositoryTask(repoConfig.getId(), targetPath.resolve(pomFilename));
log.debug("Finished Saving POM");
} catch (IOException ie) {
log.error("IOException for POM {}", ie.getMessage());
throw new ArchivaRestServiceException("Error encountered while uploading pom file: " + ie.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
} catch (RepositoryException rep) {
log.error("RepositoryException for POM {}", rep.getMessage());
throw new ArchivaRestServiceException("Repository exception: " + rep.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep);
} catch (RepositoryAdminException e) {
log.error("RepositoryAdminException for POM {}", e.getMessage());
throw new ArchivaRestServiceException("RepositoryAdmin exception: " + e.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
}
}
protected void saveFile(String repositoryId, FileMetadata fileMetadata, boolean generatePom, String groupId,
String artifactId, String version, String packaging)
throws ArchivaRestServiceException {
log.debug("Saving file");
try {
org.apache.archiva.repository.ManagedRepository repoConfig = repositoryRegistry.getManagedRepository(repositoryId);
ArtifactReference artifactReference = createArtifactRef(fileMetadata, groupId, artifactId, version);
artifactReference.setType(
StringUtils.isEmpty(fileMetadata.getPackaging()) ? packaging : fileMetadata.getPackaging());
StorageAsset artifactPath = artifactUtil.getArtifactAsset(repoConfig, artifactReference);
StorageAsset targetPath = artifactPath.getParent();
log.debug("artifactPath: {} found targetPath: {}", artifactPath, targetPath);
Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
int newBuildNumber = -1;
String timestamp = null;
StorageAsset versionMetadataFile = targetPath.resolve(MetadataTools.MAVEN_METADATA);
ArchivaRepositoryMetadata versionMetadata = getMetadata(versionMetadataFile);
if (VersionUtil.isSnapshot(version)) {
TimeZone timezone = TimeZone.getTimeZone("UTC");
DateFormat fmt = new SimpleDateFormat("yyyyMMdd.HHmmss");
fmt.setTimeZone(timezone);
timestamp = fmt.format(lastUpdatedTimestamp);
if (versionMetadata.getSnapshotVersion() != null) {
newBuildNumber = versionMetadata.getSnapshotVersion().getBuildNumber() + 1;
} else {
newBuildNumber = 1;
}
}
if (!targetPath.exists()) {
targetPath.create();
}
String filename = artifactPath.getName().toString();
if (VersionUtil.isSnapshot(version)) {
filename = filename.replaceAll(VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber);
}
// We always fix checksums for newly uploaded files, even if the content consumer is active.
boolean fixChecksums = true;
// !(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
try {
StorageAsset targetFile = targetPath.resolve(filename);
if (targetFile.exists() && !VersionUtil.isSnapshot(version) && repoConfig.blocksRedeployments()) {
throw new ArchivaRestServiceException(
"Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
Response.Status.BAD_REQUEST.getStatusCode(), null);
} else {
copyFile(Paths.get(fileMetadata.getServerFileName()), targetPath, filename, fixChecksums);
triggerAuditEvent(repoConfig.getId(), artifactPath.toString(), AuditEvent.UPLOAD_FILE);
queueRepositoryTask(repoConfig.getId(), targetFile);
}
} catch (IOException ie) {
log.error("IOException copying file: {}", ie.getMessage(), ie);
throw new ArchivaRestServiceException(
"Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
}
if (generatePom) {
String pomFilename = filename;
if (StringUtils.isNotEmpty(fileMetadata.getClassifier())) {
pomFilename = StringUtils.remove(pomFilename, "-" + fileMetadata.getClassifier());
}
pomFilename = FilenameUtils.removeExtension(pomFilename) + ".pom";
try {
StorageAsset generatedPomFile =
createPom(targetPath, pomFilename, fileMetadata, groupId, artifactId, version, packaging);
triggerAuditEvent(repoConfig.getId(), targetPath.resolve(pomFilename).toString(), AuditEvent.UPLOAD_FILE);
if (fixChecksums) {
fixChecksums(generatedPomFile);
}
queueRepositoryTask(repoConfig.getId(), generatedPomFile);
} catch (IOException ie) {
throw new ArchivaRestServiceException(
"Error encountered while writing pom file: " + ie.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie);
}
}
// explicitly update only if metadata-updater consumer is not enabled!
if (!archivaAdministration.getKnownContentConsumers().contains("metadata-updater")) {
updateProjectMetadata(targetPath, lastUpdatedTimestamp, timestamp, newBuildNumber,
fixChecksums, fileMetadata, groupId, artifactId, version, packaging);
if (VersionUtil.isSnapshot(version)) {
updateVersionMetadata(versionMetadata, versionMetadataFile, lastUpdatedTimestamp, timestamp,
newBuildNumber, fixChecksums, fileMetadata, groupId, artifactId, version,
packaging);
}
}
} catch (RepositoryNotFoundException re) {
log.error("RepositoryNotFoundException during save {}", re.getMessage());
re.printStackTrace();
throw new ArchivaRestServiceException("Target repository cannot be found: " + re.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), re);
} catch (RepositoryException rep) {
log.error("RepositoryException during save {}", rep.getMessage());
throw new ArchivaRestServiceException("Repository exception: " + rep.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep);
} catch (RepositoryAdminException e) {
log.error("RepositoryAdminException during save {}", e.getMessage());
throw new ArchivaRestServiceException("RepositoryAdmin exception: " + e.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
} catch (IOException e) {
log.error("IOException during save {}", e.getMessage());
throw new ArchivaRestServiceException("Repository exception " + e.getMessage(),
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
}
}
private ArtifactReference createArtifactRef(FileMetadata fileMetadata, String groupId, String artifactId, String version) {
ArtifactReference artifactReference = new ArtifactReference();
artifactReference.setArtifactId(artifactId);
artifactReference.setGroupId(groupId);
artifactReference.setVersion(version);
artifactReference.setClassifier(fileMetadata.getClassifier());
return artifactReference;
}
private ArchivaRepositoryMetadata getMetadata(StorageAsset metadataFile)
throws RepositoryMetadataException {
ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
if (metadataFile.exists()) {
try {
metadata = MavenMetadataReader.read(metadataFile);
} catch (XMLException | IOException e) {
throw new RepositoryMetadataException(e.getMessage(), e);
}
}
return metadata;
}
private StorageAsset createPom(StorageAsset targetPath, String filename, FileMetadata fileMetadata, String groupId,
String artifactId, String version, String packaging)
throws IOException {
Model projectModel = new Model();
projectModel.setModelVersion("4.0.0");
projectModel.setGroupId(groupId);
projectModel.setArtifactId(artifactId);
projectModel.setVersion(version);
projectModel.setPackaging(packaging);
StorageAsset pomFile = targetPath.resolve(filename);
MavenXpp3Writer writer = new MavenXpp3Writer();
try (Writer w = new OutputStreamWriter(pomFile.getWriteStream(true))) {
writer.write(w, projectModel);
}
return pomFile;
}
private void fixChecksums(StorageAsset file) {
ChecksummedFile checksum = new ChecksummedFile(file.getFilePath());
checksum.fixChecksums(algorithms);
}
private void queueRepositoryTask(String repositoryId, StorageAsset localFile) {
RepositoryTask task = new RepositoryTask();
task.setRepositoryId(repositoryId);
task.setResourceFile(localFile);
task.setUpdateRelatedArtifacts(true);
task.setScanAll(false);
try {
scheduler.queueTask(task);
} catch (TaskQueueException e) {
log.error("Unable to queue repository task to execute consumers on resource file ['{}"
+ "'].", localFile.getName());
}
}
private void copyFile(Path sourceFile, StorageAsset targetPath, String targetFilename, boolean fixChecksums)
throws IOException {
targetPath.resolve(targetFilename).replaceDataFromFile(sourceFile);
if (fixChecksums) {
fixChecksums(targetPath.resolve(targetFilename));
}
}
/**
* Update artifact level metadata. If it does not exist, create the metadata and fix checksums if necessary.
*/
private void updateProjectMetadata(StorageAsset targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
boolean fixChecksums, FileMetadata fileMetadata, String groupId,
String artifactId, String version, String packaging)
throws RepositoryMetadataException {
List<String> availableVersions = new ArrayList<>();
String latestVersion = version;
StorageAsset projectDir = targetPath.getParent();
StorageAsset projectMetadataFile = projectDir.resolve(MetadataTools.MAVEN_METADATA);
ArchivaRepositoryMetadata projectMetadata = getMetadata(projectMetadataFile);
if (projectMetadataFile.exists()) {
availableVersions = projectMetadata.getAvailableVersions();
Collections.sort(availableVersions, VersionComparator.getInstance());
if (!availableVersions.contains(version)) {
availableVersions.add(version);
}
latestVersion = availableVersions.get(availableVersions.size() - 1);
} else {
availableVersions.add(version);
projectMetadata.setGroupId(groupId);
projectMetadata.setArtifactId(artifactId);
}
if (projectMetadata.getGroupId() == null) {
projectMetadata.setGroupId(groupId);
}
if (projectMetadata.getArtifactId() == null) {
projectMetadata.setArtifactId(artifactId);
}
projectMetadata.setLatestVersion(latestVersion);
projectMetadata.setLastUpdatedTimestamp(lastUpdatedTimestamp);
projectMetadata.setAvailableVersions(availableVersions);
if (!VersionUtil.isSnapshot(version)) {
projectMetadata.setReleasedVersion(latestVersion);
}
RepositoryMetadataWriter.write(projectMetadata, projectMetadataFile);
if (fixChecksums) {
fixChecksums(projectMetadataFile);
}
}
/**
* Update version level metadata for snapshot artifacts. If it does not exist, create the metadata and fix checksums
* if necessary.
*/
private void updateVersionMetadata(ArchivaRepositoryMetadata metadata, StorageAsset metadataFile,
Date lastUpdatedTimestamp, String timestamp, int buildNumber,
boolean fixChecksums, FileMetadata fileMetadata, String groupId,
String artifactId, String version, String packaging)
throws RepositoryMetadataException {
if (!metadataFile.exists()) {
metadata.setGroupId(groupId);
metadata.setArtifactId(artifactId);
metadata.setVersion(version);
}
if (metadata.getSnapshotVersion() == null) {
metadata.setSnapshotVersion(new SnapshotVersion());
}
metadata.getSnapshotVersion().setBuildNumber(buildNumber);
metadata.getSnapshotVersion().setTimestamp(timestamp);
metadata.setLastUpdatedTimestamp(lastUpdatedTimestamp);
RepositoryMetadataWriter.write(metadata, metadataFile);
if (fixChecksums) {
fixChecksums(metadataFile);
}
}
}