001package org.apache.maven.artifact.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.util.Collections;
024import java.util.List;
025
026import org.apache.commons.lang3.Validate;
027import org.apache.maven.RepositoryUtils;
028import org.apache.maven.artifact.metadata.ArtifactMetadata;
029import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
030import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
031import org.apache.maven.artifact.repository.metadata.RepositoryMetadataStoreException;
032import org.apache.maven.repository.Proxy;
033import org.eclipse.aether.DefaultRepositorySystemSession;
034import org.eclipse.aether.RepositorySystem;
035import org.eclipse.aether.RepositorySystemSession;
036import org.eclipse.aether.artifact.Artifact;
037import org.eclipse.aether.metadata.Metadata;
038import org.eclipse.aether.repository.LocalArtifactRegistration;
039import org.eclipse.aether.repository.LocalArtifactRequest;
040import org.eclipse.aether.repository.LocalArtifactResult;
041import org.eclipse.aether.repository.LocalMetadataRegistration;
042import org.eclipse.aether.repository.LocalMetadataRequest;
043import org.eclipse.aether.repository.LocalMetadataResult;
044import org.eclipse.aether.repository.LocalRepository;
045import org.eclipse.aether.repository.LocalRepositoryManager;
046import org.eclipse.aether.repository.RemoteRepository;
047
048/**
049 * <strong>Warning:</strong> This is an internal utility class that is only public for technical reasons, it is not part
050 * of the public API. In particular, this class can be changed or deleted without prior notice.
051 *
052 * @author Benjamin Bentmann
053 */
054public class LegacyLocalRepositoryManager
055    implements LocalRepositoryManager
056{
057
058    private final ArtifactRepository delegate;
059
060    private final LocalRepository repo;
061
062    private final boolean realLocalRepo;
063
064    public static RepositorySystemSession overlay( ArtifactRepository repository, RepositorySystemSession session,
065                                                   RepositorySystem system )
066    {
067        if ( repository == null || repository.getBasedir() == null )
068        {
069            return session;
070        }
071
072        if ( session != null )
073        {
074            LocalRepositoryManager lrm = session.getLocalRepositoryManager();
075            if ( lrm != null && lrm.getRepository().getBasedir().equals( new File( repository.getBasedir() ) ) )
076            {
077                return session;
078            }
079        }
080        else
081        {
082            session = new DefaultRepositorySystemSession();
083        }
084
085        final LocalRepositoryManager llrm = new LegacyLocalRepositoryManager( repository );
086
087        return new DefaultRepositorySystemSession( session ).setLocalRepositoryManager( llrm );
088    }
089
090    private LegacyLocalRepositoryManager( ArtifactRepository delegate )
091    {
092        this.delegate = Validate.notNull( delegate, "delegate cannot be null" );
093
094        ArtifactRepositoryLayout layout = delegate.getLayout();
095        repo =
096            new LocalRepository( new File( delegate.getBasedir() ),
097                                 ( layout != null ) ? layout.getClass().getSimpleName() : "legacy" );
098
099        /*
100         * NOTE: "invoker:install" vs "appassembler:assemble": Both mojos use the artifact installer to put an artifact
101         * into a repository. In the first case, the result needs to be a proper local repository that one can use for
102         * local artifact resolution. In the second case, the result needs to precisely obey the path information of the
103         * repository's layout to allow pointing at artifacts within the repository. Unfortunately,
104         * DefaultRepositoryLayout does not correctly describe the layout of a local repository which unlike a remote
105         * repository never uses timestamps in the filename of a snapshot artifact. The discrepancy gets notable when a
106         * remotely resolved snapshot artifact gets passed into pathOf(). So producing a proper local artifact path
107         * using DefaultRepositoryLayout requires us to enforce usage of the artifact's base version. This
108         * transformation however contradicts the other use case of precisely obeying the repository's layout. The below
109         * flag tries to detect which use case applies to make both plugins happy.
110         */
111        realLocalRepo = ( layout instanceof DefaultRepositoryLayout ) && "local".equals( delegate.getId() );
112    }
113
114    public LocalRepository getRepository()
115    {
116        return repo;
117    }
118
119    public String getPathForLocalArtifact( Artifact artifact )
120    {
121        if ( realLocalRepo )
122        {
123            return delegate.pathOf( RepositoryUtils.toArtifact( artifact.setVersion( artifact.getBaseVersion() ) ) );
124        }
125        return delegate.pathOf( RepositoryUtils.toArtifact( artifact ) );
126    }
127
128    public String getPathForRemoteArtifact( Artifact artifact, RemoteRepository repository, String context )
129    {
130        return delegate.pathOf( RepositoryUtils.toArtifact( artifact ) );
131    }
132
133    public String getPathForLocalMetadata( Metadata metadata )
134    {
135        return delegate.pathOfLocalRepositoryMetadata( new ArtifactMetadataAdapter( metadata ), delegate );
136    }
137
138    public String getPathForRemoteMetadata( Metadata metadata, RemoteRepository repository, String context )
139    {
140        return delegate.pathOfLocalRepositoryMetadata( new ArtifactMetadataAdapter( metadata ),
141                                                       new ArtifactRepositoryAdapter( repository ) );
142    }
143
144    public LocalArtifactResult find( RepositorySystemSession session, LocalArtifactRequest request )
145    {
146        String path = getPathForLocalArtifact( request.getArtifact() );
147        File file = new File( getRepository().getBasedir(), path );
148
149        LocalArtifactResult result = new LocalArtifactResult( request );
150        if ( file.isFile() )
151        {
152            result.setFile( file );
153            result.setAvailable( true );
154        }
155
156        return result;
157    }
158
159    public LocalMetadataResult find( RepositorySystemSession session, LocalMetadataRequest request )
160    {
161        Metadata metadata = request.getMetadata();
162
163        String path;
164        if ( request.getRepository() == null )
165        {
166            path = getPathForLocalMetadata( metadata );
167        }
168        else
169        {
170            path = getPathForRemoteMetadata( metadata, request.getRepository(), request.getContext() );
171        }
172
173        File file = new File( getRepository().getBasedir(), path );
174
175        LocalMetadataResult result = new LocalMetadataResult( request );
176        if ( file.isFile() )
177        {
178            result.setFile( file );
179        }
180
181        return result;
182    }
183
184    public void add( RepositorySystemSession session, LocalArtifactRegistration request )
185    {
186        // noop
187    }
188
189    public void add( RepositorySystemSession session, LocalMetadataRegistration request )
190    {
191        // noop
192    }
193
194    static class ArtifactMetadataAdapter
195        implements ArtifactMetadata
196    {
197
198        private final Metadata metadata;
199
200        public ArtifactMetadataAdapter( Metadata metadata )
201        {
202            this.metadata = metadata;
203        }
204
205        public boolean storedInArtifactVersionDirectory()
206        {
207            return metadata.getVersion().length() > 0;
208        }
209
210        public boolean storedInGroupDirectory()
211        {
212            return metadata.getArtifactId().length() <= 0;
213        }
214
215        public String getGroupId()
216        {
217            return nullify( metadata.getGroupId() );
218        }
219
220        public String getArtifactId()
221        {
222            return nullify( metadata.getArtifactId() );
223        }
224
225        public String getBaseVersion()
226        {
227            return nullify( metadata.getVersion() );
228        }
229
230        private String nullify( String str )
231        {
232            return ( str == null || str.length() <= 0 ) ? null : str;
233        }
234
235        public Object getKey()
236        {
237            return metadata.toString();
238        }
239
240        public String getRemoteFilename()
241        {
242            return metadata.getType();
243        }
244
245        public String getLocalFilename( ArtifactRepository repository )
246        {
247            return insertRepositoryKey( getRemoteFilename(), repository.getKey() );
248        }
249
250        private String insertRepositoryKey( String filename, String repositoryKey )
251        {
252            String result;
253            int idx = filename.indexOf( '.' );
254            if ( idx < 0 )
255            {
256                result = filename + '-' + repositoryKey;
257            }
258            else
259            {
260                result = filename.substring( 0, idx ) + '-' + repositoryKey + filename.substring( idx );
261            }
262            return result;
263        }
264
265        public void merge( org.apache.maven.repository.legacy.metadata.ArtifactMetadata metadata )
266        {
267            // not used
268        }
269
270        public void merge( ArtifactMetadata metadata )
271        {
272            // not used
273        }
274
275        public void storeInLocalRepository( ArtifactRepository localRepository, ArtifactRepository remoteRepository )
276            throws RepositoryMetadataStoreException
277        {
278            // not used
279        }
280
281        public String extendedToString()
282        {
283            return metadata.toString();
284        }
285
286    }
287
288    static class ArtifactRepositoryAdapter
289        implements ArtifactRepository
290    {
291
292        private final RemoteRepository repository;
293
294        public ArtifactRepositoryAdapter( RemoteRepository repository )
295        {
296            this.repository = repository;
297        }
298
299        public String pathOf( org.apache.maven.artifact.Artifact artifact )
300        {
301            return null;
302        }
303
304        public String pathOfRemoteRepositoryMetadata( ArtifactMetadata artifactMetadata )
305        {
306            return null;
307        }
308
309        public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository )
310        {
311            return null;
312        }
313
314        public String getUrl()
315        {
316            return repository.getUrl();
317        }
318
319        public void setUrl( String url )
320        {
321        }
322
323        public String getBasedir()
324        {
325            return null;
326        }
327
328        public String getProtocol()
329        {
330            return repository.getProtocol();
331        }
332
333        public String getId()
334        {
335            return repository.getId();
336        }
337
338        public void setId( String id )
339        {
340        }
341
342        public ArtifactRepositoryPolicy getSnapshots()
343        {
344            return null;
345        }
346
347        public void setSnapshotUpdatePolicy( ArtifactRepositoryPolicy policy )
348        {
349        }
350
351        public ArtifactRepositoryPolicy getReleases()
352        {
353            return null;
354        }
355
356        public void setReleaseUpdatePolicy( ArtifactRepositoryPolicy policy )
357        {
358        }
359
360        public ArtifactRepositoryLayout getLayout()
361        {
362            return null;
363        }
364
365        public void setLayout( ArtifactRepositoryLayout layout )
366        {
367        }
368
369        public String getKey()
370        {
371            return getId();
372        }
373
374        public boolean isUniqueVersion()
375        {
376            return true;
377        }
378
379        public boolean isBlacklisted()
380        {
381            return false;
382        }
383
384        public void setBlacklisted( boolean blackListed )
385        {
386        }
387
388        public org.apache.maven.artifact.Artifact find( org.apache.maven.artifact.Artifact artifact )
389        {
390            return null;
391        }
392
393        public List<String> findVersions( org.apache.maven.artifact.Artifact artifact )
394        {
395            return Collections.emptyList();
396        }
397
398        public boolean isProjectAware()
399        {
400            return false;
401        }
402
403        public void setAuthentication( Authentication authentication )
404        {
405        }
406
407        public Authentication getAuthentication()
408        {
409            return null;
410        }
411
412        public void setProxy( Proxy proxy )
413        {
414        }
415
416        public Proxy getProxy()
417        {
418            return null;
419        }
420
421        public List<ArtifactRepository> getMirroredRepositories()
422        {
423            return Collections.emptyList();
424        }
425
426        public void setMirroredRepositories( List<ArtifactRepository> mirroredRepositories )
427        {
428        }
429
430    }
431
432}