001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.util.repository; 020 021import java.io.File; 022import java.nio.file.Files; 023import java.nio.file.Path; 024import java.util.List; 025 026import org.eclipse.aether.RepositorySystemSession; 027import org.eclipse.aether.artifact.Artifact; 028import org.eclipse.aether.metadata.Metadata; 029import org.eclipse.aether.repository.LocalArtifactRegistration; 030import org.eclipse.aether.repository.LocalArtifactRequest; 031import org.eclipse.aether.repository.LocalArtifactResult; 032import org.eclipse.aether.repository.LocalMetadataRegistration; 033import org.eclipse.aether.repository.LocalMetadataRequest; 034import org.eclipse.aether.repository.LocalMetadataResult; 035import org.eclipse.aether.repository.LocalRepository; 036import org.eclipse.aether.repository.LocalRepositoryManager; 037import org.eclipse.aether.repository.RemoteRepository; 038import org.eclipse.aether.util.ConfigUtils; 039 040import static java.util.Objects.requireNonNull; 041import static java.util.stream.Collectors.toList; 042 043/** 044 * A local repository manager that chains multiple local repository managers: it directs all the write operations 045 * to chain head, while uses tail for {@link #find(RepositorySystemSession, LocalArtifactRequest)} and 046 * {@link #find(RepositorySystemSession, LocalMetadataRequest)} methods only. Hence, tail is used in resolving 047 * metadata and artifacts with or without (configurable) artifact availability tracking. 048 * <p> 049 * Implementation represents itself using the head local repository manager. 050 * 051 * @since 1.9.2 052 */ 053public final class ChainedLocalRepositoryManager implements LocalRepositoryManager { 054 public static final String IGNORE_TAIL_AVAILABILITY = "aether.chainedLocalRepository.ignoreTailAvailability"; 055 056 private static final boolean DEFAULT_IGNORE_TAIL_AVAILABILITY = true; 057 058 private final LocalRepositoryManager head; 059 060 private final List<LocalRepositoryManager> tail; 061 062 private final boolean ignoreTailAvailability; 063 064 public ChainedLocalRepositoryManager( 065 LocalRepositoryManager head, List<LocalRepositoryManager> tail, boolean ignoreTailAvailability) { 066 this.head = requireNonNull(head, "head cannot be null"); 067 this.tail = requireNonNull(tail, "tail cannot be null"); 068 this.ignoreTailAvailability = ignoreTailAvailability; 069 } 070 071 public ChainedLocalRepositoryManager( 072 LocalRepositoryManager head, List<LocalRepositoryManager> tail, RepositorySystemSession session) { 073 this.head = requireNonNull(head, "head cannot be null"); 074 this.tail = requireNonNull(tail, "tail cannot be null"); 075 this.ignoreTailAvailability = 076 ConfigUtils.getBoolean(session, DEFAULT_IGNORE_TAIL_AVAILABILITY, IGNORE_TAIL_AVAILABILITY); 077 } 078 079 @Override 080 public LocalRepository getRepository() { 081 return head.getRepository(); 082 } 083 084 @Override 085 public String getPathForLocalArtifact(Artifact artifact) { 086 return head.getPathForLocalArtifact(artifact); 087 } 088 089 @Override 090 public String getPathForRemoteArtifact(Artifact artifact, RemoteRepository repository, String context) { 091 return head.getPathForRemoteArtifact(artifact, repository, context); 092 } 093 094 @Override 095 public String getPathForLocalMetadata(Metadata metadata) { 096 return head.getPathForLocalMetadata(metadata); 097 } 098 099 @Override 100 public String getPathForRemoteMetadata(Metadata metadata, RemoteRepository repository, String context) { 101 return head.getPathForRemoteMetadata(metadata, repository, context); 102 } 103 104 @Override 105 public LocalArtifactResult find(RepositorySystemSession session, LocalArtifactRequest request) { 106 LocalArtifactResult result = head.find(session, request); 107 if (result.isAvailable()) { 108 return result; 109 } 110 111 for (LocalRepositoryManager lrm : tail) { 112 result = lrm.find(session, request); 113 if (result.getFile() != null) { 114 if (ignoreTailAvailability) { 115 result.setAvailable(true); 116 return result; 117 } else if (result.isAvailable()) { 118 return result; 119 } 120 } 121 } 122 return new LocalArtifactResult(request); 123 } 124 125 @Override 126 public void add(RepositorySystemSession session, LocalArtifactRegistration request) { 127 String artifactPath; 128 if (request.getRepository() != null) { 129 artifactPath = getPathForRemoteArtifact(request.getArtifact(), request.getRepository(), "check"); 130 } else { 131 artifactPath = getPathForLocalArtifact(request.getArtifact()); 132 } 133 134 Path file = new File(head.getRepository().getBasedir(), artifactPath).toPath(); 135 if (Files.isRegularFile(file)) { 136 head.add(session, request); 137 } 138 } 139 140 @Override 141 public LocalMetadataResult find(RepositorySystemSession session, LocalMetadataRequest request) { 142 LocalMetadataResult result = head.find(session, request); 143 if (result.getFile() != null) { 144 return result; 145 } 146 147 for (LocalRepositoryManager lrm : tail) { 148 result = lrm.find(session, request); 149 if (result.getFile() != null) { 150 return result; 151 } 152 } 153 return new LocalMetadataResult(request); 154 } 155 156 @Override 157 public void add(RepositorySystemSession session, LocalMetadataRegistration request) { 158 String metadataPath; 159 if (request.getRepository() != null) { 160 metadataPath = getPathForRemoteMetadata(request.getMetadata(), request.getRepository(), "check"); 161 } else { 162 metadataPath = getPathForLocalMetadata(request.getMetadata()); 163 } 164 165 Path file = new File(head.getRepository().getBasedir(), metadataPath).toPath(); 166 if (Files.isRegularFile(file)) { 167 head.add(session, request); 168 } 169 } 170 171 @Override 172 public String toString() { 173 return head.getRepository().toString() 174 + tail.stream().map(LocalRepositoryManager::getRepository).collect(toList()); 175 } 176}