001package org.eclipse.aether.util.repository;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.nio.file.Files;
024import java.nio.file.Path;
025import java.util.List;
026
027import org.eclipse.aether.RepositorySystemSession;
028import org.eclipse.aether.artifact.Artifact;
029import org.eclipse.aether.metadata.Metadata;
030import org.eclipse.aether.repository.LocalArtifactRegistration;
031import org.eclipse.aether.repository.LocalArtifactRequest;
032import org.eclipse.aether.repository.LocalArtifactResult;
033import org.eclipse.aether.repository.LocalMetadataRegistration;
034import org.eclipse.aether.repository.LocalMetadataRequest;
035import org.eclipse.aether.repository.LocalMetadataResult;
036import org.eclipse.aether.repository.LocalRepository;
037import org.eclipse.aether.repository.LocalRepositoryManager;
038import org.eclipse.aether.repository.RemoteRepository;
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
054        implements LocalRepositoryManager
055{
056    private final LocalRepositoryManager head;
057
058    private final List<LocalRepositoryManager> tail;
059
060    private final boolean ignoreTailAvailability;
061
062    public ChainedLocalRepositoryManager( LocalRepositoryManager head,
063                                          List<LocalRepositoryManager> tail,
064                                          boolean ignoreTailAvailability )
065    {
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    @Override
072    public LocalRepository getRepository()
073    {
074        return head.getRepository();
075    }
076
077    @Override
078    public String getPathForLocalArtifact( Artifact artifact )
079    {
080        return head.getPathForLocalArtifact( artifact );
081    }
082
083    @Override
084    public String getPathForRemoteArtifact( Artifact artifact, RemoteRepository repository, String context )
085    {
086        return head.getPathForRemoteArtifact( artifact, repository, context );
087    }
088
089    @Override
090    public String getPathForLocalMetadata( Metadata metadata )
091    {
092        return head.getPathForLocalMetadata( metadata );
093    }
094
095    @Override
096    public String getPathForRemoteMetadata( Metadata metadata, RemoteRepository repository, String context )
097    {
098        return head.getPathForRemoteMetadata( metadata, repository, context );
099    }
100
101    @Override
102    public LocalArtifactResult find( RepositorySystemSession session, LocalArtifactRequest request )
103    {
104        LocalArtifactResult result = head.find( session, request );
105        if ( result.isAvailable() )
106        {
107            return result;
108        }
109
110        for ( LocalRepositoryManager lrm : tail )
111        {
112            result = lrm.find( session, request );
113            if ( result.getFile() != null )
114            {
115                if ( ignoreTailAvailability )
116                {
117                    result.setAvailable( true );
118                    return result;
119                }
120                else if ( result.isAvailable() )
121                {
122                    return result;
123                }
124            }
125        }
126        return new LocalArtifactResult( request );
127    }
128
129    @Override
130    public void add( RepositorySystemSession session, LocalArtifactRegistration request )
131    {
132        String artifactPath;
133        if ( request.getRepository() != null )
134        {
135            artifactPath = getPathForRemoteArtifact( request.getArtifact(), request.getRepository(), "check" );
136        }
137        else
138        {
139            artifactPath = getPathForLocalArtifact( request.getArtifact() );
140        }
141
142        Path file = new File( head.getRepository().getBasedir(), artifactPath ).toPath();
143        if ( Files.isRegularFile( file ) )
144        {
145            head.add( session, request );
146        }
147    }
148
149    @Override
150    public LocalMetadataResult find( RepositorySystemSession session, LocalMetadataRequest request )
151    {
152        LocalMetadataResult result = head.find( session, request );
153        if ( result.getFile() != null )
154        {
155            return result;
156        }
157
158        for ( LocalRepositoryManager lrm : tail )
159        {
160            result = lrm.find( session, request );
161            if ( result.getFile() != null )
162            {
163                return result;
164            }
165        }
166        return new LocalMetadataResult( request );
167    }
168
169    @Override
170    public void add( RepositorySystemSession session, LocalMetadataRegistration request )
171    {
172        String metadataPath;
173        if ( request.getRepository() != null )
174        {
175            metadataPath = getPathForRemoteMetadata( request.getMetadata(), request.getRepository(), "check" );
176        }
177        else
178        {
179            metadataPath = getPathForLocalMetadata( request.getMetadata() );
180        }
181
182        Path file = new File( head.getRepository().getBasedir(), metadataPath ).toPath();
183        if ( Files.isRegularFile( file ) )
184        {
185            head.add( session, request );
186        }
187    }
188
189    @Override
190    public String toString()
191    {
192        return head.getRepository().toString()
193                + tail.stream().map( LocalRepositoryManager::getRepository ).collect( toList() );
194    }
195}