123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921 |
- package org.apache.archiva.metadata.repository.storage.maven2;
-
- /*
- * 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 org.apache.archiva.checksum.ChecksumAlgorithm;
- import org.apache.archiva.checksum.ChecksummedFile;
- import org.apache.archiva.common.Try;
- import org.apache.archiva.common.utils.VersionUtil;
- import org.apache.archiva.filter.Filter;
- import org.apache.archiva.maven2.metadata.MavenMetadataReader;
- import org.apache.archiva.metadata.model.ArtifactMetadata;
- import org.apache.archiva.metadata.model.ProjectMetadata;
- import org.apache.archiva.metadata.model.ProjectVersionMetadata;
- import org.apache.archiva.metadata.model.facets.RepositoryProblemFacet;
- import org.apache.archiva.metadata.repository.storage.*;
- import org.apache.archiva.model.ArchivaRepositoryMetadata;
- import org.apache.archiva.model.ArtifactReference;
- import org.apache.archiva.model.SnapshotVersion;
- import org.apache.archiva.policies.ProxyDownloadException;
- import org.apache.archiva.proxy.ProxyRegistry;
- import org.apache.archiva.proxy.maven.WagonFactory;
- import org.apache.archiva.proxy.model.NetworkProxy;
- import org.apache.archiva.proxy.model.ProxyConnector;
- import org.apache.archiva.proxy.model.RepositoryProxyHandler;
- import org.apache.archiva.repository.*;
- import org.apache.archiva.repository.content.PathParser;
- import org.apache.archiva.repository.maven2.MavenSystemManager;
- import org.apache.archiva.repository.storage.StorageAsset;
- import org.apache.archiva.xml.XMLException;
- import org.apache.commons.lang.ArrayUtils;
- import org.apache.commons.lang.StringUtils;
- import org.apache.maven.model.*;
- import org.apache.maven.model.building.*;
- import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
- import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.context.ApplicationContext;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.PostConstruct;
- import javax.inject.Inject;
- import javax.inject.Named;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.Reader;
- import java.nio.channels.Channels;
- import java.nio.charset.Charset;
- import java.nio.file.NoSuchFileException;
- import java.util.*;
- import java.util.function.Predicate;
- import java.util.stream.Collectors;
-
- // import java.io.FileNotFoundException;
-
- /**
- * <p>
- * Maven 2 repository format storage implementation. This class currently takes parameters to indicate the repository to
- * deal with rather than being instantiated per-repository.
- * FIXME: instantiate one per repository and allocate permanently from a factory (which can be obtained within the session).
- * </p>
- * <p>
- * The session is passed in as an argument to obtain any necessary resources, rather than the class being instantiated
- * within the session in the context of a single managed repository's resolution needs.
- * </p>
- */
- @Service("repositoryStorage#maven2")
- public class Maven2RepositoryStorage
- implements RepositoryStorage {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Maven2RepositoryStorage.class);
-
- private ModelBuilder builder;
-
- @Inject
- RepositoryRegistry repositoryRegistry;
-
- @Inject
- @Named("repositoryPathTranslator#maven2")
- private RepositoryPathTranslator pathTranslator;
-
- @Inject
- private WagonFactory wagonFactory;
-
- @Inject
- private ApplicationContext applicationContext;
-
- @Inject
- @Named("pathParser#default")
- private PathParser pathParser;
-
- @Inject
- private ProxyRegistry proxyRegistry;
-
- @Inject
- private MavenSystemManager mavenSystemManager;
-
- private static final String METADATA_FILENAME_START = "maven-metadata";
-
- private static final String METADATA_FILENAME = METADATA_FILENAME_START + ".xml";
-
- // This array must be lexically sorted
- private static final String[] IGNORED_FILES = {METADATA_FILENAME, "resolver-status.properties"};
-
- private static final MavenXpp3Reader MAVEN_XPP_3_READER = new MavenXpp3Reader();
-
-
- @PostConstruct
- public void initialize() {
- builder = new DefaultModelBuilderFactory().newInstance();
-
- }
-
- @Override
- public ProjectMetadata readProjectMetadata(String repoId, String namespace, String projectId) {
- // TODO: could natively implement the "shared model" concept from the browse action to avoid needing it there?
- return null;
- }
-
- @Override
- public ProjectVersionMetadata readProjectVersionMetadata(ReadMetadataRequest readMetadataRequest)
- throws RepositoryStorageMetadataNotFoundException, RepositoryStorageMetadataInvalidException,
- RepositoryStorageRuntimeException {
-
- ManagedRepository managedRepository = repositoryRegistry.getManagedRepository(readMetadataRequest.getRepositoryId());
- boolean isReleases = managedRepository.getActiveReleaseSchemes().contains(ReleaseScheme.RELEASE);
- boolean isSnapshots = managedRepository.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT);
- String artifactVersion = readMetadataRequest.getProjectVersion();
- // olamy: in case of browsing via the ui we can mix repos (parent of a SNAPSHOT can come from release repo)
- if (!readMetadataRequest.isBrowsingRequest()) {
- if (VersionUtil.isSnapshot(artifactVersion)) {
- // skygo trying to improve speed by honoring managed configuration MRM-1658
- if (isReleases && !isSnapshots) {
- throw new RepositoryStorageRuntimeException("lookforsnaponreleaseonly",
- "managed repo is configured for release only");
- }
- } else {
- if (!isReleases && isSnapshots) {
- throw new RepositoryStorageRuntimeException("lookforsreleaseonsneponly",
- "managed repo is configured for snapshot only");
- }
- }
- }
- StorageAsset basedir = managedRepository.getAsset("");
- if (VersionUtil.isSnapshot(artifactVersion)) {
- StorageAsset metadataFile = pathTranslator.toFile(basedir, readMetadataRequest.getNamespace(),
- readMetadataRequest.getProjectId(), artifactVersion,
- METADATA_FILENAME);
- try {
- ArchivaRepositoryMetadata metadata = MavenMetadataReader.read(metadataFile);
-
- // re-adjust to timestamp if present, otherwise retain the original -SNAPSHOT filename
- SnapshotVersion snapshotVersion = metadata.getSnapshotVersion();
- if (snapshotVersion != null) {
- artifactVersion =
- artifactVersion.substring(0, artifactVersion.length() - 8); // remove SNAPSHOT from end
- artifactVersion =
- artifactVersion + snapshotVersion.getTimestamp() + "-" + snapshotVersion.getBuildNumber();
- }
- } catch (XMLException | IOException e) {
- // unable to parse metadata - LOGGER it, and continue with the version as the original SNAPSHOT version
- LOGGER.warn("Invalid metadata: {} - {}", metadataFile, e.getMessage());
- }
- }
-
- // TODO: won't work well with some other layouts, might need to convert artifact parts to ID by path translator
- String id = readMetadataRequest.getProjectId() + "-" + artifactVersion + ".pom";
- StorageAsset file =
- pathTranslator.toFile(basedir, readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
- readMetadataRequest.getProjectVersion(), id);
-
- if (!file.exists()) {
- // metadata could not be resolved
- throw new RepositoryStorageMetadataNotFoundException(
- "The artifact's POM file '" + file.getPath() + "' was missing");
- }
-
- // TODO: this is a workaround until we can properly resolve using proxies as well - this doesn't cache
- // anything locally!
- List<RemoteRepository> remoteRepositories = new ArrayList<>();
- Map<String, NetworkProxy> networkProxies = new HashMap<>();
-
- Map<String, List<ProxyConnector>> proxyConnectorsMap = proxyRegistry.getProxyConnectorAsMap();
- List<ProxyConnector> proxyConnectors = proxyConnectorsMap.get(readMetadataRequest.getRepositoryId());
- if (proxyConnectors != null) {
- for (ProxyConnector proxyConnector : proxyConnectors) {
- RemoteRepository remoteRepoConfig =
- repositoryRegistry.getRemoteRepository(proxyConnector.getTargetRepository().getId());
-
- if (remoteRepoConfig != null) {
- remoteRepositories.add(remoteRepoConfig);
-
- NetworkProxy networkProxyConfig =
- proxyRegistry.getNetworkProxy(proxyConnector.getProxyId());
-
- if (networkProxyConfig != null) {
- // key/value: remote repo ID/proxy info
- networkProxies.put(proxyConnector.getTargetRepository().getId(), networkProxyConfig);
- }
- }
- }
- }
-
- // That's a browsing request so we can a mix of SNAPSHOT and release artifacts (especially with snapshots which
- // can have released parent pom
- if (readMetadataRequest.isBrowsingRequest()) {
- remoteRepositories.addAll(repositoryRegistry.getRemoteRepositories());
- }
-
- ModelBuildingRequest req =
- new DefaultModelBuildingRequest().setProcessPlugins(false).setPomFile(file.getFilePath().toFile()).setTwoPhaseBuilding(
- false).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
-
- //MRM-1607. olamy this will resolve jdk profiles on the current running archiva jvm
- req.setSystemProperties(System.getProperties());
-
- // MRM-1411
- req.setModelResolver(
- new RepositoryModelResolver(managedRepository, pathTranslator, wagonFactory, remoteRepositories,
- networkProxies, managedRepository, mavenSystemManager));
-
- Model model;
- try {
- model = builder.build(req).getEffectiveModel();
- } catch (ModelBuildingException e) {
- String msg = "The artifact's POM file '" + file + "' was invalid: " + e.getMessage();
-
- List<ModelProblem> modelProblems = e.getProblems();
- for (ModelProblem problem : modelProblems) {
- // MRM-1411, related to MRM-1335
- // this means that the problem was that the parent wasn't resolved!
- // olamy really hackhish but fail with java profile so use error message
- // || ( StringUtils.startsWith( problem.getMessage(), "Failed to determine Java version for profile" ) )
- // but setTwoPhaseBuilding(true) fix that
- if (((problem.getException() instanceof FileNotFoundException
- || problem.getException() instanceof NoSuchFileException
- ) && e.getModelId() != null &&
- !e.getModelId().equals(problem.getModelId()))) {
- LOGGER.warn("The artifact's parent POM file '{}' cannot be resolved. "
- + "Using defaults for project version metadata..", file);
-
- ProjectVersionMetadata metadata = new ProjectVersionMetadata();
- metadata.setId(readMetadataRequest.getProjectVersion());
-
- MavenProjectFacet facet = new MavenProjectFacet();
- facet.setGroupId(readMetadataRequest.getNamespace());
- facet.setArtifactId(readMetadataRequest.getProjectId());
- facet.setPackaging("jar");
- metadata.addFacet(facet);
-
- String errMsg =
- "Error in resolving artifact's parent POM file. " + (problem.getException() == null
- ? problem.getMessage()
- : problem.getException().getMessage());
- RepositoryProblemFacet repoProblemFacet = new RepositoryProblemFacet();
- repoProblemFacet.setRepositoryId(readMetadataRequest.getRepositoryId());
- repoProblemFacet.setId(readMetadataRequest.getRepositoryId());
- repoProblemFacet.setMessage(errMsg);
- repoProblemFacet.setProblem(errMsg);
- repoProblemFacet.setProject(readMetadataRequest.getProjectId());
- repoProblemFacet.setVersion(readMetadataRequest.getProjectVersion());
- repoProblemFacet.setNamespace(readMetadataRequest.getNamespace());
-
- metadata.addFacet(repoProblemFacet);
-
- return metadata;
- }
- }
-
- throw new RepositoryStorageMetadataInvalidException("invalid-pom", msg, e);
- }
-
- // Check if the POM is in the correct location
- boolean correctGroupId = readMetadataRequest.getNamespace().equals(model.getGroupId());
- boolean correctArtifactId = readMetadataRequest.getProjectId().equals(model.getArtifactId());
- boolean correctVersion = readMetadataRequest.getProjectVersion().equals(model.getVersion());
- if (!correctGroupId || !correctArtifactId || !correctVersion) {
- StringBuilder message = new StringBuilder("Incorrect POM coordinates in '" + file + "':");
- if (!correctGroupId) {
- message.append("\nIncorrect group ID: ").append(model.getGroupId());
- }
- if (!correctArtifactId) {
- message.append("\nIncorrect artifact ID: ").append(model.getArtifactId());
- }
- if (!correctVersion) {
- message.append("\nIncorrect version: ").append(model.getVersion());
- }
-
- throw new RepositoryStorageMetadataInvalidException("mislocated-pom", message.toString());
- }
-
- ProjectVersionMetadata metadata = new ProjectVersionMetadata();
- metadata.setCiManagement(convertCiManagement(model.getCiManagement()));
- metadata.setDescription(model.getDescription());
- metadata.setId(readMetadataRequest.getProjectVersion());
- metadata.setIssueManagement(convertIssueManagement(model.getIssueManagement()));
- metadata.setLicenses(convertLicenses(model.getLicenses()));
- metadata.setMailingLists(convertMailingLists(model.getMailingLists()));
- metadata.setDependencies(convertDependencies(model.getDependencies()));
- metadata.setName(model.getName());
- metadata.setOrganization(convertOrganization(model.getOrganization()));
- metadata.setScm(convertScm(model.getScm()));
- metadata.setUrl(model.getUrl());
- metadata.setProperties(model.getProperties());
-
- MavenProjectFacet facet = new MavenProjectFacet();
- facet.setGroupId(model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId());
- facet.setArtifactId(model.getArtifactId());
- facet.setPackaging(model.getPackaging());
- if (model.getParent() != null) {
- MavenProjectParent parent = new MavenProjectParent();
- parent.setGroupId(model.getParent().getGroupId());
- parent.setArtifactId(model.getParent().getArtifactId());
- parent.setVersion(model.getParent().getVersion());
- facet.setParent(parent);
- }
- metadata.addFacet(facet);
-
- return metadata;
-
-
- }
-
- public void setWagonFactory(WagonFactory wagonFactory) {
- this.wagonFactory = wagonFactory;
- }
-
- private List<org.apache.archiva.metadata.model.Dependency> convertDependencies(List<Dependency> dependencies) {
- List<org.apache.archiva.metadata.model.Dependency> l = new ArrayList<>();
- for (Dependency dependency : dependencies) {
- org.apache.archiva.metadata.model.Dependency newDependency =
- new org.apache.archiva.metadata.model.Dependency();
- newDependency.setArtifactId(dependency.getArtifactId());
- newDependency.setClassifier(dependency.getClassifier());
- newDependency.setGroupId(dependency.getGroupId());
- newDependency.setOptional(dependency.isOptional());
- newDependency.setScope(dependency.getScope());
- newDependency.setSystemPath(dependency.getSystemPath());
- newDependency.setType(dependency.getType());
- newDependency.setVersion(dependency.getVersion());
- l.add(newDependency);
- }
- return l;
- }
-
- private org.apache.archiva.metadata.model.Scm convertScm(Scm scm) {
- org.apache.archiva.metadata.model.Scm newScm = null;
- if (scm != null) {
- newScm = new org.apache.archiva.metadata.model.Scm();
- newScm.setConnection(scm.getConnection());
- newScm.setDeveloperConnection(scm.getDeveloperConnection());
- newScm.setUrl(scm.getUrl());
- }
- return newScm;
- }
-
- private org.apache.archiva.metadata.model.Organization convertOrganization(Organization organization) {
- org.apache.archiva.metadata.model.Organization org = null;
- if (organization != null) {
- org = new org.apache.archiva.metadata.model.Organization();
- org.setName(organization.getName());
- org.setUrl(organization.getUrl());
- }
- return org;
- }
-
- private List<org.apache.archiva.metadata.model.License> convertLicenses(List<License> licenses) {
- List<org.apache.archiva.metadata.model.License> l = new ArrayList<>();
- for (License license : licenses) {
- org.apache.archiva.metadata.model.License newLicense = new org.apache.archiva.metadata.model.License();
- newLicense.setName(license.getName());
- newLicense.setUrl(license.getUrl());
- l.add(newLicense);
- }
- return l;
- }
-
- private List<org.apache.archiva.metadata.model.MailingList> convertMailingLists(List<MailingList> mailingLists) {
- List<org.apache.archiva.metadata.model.MailingList> l = new ArrayList<>();
- for (MailingList mailingList : mailingLists) {
- org.apache.archiva.metadata.model.MailingList newMailingList =
- new org.apache.archiva.metadata.model.MailingList();
- newMailingList.setName(mailingList.getName());
- newMailingList.setMainArchiveUrl(mailingList.getArchive());
- newMailingList.setPostAddress(mailingList.getPost());
- newMailingList.setSubscribeAddress(mailingList.getSubscribe());
- newMailingList.setUnsubscribeAddress(mailingList.getUnsubscribe());
- newMailingList.setOtherArchives(mailingList.getOtherArchives());
- l.add(newMailingList);
- }
- return l;
- }
-
- private org.apache.archiva.metadata.model.IssueManagement convertIssueManagement(IssueManagement issueManagement) {
- org.apache.archiva.metadata.model.IssueManagement im = null;
- if (issueManagement != null) {
- im = new org.apache.archiva.metadata.model.IssueManagement();
- im.setSystem(issueManagement.getSystem());
- im.setUrl(issueManagement.getUrl());
- }
- return im;
- }
-
- private org.apache.archiva.metadata.model.CiManagement convertCiManagement(CiManagement ciManagement) {
- org.apache.archiva.metadata.model.CiManagement ci = null;
- if (ciManagement != null) {
- ci = new org.apache.archiva.metadata.model.CiManagement();
- ci.setSystem(ciManagement.getSystem());
- ci.setUrl(ciManagement.getUrl());
- }
- return ci;
- }
-
- @Override
- public Collection<String> listRootNamespaces(String repoId, Filter<String> filter)
- throws RepositoryStorageRuntimeException {
- StorageAsset dir = getRepositoryBasedir(repoId);
-
- return getSortedFiles(dir, filter);
- }
-
- private static Collection<String> getSortedFiles(StorageAsset dir, Filter<String> filter) {
-
- final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
- return dir.list().stream().filter(f -> f.isContainer())
- .filter(dFilter)
- .map(path -> path.getName().toString())
- .sorted().collect(Collectors.toList());
-
- }
-
- private StorageAsset getRepositoryBasedir(String repoId)
- throws RepositoryStorageRuntimeException {
- ManagedRepository repositoryConfiguration = repositoryRegistry.getManagedRepository(repoId);
-
- return repositoryConfiguration.getAsset("");
- }
-
- @Override
- public Collection<String> listNamespaces(String repoId, String namespace, Filter<String> filter)
- throws RepositoryStorageRuntimeException {
- StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace);
- if (!(dir.exists()) && !dir.isContainer()) {
- return Collections.emptyList();
- }
- // scan all the directories which are potential namespaces. Any directories known to be projects are excluded
- Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
- return dir.list().stream().filter(dFilter).filter(path -> !isProject(path, filter)).map(path -> path.getName().toString())
- .sorted().collect(Collectors.toList());
- }
-
- @Override
- public Collection<String> listProjects(String repoId, String namespace, Filter<String> filter)
- throws RepositoryStorageRuntimeException {
- StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace);
- if (!(dir.exists() && dir.isContainer())) {
- return Collections.emptyList();
- }
- // scan all directories in the namespace, and only include those that are known to be projects
- final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
- return dir.list().stream().filter(dFilter).filter(path -> isProject(path, filter)).map(path -> path.getName().toString())
- .sorted().collect(Collectors.toList());
-
- }
-
- @Override
- public Collection<String> listProjectVersions(String repoId, String namespace, String projectId,
- Filter<String> filter)
- throws RepositoryStorageRuntimeException {
- StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace, projectId);
- if (!(dir.exists() && dir.isContainer())) {
- return Collections.emptyList();
- }
-
- // all directories in a project directory can be considered a version
- return getSortedFiles(dir, filter);
- }
-
- @Override
- public Collection<ArtifactMetadata> readArtifactsMetadata(ReadMetadataRequest readMetadataRequest)
- throws RepositoryStorageRuntimeException {
- StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(readMetadataRequest.getRepositoryId()),
- readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
- readMetadataRequest.getProjectVersion());
- if (!(dir.exists() && dir.isContainer())) {
- return Collections.emptyList();
- }
-
- // all files that are not metadata and not a checksum / signature are considered artifacts
- final Predicate<StorageAsset> dFilter = new ArtifactDirectoryFilter(readMetadataRequest.getFilter());
- // Returns a map TRUE -> (success values), FALSE -> (Exceptions)
- Map<Boolean, List<Try<ArtifactMetadata>>> result = dir.list().stream().filter(dFilter).map(path -> {
- try {
- return Try.success(getArtifactFromFile(readMetadataRequest.getRepositoryId(), readMetadataRequest.getNamespace(),
- readMetadataRequest.getProjectId(), readMetadataRequest.getProjectVersion(),
- path));
- } catch (Exception e) {
- LOGGER.debug("Could not create metadata for {}: {}", path, e.getMessage(), e);
- return Try.<ArtifactMetadata>failure(e);
- }
- }
- ).collect(Collectors.groupingBy(Try::isSuccess));
- if (result.containsKey(Boolean.FALSE) && result.get(Boolean.FALSE).size() > 0 && (!result.containsKey(Boolean.TRUE) || result.get(Boolean.TRUE).size() == 0)) {
- LOGGER.error("Could not get artifact metadata. Directory: {}. Number of errors {}.", dir, result.get(Boolean.FALSE).size());
- Try<ArtifactMetadata> failure = result.get(Boolean.FALSE).get(0);
- LOGGER.error("Sample exception {}", failure.getError().getMessage(), failure.getError());
- throw new RepositoryStorageRuntimeException(readMetadataRequest.getRepositoryId(), "Could not retrieve metadata of the files");
- } else {
- if (!result.containsKey(Boolean.TRUE) || result.get(Boolean.TRUE) == null) {
- return Collections.emptyList();
- }
- return result.get(Boolean.TRUE).stream().map(tr -> tr.get()).collect(Collectors.toList());
- }
-
- }
-
- @Override
- public ArtifactMetadata readArtifactMetadataFromPath(String repoId, String path)
- throws RepositoryStorageRuntimeException {
- ArtifactMetadata metadata = pathTranslator.getArtifactForPath(repoId, path);
-
- try {
- populateArtifactMetadataFromFile(metadata, getRepositoryBasedir(repoId).resolve(path));
- } catch (IOException e) {
- throw new RepositoryStorageRuntimeException(repoId, "Error during metadata retrieval of " + path + " :" + e.getMessage(), e);
- }
-
- return metadata;
- }
-
- private ArtifactMetadata getArtifactFromFile(String repoId, String namespace, String projectId,
- String projectVersion, StorageAsset file) throws IOException {
- ArtifactMetadata metadata =
- pathTranslator.getArtifactFromId(repoId, namespace, projectId, projectVersion, file.getName());
-
- populateArtifactMetadataFromFile(metadata, file);
-
- return metadata;
- }
-
- @Override
- public void applyServerSideRelocation(ManagedRepositoryContent managedRepository, ArtifactReference artifact)
- throws ProxyDownloadException {
- if ("pom".equals(artifact.getType())) {
- return;
- }
-
- // Build the artifact POM reference
- ArtifactReference pomReference = new ArtifactReference();
- pomReference.setGroupId(artifact.getGroupId());
- pomReference.setArtifactId(artifact.getArtifactId());
- pomReference.setVersion(artifact.getVersion());
- pomReference.setType("pom");
-
- RepositoryType repositoryType = managedRepository.getRepository().getType();
- if (!proxyRegistry.hasHandler(repositoryType)) {
- throw new ProxyDownloadException("No proxy handler found for repository type " + repositoryType, new HashMap<>());
- }
-
- RepositoryProxyHandler proxyHandler = proxyRegistry.getHandler(repositoryType).get(0);
-
- // Get the artifact POM from proxied repositories if needed
- proxyHandler.fetchFromProxies(managedRepository, pomReference);
-
- // Open and read the POM from the managed repo
- StorageAsset pom = managedRepository.toFile(pomReference);
-
- if (!pom.exists()) {
- return;
- }
-
- try {
- // MavenXpp3Reader leaves the file open, so we need to close it ourselves.
-
- Model model;
- try (Reader reader = Channels.newReader(pom.getReadChannel(), Charset.defaultCharset().name())) {
- model = MAVEN_XPP_3_READER.read(reader);
- }
-
- DistributionManagement dist = model.getDistributionManagement();
- if (dist != null) {
- Relocation relocation = dist.getRelocation();
- if (relocation != null) {
- // artifact is relocated : update the repositoryPath
- if (relocation.getGroupId() != null) {
- artifact.setGroupId(relocation.getGroupId());
- }
- if (relocation.getArtifactId() != null) {
- artifact.setArtifactId(relocation.getArtifactId());
- }
- if (relocation.getVersion() != null) {
- artifact.setVersion(relocation.getVersion());
- }
- }
- }
- } catch (IOException e) {
- // Unable to read POM : ignore.
- } catch (XmlPullParserException e) {
- // Invalid POM : ignore
- }
- }
-
-
- @Override
- public String getFilePath(String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository) {
- // managedRepository can be null
- // extract artifact reference from url
- // groupId:artifactId:version:packaging:classifier
- //org/apache/archiva/archiva-checksum/1.4-M4-SNAPSHOT/archiva-checksum-1.4-M4-SNAPSHOT.jar
- String logicalResource = null;
- String requestPathInfo = StringUtils.defaultString(requestPath);
-
- //remove prefix ie /repository/blah becomes /blah
- requestPathInfo = removePrefix(requestPathInfo);
-
- // Remove prefixing slash as the repository id doesn't contain it;
- if (requestPathInfo.startsWith("/")) {
- requestPathInfo = requestPathInfo.substring(1);
- }
-
- int slash = requestPathInfo.indexOf('/');
- if (slash > 0) {
- logicalResource = requestPathInfo.substring(slash);
-
- if (logicalResource.endsWith("/..")) {
- logicalResource += "/";
- }
-
- if (logicalResource != null && logicalResource.startsWith("//")) {
- logicalResource = logicalResource.substring(1);
- }
-
- if (logicalResource == null) {
- logicalResource = "/";
- }
- } else {
- logicalResource = "/";
- }
- return logicalResource;
-
- }
-
- @Override
- public String getFilePathWithVersion(final String requestPath, ManagedRepositoryContent managedRepositoryContent)
- throws RelocationException, XMLException, IOException {
-
- if (StringUtils.endsWith(requestPath, METADATA_FILENAME)) {
- return getFilePath(requestPath, managedRepositoryContent.getRepository());
- }
-
- String filePath = getFilePath(requestPath, managedRepositoryContent.getRepository());
-
- ArtifactReference artifactReference = null;
- try {
- artifactReference = pathParser.toArtifactReference(filePath);
- } catch (LayoutException e) {
- return filePath;
- }
-
- if (StringUtils.endsWith(artifactReference.getVersion(), VersionUtil.SNAPSHOT)) {
- // read maven metadata to get last timestamp
- StorageAsset metadataDir = managedRepositoryContent.getRepository().getAsset(filePath).getParent();
- if (!metadataDir.exists()) {
- return filePath;
- }
- StorageAsset metadataFile = metadataDir.resolve(METADATA_FILENAME);
- if (!metadataFile.exists()) {
- return filePath;
- }
- ArchivaRepositoryMetadata archivaRepositoryMetadata = MavenMetadataReader.read(metadataFile);
- int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
- String timestamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
-
- // MRM-1846
- if (buildNumber < 1 && timestamp == null) {
- return filePath;
- }
-
- // org/apache/archiva/archiva-checksum/1.4-M4-SNAPSHOT/archiva-checksum-1.4-M4-SNAPSHOT.jar
- // -> archiva-checksum-1.4-M4-20130425.081822-1.jar
-
- filePath = StringUtils.replace(filePath, //
- artifactReference.getArtifactId() //
- + "-" + artifactReference.getVersion(), //
- artifactReference.getArtifactId() //
- + "-" + StringUtils.remove(artifactReference.getVersion(),
- "-" + VersionUtil.SNAPSHOT) //
- + "-" + timestamp //
- + "-" + buildNumber);
-
- throw new RelocationException("/repository/" + managedRepositoryContent.getRepository().getId() +
- (StringUtils.startsWith(filePath, "/") ? "" : "/") + filePath,
- RelocationException.RelocationType.TEMPORARY);
-
- }
-
- return filePath;
- }
-
- //-----------------------------
- // internal
- //-----------------------------
-
- /**
- * FIXME remove
- *
- * @param href
- * @return
- */
- private static String removePrefix(final String href) {
- String[] parts = StringUtils.split(href, '/');
- parts = (String[]) ArrayUtils.subarray(parts, 1, parts.length);
- if (parts == null || parts.length == 0) {
- return "/";
- }
-
- String joinedString = StringUtils.join(parts, '/');
- if (href.endsWith("/")) {
- joinedString = joinedString + "/";
- }
-
- return joinedString;
- }
-
- private static void populateArtifactMetadataFromFile(ArtifactMetadata metadata, StorageAsset file) throws IOException {
- metadata.setWhenGathered(new Date());
- metadata.setFileLastModified(file.getModificationTime().toEpochMilli());
- ChecksummedFile checksummedFile = new ChecksummedFile(file.getFilePath());
- try {
- metadata.setMd5(checksummedFile.calculateChecksum(ChecksumAlgorithm.MD5));
- } catch (IOException e) {
- LOGGER.error("Unable to checksum file {}: {},MD5", file, e.getMessage());
- }
- try {
- metadata.setSha1(checksummedFile.calculateChecksum(ChecksumAlgorithm.SHA1));
- } catch (IOException e) {
- LOGGER.error("Unable to checksum file {}: {},SHA1", file, e.getMessage());
- }
- metadata.setSize(file.getSize());
- }
-
- private boolean isProject(StorageAsset dir, Filter<String> filter) {
- // scan directories for a valid project version subdirectory, meaning this must be a project directory
- final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
- boolean projFound = dir.list().stream().filter(dFilter)
- .anyMatch(path -> isProjectVersion(path));
- if (projFound) {
- return true;
- }
-
- // if a metadata file is present, check if this is the "artifactId" directory, marking it as a project
- ArchivaRepositoryMetadata metadata = readMetadata(dir);
- if (metadata != null && dir.getName().toString().equals(metadata.getArtifactId())) {
- return true;
- }
-
- return false;
- }
-
- private boolean isProjectVersion(StorageAsset dir) {
- final String artifactId = dir.getParent().getName();
- final String projectVersion = dir.getName();
-
- // check if there is a POM artifact file to ensure it is a version directory
-
- Predicate<StorageAsset> filter;
- if (VersionUtil.isSnapshot(projectVersion)) {
- filter = new PomFilenameFilter(artifactId, projectVersion);
- } else {
- final String pomFile = artifactId + "-" + projectVersion + ".pom";
- filter = new PomFileFilter(pomFile);
- }
- if (dir.list().stream().filter(f -> !f.isContainer()).anyMatch(filter)) {
- return true;
- }
- // if a metadata file is present, check if this is the "version" directory, marking it as a project version
- ArchivaRepositoryMetadata metadata = readMetadata(dir);
- if (metadata != null && projectVersion.equals(metadata.getVersion())) {
- return true;
- }
-
- return false;
- }
-
- private ArchivaRepositoryMetadata readMetadata(StorageAsset directory) {
- ArchivaRepositoryMetadata metadata = null;
- StorageAsset metadataFile = directory.resolve(METADATA_FILENAME);
- if (metadataFile.exists()) {
- try {
- metadata = MavenMetadataReader.read(metadataFile);
- } catch (XMLException | IOException e) {
- // ignore missing or invalid metadata
- }
- }
- return metadata;
- }
-
- private static class DirectoryFilter
- implements Predicate<StorageAsset> {
- private final Filter<String> filter;
-
- public DirectoryFilter(Filter<String> filter) {
- this.filter = filter;
- }
-
- @Override
- public boolean test(StorageAsset dir) {
- final String name = dir.getName();
- if (!filter.accept(name)) {
- return false;
- } else if (name.startsWith(".")) {
- return false;
- } else if (!dir.isContainer()) {
- return false;
- }
- return true;
- }
- }
-
- private static class ArtifactDirectoryFilter
- implements Predicate<StorageAsset> {
- private final Filter<String> filter;
-
- private ArtifactDirectoryFilter(Filter<String> filter) {
- this.filter = filter;
- }
-
- @Override
- public boolean test(StorageAsset file) {
- final Set<String> checksumExts = ChecksumAlgorithm.getAllExtensions();
- final String path = file.getPath();
- final String name = file.getName();
- final String extension = StringUtils.substringAfterLast(name, ".").toLowerCase();
- // TODO compare to logic in maven-repository-layer
- if (file.isContainer()) {
- return false;
- } else if (!filter.accept(name)) {
- return false;
- } else if (name.startsWith(".") || path.contains("/.") ) {
- return false;
- } else if (checksumExts.contains(extension)) {
- return false;
- } else if (Arrays.binarySearch(IGNORED_FILES, name) >= 0) {
- return false;
- }
- // some files from remote repositories can have name like maven-metadata-archiva-vm-all-public.xml
- else if (StringUtils.startsWith(name, METADATA_FILENAME_START) && StringUtils.endsWith(name, ".xml")) {
- return false;
- }
-
- return true;
-
- }
- }
-
-
- private static final class PomFilenameFilter
- implements Predicate<StorageAsset> {
-
- private final String artifactId, projectVersion;
-
- private PomFilenameFilter(String artifactId, String projectVersion) {
- this.artifactId = artifactId;
- this.projectVersion = projectVersion;
- }
-
- @Override
- public boolean test(StorageAsset dir) {
- final String name = dir.getName();
- if (name.startsWith(artifactId + "-") && name.endsWith(".pom")) {
- String v = name.substring(artifactId.length() + 1, name.length() - 4);
- v = VersionUtil.getBaseVersion(v);
- if (v.equals(projectVersion)) {
- return true;
- }
- }
- return false;
- }
-
- }
-
- private static class PomFileFilter
- implements Predicate<StorageAsset> {
- private final String pomFile;
-
- private PomFileFilter(String pomFile) {
- this.pomFile = pomFile;
- }
-
- @Override
- public boolean test(StorageAsset dir) {
- return pomFile.equals(dir.getName());
- }
- }
-
-
- public PathParser getPathParser() {
- return pathParser;
- }
-
- public void setPathParser(PathParser pathParser) {
- this.pathParser = pathParser;
- }
- }
|