View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.ListIterator;
26  import static java.util.Objects.requireNonNull;
27  
28  import javax.inject.Inject;
29  import javax.inject.Named;
30  import javax.inject.Singleton;
31  
32  import org.apache.commons.lang3.StringUtils;
33  import org.eclipse.aether.RepositoryCache;
34  import org.eclipse.aether.RepositorySystemSession;
35  import org.eclipse.aether.impl.RemoteRepositoryManager;
36  import org.eclipse.aether.impl.UpdatePolicyAnalyzer;
37  import org.eclipse.aether.repository.Authentication;
38  import org.eclipse.aether.repository.AuthenticationSelector;
39  import org.eclipse.aether.repository.MirrorSelector;
40  import org.eclipse.aether.repository.Proxy;
41  import org.eclipse.aether.repository.ProxySelector;
42  import org.eclipse.aether.repository.RemoteRepository;
43  import org.eclipse.aether.repository.RepositoryPolicy;
44  import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider;
45  import org.eclipse.aether.spi.locator.Service;
46  import org.eclipse.aether.spi.locator.ServiceLocator;
47  import org.slf4j.Logger;
48  import org.slf4j.LoggerFactory;
49  
50  /**
51   */
52  @Singleton
53  @Named
54  public class DefaultRemoteRepositoryManager
55      implements RemoteRepositoryManager, Service
56  {
57  
58      private static final class LoggedMirror
59      {
60  
61          private final Object[] keys;
62  
63          LoggedMirror( RemoteRepository original, RemoteRepository mirror )
64          {
65              keys = new Object[] { mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() };
66          }
67  
68          @Override
69          public boolean equals( Object obj )
70          {
71              if ( this == obj )
72              {
73                  return true;
74              }
75              else if ( !( obj instanceof LoggedMirror ) )
76              {
77                  return false;
78              }
79              LoggedMirror that = (LoggedMirror) obj;
80              return Arrays.equals( keys, that.keys );
81          }
82  
83          @Override
84          public int hashCode()
85          {
86              return Arrays.hashCode( keys );
87          }
88  
89      }
90  
91      private static final Logger LOGGER = LoggerFactory.getLogger( DefaultRemoteRepositoryManager.class );
92  
93      private UpdatePolicyAnalyzer updatePolicyAnalyzer;
94  
95      private ChecksumPolicyProvider checksumPolicyProvider;
96  
97      public DefaultRemoteRepositoryManager()
98      {
99          // enables default constructor
100     }
101 
102     @Inject
103     DefaultRemoteRepositoryManager( UpdatePolicyAnalyzer updatePolicyAnalyzer,
104                                     ChecksumPolicyProvider checksumPolicyProvider )
105     {
106         setUpdatePolicyAnalyzer( updatePolicyAnalyzer );
107         setChecksumPolicyProvider( checksumPolicyProvider );
108     }
109 
110     public void initService( ServiceLocator locator )
111     {
112         setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) );
113         setChecksumPolicyProvider( locator.getService( ChecksumPolicyProvider.class ) );
114     }
115 
116     public DefaultRemoteRepositoryManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer )
117     {
118         this.updatePolicyAnalyzer = requireNonNull( updatePolicyAnalyzer, "update policy analyzer cannot be null" );
119         return this;
120     }
121 
122     public DefaultRemoteRepositoryManager setChecksumPolicyProvider( ChecksumPolicyProvider checksumPolicyProvider )
123     {
124         this.checksumPolicyProvider = requireNonNull(
125                 checksumPolicyProvider, "checksum policy provider cannot be null" );
126         return this;
127     }
128 
129     public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session,
130                                                          List<RemoteRepository> dominantRepositories,
131                                                          List<RemoteRepository> recessiveRepositories,
132                                                          boolean recessiveIsRaw )
133     {
134         requireNonNull( session, "session cannot be null" );
135         requireNonNull( dominantRepositories, "dominantRepositories cannot be null" );
136         requireNonNull( recessiveRepositories, "recessiveRepositories cannot be null" );
137         if ( recessiveRepositories.isEmpty() )
138         {
139             return dominantRepositories;
140         }
141 
142         MirrorSelector mirrorSelector = session.getMirrorSelector();
143         AuthenticationSelector authSelector = session.getAuthenticationSelector();
144         ProxySelector proxySelector = session.getProxySelector();
145 
146         List<RemoteRepository> result = new ArrayList<>( dominantRepositories );
147 
148         next: for ( RemoteRepository recessiveRepository : recessiveRepositories )
149         {
150             RemoteRepository repository = recessiveRepository;
151 
152             if ( recessiveIsRaw )
153             {
154                 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository );
155 
156                 if ( mirrorRepository != null )
157                 {
158                     logMirror( session, recessiveRepository, mirrorRepository );
159                     repository = mirrorRepository;
160                 }
161             }
162 
163             String key = getKey( repository );
164 
165             for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); )
166             {
167                 RemoteRepository dominantRepository = it.next();
168 
169                 if ( key.equals( getKey( dominantRepository ) ) )
170                 {
171                     if ( !dominantRepository.getMirroredRepositories().isEmpty()
172                         && !repository.getMirroredRepositories().isEmpty() )
173                     {
174                         RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository );
175                         if ( mergedRepository != dominantRepository )
176                         {
177                             it.set( mergedRepository );
178                         }
179                     }
180 
181                     continue next;
182                 }
183             }
184 
185             if ( recessiveIsRaw )
186             {
187                 RemoteRepository.Builder builder = null;
188                 Authentication auth = authSelector.getAuthentication( repository );
189                 if ( auth != null )
190                 {
191                     builder = new RemoteRepository.Builder( repository );
192                     builder.setAuthentication( auth );
193                 }
194                 Proxy proxy = proxySelector.getProxy( repository );
195                 if ( proxy != null )
196                 {
197                     if ( builder == null )
198                     {
199                         builder = new RemoteRepository.Builder( repository );
200                     }
201                     builder.setProxy( proxy );
202                 }
203                 if ( builder != null )
204                 {
205                     repository = builder.build();
206                 }
207             }
208 
209             result.add( repository );
210         }
211 
212         return result;
213     }
214 
215     private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror )
216     {
217         if ( !LOGGER.isDebugEnabled() )
218         {
219             return;
220         }
221         RepositoryCache cache = session.getCache();
222         if ( cache != null )
223         {
224             Object key = new LoggedMirror( original, mirror );
225             if ( cache.get( session, key ) != null )
226             {
227                 return;
228             }
229             cache.put( session, key, Boolean.TRUE );
230         }
231         LOGGER.debug( "Using mirror {} ({}) for {} ({}).",
232                 mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() );
233     }
234 
235     private String getKey( RemoteRepository repository )
236     {
237         return repository.getId();
238     }
239 
240     private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant,
241                                            RemoteRepository recessive )
242     {
243         RemoteRepository.Builder merged = null;
244         RepositoryPolicy releases = null, snapshots = null;
245 
246         next: for ( RemoteRepository rec : recessive.getMirroredRepositories() )
247         {
248             String recKey = getKey( rec );
249 
250             for ( RemoteRepository dom : dominant.getMirroredRepositories() )
251             {
252                 if ( recKey.equals( getKey( dom ) ) )
253                 {
254                     continue next;
255                 }
256             }
257 
258             if ( merged == null )
259             {
260                 merged = new RemoteRepository.Builder( dominant );
261                 releases = dominant.getPolicy( false );
262                 snapshots = dominant.getPolicy( true );
263             }
264 
265             releases = merge( session, releases, rec.getPolicy( false ), false );
266             snapshots = merge( session, snapshots, rec.getPolicy( true ), false );
267 
268             merged.addMirroredRepository( rec );
269         }
270 
271         if ( merged == null )
272         {
273             return dominant;
274         }
275         return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build();
276     }
277 
278     public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases,
279                                        boolean snapshots )
280     {
281         requireNonNull( session, "session cannot be null" );
282         requireNonNull( repository, "repository cannot be null" );
283         RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null;
284         RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null;
285         return merge( session, policy1, policy2, true );
286     }
287 
288     private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1,
289                                     RepositoryPolicy policy2, boolean globalPolicy )
290     {
291         RepositoryPolicy policy;
292 
293         if ( policy2 == null )
294         {
295             if ( globalPolicy )
296             {
297                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
298             }
299             else
300             {
301                 policy = policy1;
302             }
303         }
304         else if ( policy1 == null )
305         {
306             if ( globalPolicy )
307             {
308                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
309             }
310             else
311             {
312                 policy = policy2;
313             }
314         }
315         else if ( !policy2.isEnabled() )
316         {
317             if ( globalPolicy )
318             {
319                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
320             }
321             else
322             {
323                 policy = policy1;
324             }
325         }
326         else if ( !policy1.isEnabled() )
327         {
328             if ( globalPolicy )
329             {
330                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
331             }
332             else
333             {
334                 policy = policy2;
335             }
336         }
337         else
338         {
339             String checksums = session.getChecksumPolicy();
340             //noinspection StatementWithEmptyBody
341             if ( globalPolicy && !StringUtils.isEmpty( checksums ) )
342             {
343                 // use global override
344             }
345             else
346             {
347                 checksums =
348                     checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(),
349                                                                        policy2.getChecksumPolicy() );
350             }
351 
352             String updates = session.getUpdatePolicy();
353             //noinspection StatementWithEmptyBody
354             if ( globalPolicy && !StringUtils.isEmpty( updates ) )
355             {
356                 // use global override
357             }
358             else
359             {
360                 updates =
361                     updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(),
362                                                                    policy2.getUpdatePolicy() );
363             }
364 
365             policy = new RepositoryPolicy( true, updates, checksums );
366         }
367 
368         return policy;
369     }
370 
371     private RepositoryPolicy merge( RepositoryPolicy policy, String updates, String checksums )
372     {
373         if ( policy != null )
374         {
375             if ( StringUtils.isEmpty( updates ) )
376             {
377                 updates = policy.getUpdatePolicy();
378             }
379             if ( StringUtils.isEmpty( checksums ) )
380             {
381                 checksums = policy.getChecksumPolicy();
382             }
383             if ( !policy.getUpdatePolicy().equals( updates ) || !policy.getChecksumPolicy().equals( checksums ) )
384             {
385                 policy = new RepositoryPolicy( policy.isEnabled(), updates, checksums );
386             }
387         }
388         return policy;
389     }
390 
391 }