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  
27  import javax.inject.Inject;
28  import javax.inject.Named;
29  
30  import org.eclipse.aether.RepositoryCache;
31  import org.eclipse.aether.RepositorySystemSession;
32  import org.eclipse.aether.impl.RemoteRepositoryManager;
33  import org.eclipse.aether.impl.UpdatePolicyAnalyzer;
34  import org.eclipse.aether.repository.Authentication;
35  import org.eclipse.aether.repository.AuthenticationSelector;
36  import org.eclipse.aether.repository.MirrorSelector;
37  import org.eclipse.aether.repository.Proxy;
38  import org.eclipse.aether.repository.ProxySelector;
39  import org.eclipse.aether.repository.RemoteRepository;
40  import org.eclipse.aether.repository.RepositoryPolicy;
41  import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider;
42  import org.eclipse.aether.spi.locator.Service;
43  import org.eclipse.aether.spi.locator.ServiceLocator;
44  import org.eclipse.aether.spi.log.Logger;
45  import org.eclipse.aether.spi.log.LoggerFactory;
46  import org.eclipse.aether.spi.log.NullLoggerFactory;
47  import org.eclipse.aether.util.StringUtils;
48  
49  /**
50   */
51  @Named
52  public class DefaultRemoteRepositoryManager
53      implements RemoteRepositoryManager, Service
54  {
55  
56      private static final class LoggedMirror
57      {
58  
59          private final Object[] keys;
60  
61          public LoggedMirror( RemoteRepository original, RemoteRepository mirror )
62          {
63              keys = new Object[] { mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() };
64          }
65  
66          @Override
67          public boolean equals( Object obj )
68          {
69              if ( this == obj )
70              {
71                  return true;
72              }
73              else if ( !( obj instanceof LoggedMirror ) )
74              {
75                  return false;
76              }
77              LoggedMirror that = (LoggedMirror) obj;
78              return Arrays.equals( keys, that.keys );
79          }
80  
81          @Override
82          public int hashCode()
83          {
84              return Arrays.hashCode( keys );
85          }
86  
87      }
88  
89      private Logger logger = NullLoggerFactory.LOGGER;
90  
91      private UpdatePolicyAnalyzer updatePolicyAnalyzer;
92  
93      private ChecksumPolicyProvider checksumPolicyProvider;
94  
95      public DefaultRemoteRepositoryManager()
96      {
97          // enables default constructor
98      }
99  
100     @Inject
101     DefaultRemoteRepositoryManager( UpdatePolicyAnalyzer updatePolicyAnalyzer,
102                                     ChecksumPolicyProvider checksumPolicyProvider, LoggerFactory loggerFactory )
103     {
104         setUpdatePolicyAnalyzer( updatePolicyAnalyzer );
105         setChecksumPolicyProvider( checksumPolicyProvider );
106         setLoggerFactory( loggerFactory );
107     }
108 
109     public void initService( ServiceLocator locator )
110     {
111         setLoggerFactory( locator.getService( LoggerFactory.class ) );
112         setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) );
113         setChecksumPolicyProvider( locator.getService( ChecksumPolicyProvider.class ) );
114     }
115 
116     public DefaultRemoteRepositoryManager setLoggerFactory( LoggerFactory loggerFactory )
117     {
118         this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() );
119         return this;
120     }
121 
122     public DefaultRemoteRepositoryManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer )
123     {
124         if ( updatePolicyAnalyzer == null )
125         {
126             throw new IllegalArgumentException( "update policy analyzer has not been specified" );
127         }
128         this.updatePolicyAnalyzer = updatePolicyAnalyzer;
129         return this;
130     }
131 
132     public DefaultRemoteRepositoryManager setChecksumPolicyProvider( ChecksumPolicyProvider checksumPolicyProvider )
133     {
134         if ( checksumPolicyProvider == null )
135         {
136             throw new IllegalArgumentException( "checksum policy provider has not been specified" );
137         }
138         this.checksumPolicyProvider = checksumPolicyProvider;
139         return this;
140     }
141 
142     public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session,
143                                                          List<RemoteRepository> dominantRepositories,
144                                                          List<RemoteRepository> recessiveRepositories,
145                                                          boolean recessiveIsRaw )
146     {
147         if ( recessiveRepositories.isEmpty() )
148         {
149             return dominantRepositories;
150         }
151 
152         MirrorSelector mirrorSelector = session.getMirrorSelector();
153         AuthenticationSelector authSelector = session.getAuthenticationSelector();
154         ProxySelector proxySelector = session.getProxySelector();
155 
156         List<RemoteRepository> result = new ArrayList<RemoteRepository>( dominantRepositories );
157 
158         next: for ( RemoteRepository recessiveRepository : recessiveRepositories )
159         {
160             RemoteRepository repository = recessiveRepository;
161 
162             if ( recessiveIsRaw )
163             {
164                 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository );
165 
166                 if ( mirrorRepository != null )
167                 {
168                     logMirror( session, recessiveRepository, mirrorRepository );
169                     repository = mirrorRepository;
170                 }
171             }
172 
173             String key = getKey( repository );
174 
175             for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); )
176             {
177                 RemoteRepository dominantRepository = it.next();
178 
179                 if ( key.equals( getKey( dominantRepository ) ) )
180                 {
181                     if ( !dominantRepository.getMirroredRepositories().isEmpty()
182                         && !repository.getMirroredRepositories().isEmpty() )
183                     {
184                         RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository );
185                         if ( mergedRepository != dominantRepository )
186                         {
187                             it.set( mergedRepository );
188                         }
189                     }
190 
191                     continue next;
192                 }
193             }
194 
195             if ( recessiveIsRaw )
196             {
197                 RemoteRepository.Builder builder = null;
198                 Authentication auth = authSelector.getAuthentication( repository );
199                 if ( auth != null )
200                 {
201                     builder = new RemoteRepository.Builder( repository );
202                     builder.setAuthentication( auth );
203                 }
204                 Proxy proxy = proxySelector.getProxy( repository );
205                 if ( proxy != null )
206                 {
207                     if ( builder == null )
208                     {
209                         builder = new RemoteRepository.Builder( repository );
210                     }
211                     builder.setProxy( proxy );
212                 }
213                 if ( builder != null )
214                 {
215                     repository = builder.build();
216                 }
217             }
218 
219             result.add( repository );
220         }
221 
222         return result;
223     }
224 
225     private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror )
226     {
227         if ( !logger.isDebugEnabled() )
228         {
229             return;
230         }
231         RepositoryCache cache = session.getCache();
232         if ( cache != null )
233         {
234             Object key = new LoggedMirror( original, mirror );
235             if ( cache.get( session, key ) != null )
236             {
237                 return;
238             }
239             cache.put( session, key, Boolean.TRUE );
240         }
241         logger.debug( "Using mirror " + mirror.getId() + " (" + mirror.getUrl() + ") for " + original.getId() + " ("
242             + original.getUrl() + ")." );
243     }
244 
245     private String getKey( RemoteRepository repository )
246     {
247         return repository.getId();
248     }
249 
250     private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant,
251                                            RemoteRepository recessive )
252     {
253         RemoteRepository.Builder merged = null;
254         RepositoryPolicy releases = null, snapshots = null;
255 
256         next: for ( RemoteRepository rec : recessive.getMirroredRepositories() )
257         {
258             String recKey = getKey( rec );
259 
260             for ( RemoteRepository dom : dominant.getMirroredRepositories() )
261             {
262                 if ( recKey.equals( getKey( dom ) ) )
263                 {
264                     continue next;
265                 }
266             }
267 
268             if ( merged == null )
269             {
270                 merged = new RemoteRepository.Builder( dominant );
271                 releases = dominant.getPolicy( false );
272                 snapshots = dominant.getPolicy( true );
273             }
274 
275             releases = merge( session, releases, rec.getPolicy( false ), false );
276             snapshots = merge( session, snapshots, rec.getPolicy( true ), false );
277 
278             merged.addMirroredRepository( rec );
279         }
280 
281         if ( merged == null )
282         {
283             return dominant;
284         }
285         return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build();
286     }
287 
288     public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases,
289                                        boolean snapshots )
290     {
291         RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null;
292         RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null;
293         RepositoryPolicy policy = merge( session, policy1, policy2, true );
294         return policy;
295     }
296 
297     private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1,
298                                     RepositoryPolicy policy2, boolean globalPolicy )
299     {
300         RepositoryPolicy policy;
301 
302         if ( policy2 == null )
303         {
304             if ( globalPolicy )
305             {
306                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
307             }
308             else
309             {
310                 policy = policy1;
311             }
312         }
313         else if ( policy1 == null )
314         {
315             if ( globalPolicy )
316             {
317                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
318             }
319             else
320             {
321                 policy = policy2;
322             }
323         }
324         else if ( !policy2.isEnabled() )
325         {
326             if ( globalPolicy )
327             {
328                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
329             }
330             else
331             {
332                 policy = policy1;
333             }
334         }
335         else if ( !policy1.isEnabled() )
336         {
337             if ( globalPolicy )
338             {
339                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
340             }
341             else
342             {
343                 policy = policy2;
344             }
345         }
346         else
347         {
348             String checksums = session.getChecksumPolicy();
349             if ( globalPolicy && !StringUtils.isEmpty( checksums ) )
350             {
351                 // use global override
352             }
353             else
354             {
355                 checksums =
356                     checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(),
357                                                                        policy2.getChecksumPolicy() );
358             }
359 
360             String updates = session.getUpdatePolicy();
361             if ( globalPolicy && !StringUtils.isEmpty( updates ) )
362             {
363                 // use global override
364             }
365             else
366             {
367                 updates =
368                     updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(),
369                                                                    policy2.getUpdatePolicy() );
370             }
371 
372             policy = new RepositoryPolicy( true, updates, checksums );
373         }
374 
375         return policy;
376     }
377 
378     private RepositoryPolicy merge( RepositoryPolicy policy, String updates, String checksums )
379     {
380         if ( policy != null )
381         {
382             if ( StringUtils.isEmpty( updates ) )
383             {
384                 updates = policy.getUpdatePolicy();
385             }
386             if ( StringUtils.isEmpty( checksums ) )
387             {
388                 checksums = policy.getChecksumPolicy();
389             }
390             if ( !policy.getUpdatePolicy().equals( updates ) || !policy.getChecksumPolicy().equals( checksums ) )
391             {
392                 policy = new RepositoryPolicy( policy.isEnabled(), updates, checksums );
393             }
394         }
395         return policy;
396     }
397 
398 }