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