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.apache.commons.lang3.StringUtils;
32  import org.eclipse.aether.RepositoryCache;
33  import org.eclipse.aether.RepositorySystemSession;
34  import org.eclipse.aether.impl.RemoteRepositoryManager;
35  import org.eclipse.aether.impl.UpdatePolicyAnalyzer;
36  import org.eclipse.aether.repository.Authentication;
37  import org.eclipse.aether.repository.AuthenticationSelector;
38  import org.eclipse.aether.repository.MirrorSelector;
39  import org.eclipse.aether.repository.Proxy;
40  import org.eclipse.aether.repository.ProxySelector;
41  import org.eclipse.aether.repository.RemoteRepository;
42  import org.eclipse.aether.repository.RepositoryPolicy;
43  import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider;
44  import org.eclipse.aether.spi.locator.Service;
45  import org.eclipse.aether.spi.locator.ServiceLocator;
46  import org.slf4j.Logger;
47  import org.slf4j.LoggerFactory;
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          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 static final Logger LOGGER = LoggerFactory.getLogger( DefaultRemoteRepositoryManager.class );
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 )
103     {
104         setUpdatePolicyAnalyzer( updatePolicyAnalyzer );
105         setChecksumPolicyProvider( checksumPolicyProvider );
106     }
107 
108     public void initService( ServiceLocator locator )
109     {
110         setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) );
111         setChecksumPolicyProvider( locator.getService( ChecksumPolicyProvider.class ) );
112     }
113 
114     public DefaultRemoteRepositoryManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer )
115     {
116         this.updatePolicyAnalyzer = requireNonNull( updatePolicyAnalyzer, "update policy analyzer cannot be null" );
117         return this;
118     }
119 
120     public DefaultRemoteRepositoryManager setChecksumPolicyProvider( ChecksumPolicyProvider checksumPolicyProvider )
121     {
122         this.checksumPolicyProvider = requireNonNull(
123                 checksumPolicyProvider, "checksum policy provider cannot be null" );
124         return this;
125     }
126 
127     public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session,
128                                                          List<RemoteRepository> dominantRepositories,
129                                                          List<RemoteRepository> recessiveRepositories,
130                                                          boolean recessiveIsRaw )
131     {
132         if ( recessiveRepositories.isEmpty() )
133         {
134             return dominantRepositories;
135         }
136 
137         MirrorSelector mirrorSelector = session.getMirrorSelector();
138         AuthenticationSelector authSelector = session.getAuthenticationSelector();
139         ProxySelector proxySelector = session.getProxySelector();
140 
141         List<RemoteRepository> result = new ArrayList<>( dominantRepositories );
142 
143         next: for ( RemoteRepository recessiveRepository : recessiveRepositories )
144         {
145             RemoteRepository repository = recessiveRepository;
146 
147             if ( recessiveIsRaw )
148             {
149                 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository );
150 
151                 if ( mirrorRepository != null )
152                 {
153                     logMirror( session, recessiveRepository, mirrorRepository );
154                     repository = mirrorRepository;
155                 }
156             }
157 
158             String key = getKey( repository );
159 
160             for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); )
161             {
162                 RemoteRepository dominantRepository = it.next();
163 
164                 if ( key.equals( getKey( dominantRepository ) ) )
165                 {
166                     if ( !dominantRepository.getMirroredRepositories().isEmpty()
167                         && !repository.getMirroredRepositories().isEmpty() )
168                     {
169                         RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository );
170                         if ( mergedRepository != dominantRepository )
171                         {
172                             it.set( mergedRepository );
173                         }
174                     }
175 
176                     continue next;
177                 }
178             }
179 
180             if ( recessiveIsRaw )
181             {
182                 RemoteRepository.Builder builder = null;
183                 Authentication auth = authSelector.getAuthentication( repository );
184                 if ( auth != null )
185                 {
186                     builder = new RemoteRepository.Builder( repository );
187                     builder.setAuthentication( auth );
188                 }
189                 Proxy proxy = proxySelector.getProxy( repository );
190                 if ( proxy != null )
191                 {
192                     if ( builder == null )
193                     {
194                         builder = new RemoteRepository.Builder( repository );
195                     }
196                     builder.setProxy( proxy );
197                 }
198                 if ( builder != null )
199                 {
200                     repository = builder.build();
201                 }
202             }
203 
204             result.add( repository );
205         }
206 
207         return result;
208     }
209 
210     private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror )
211     {
212         if ( !LOGGER.isDebugEnabled() )
213         {
214             return;
215         }
216         RepositoryCache cache = session.getCache();
217         if ( cache != null )
218         {
219             Object key = new LoggedMirror( original, mirror );
220             if ( cache.get( session, key ) != null )
221             {
222                 return;
223             }
224             cache.put( session, key, Boolean.TRUE );
225         }
226         LOGGER.debug( "Using mirror {} ({}) for {} ({}).",
227                 mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() );
228     }
229 
230     private String getKey( RemoteRepository repository )
231     {
232         return repository.getId();
233     }
234 
235     private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant,
236                                            RemoteRepository recessive )
237     {
238         RemoteRepository.Builder merged = null;
239         RepositoryPolicy releases = null, snapshots = null;
240 
241         next: for ( RemoteRepository rec : recessive.getMirroredRepositories() )
242         {
243             String recKey = getKey( rec );
244 
245             for ( RemoteRepository dom : dominant.getMirroredRepositories() )
246             {
247                 if ( recKey.equals( getKey( dom ) ) )
248                 {
249                     continue next;
250                 }
251             }
252 
253             if ( merged == null )
254             {
255                 merged = new RemoteRepository.Builder( dominant );
256                 releases = dominant.getPolicy( false );
257                 snapshots = dominant.getPolicy( true );
258             }
259 
260             releases = merge( session, releases, rec.getPolicy( false ), false );
261             snapshots = merge( session, snapshots, rec.getPolicy( true ), false );
262 
263             merged.addMirroredRepository( rec );
264         }
265 
266         if ( merged == null )
267         {
268             return dominant;
269         }
270         return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build();
271     }
272 
273     public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases,
274                                        boolean snapshots )
275     {
276         RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null;
277         RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null;
278         return merge( session, policy1, policy2, true );
279     }
280 
281     private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1,
282                                     RepositoryPolicy policy2, boolean globalPolicy )
283     {
284         RepositoryPolicy policy;
285 
286         if ( policy2 == null )
287         {
288             if ( globalPolicy )
289             {
290                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
291             }
292             else
293             {
294                 policy = policy1;
295             }
296         }
297         else if ( policy1 == null )
298         {
299             if ( globalPolicy )
300             {
301                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
302             }
303             else
304             {
305                 policy = policy2;
306             }
307         }
308         else if ( !policy2.isEnabled() )
309         {
310             if ( globalPolicy )
311             {
312                 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() );
313             }
314             else
315             {
316                 policy = policy1;
317             }
318         }
319         else if ( !policy1.isEnabled() )
320         {
321             if ( globalPolicy )
322             {
323                 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() );
324             }
325             else
326             {
327                 policy = policy2;
328             }
329         }
330         else
331         {
332             String checksums = session.getChecksumPolicy();
333             //noinspection StatementWithEmptyBody
334             if ( globalPolicy && !StringUtils.isEmpty( checksums ) )
335             {
336                 // use global override
337             }
338             else
339             {
340                 checksums =
341                     checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(),
342                                                                        policy2.getChecksumPolicy() );
343             }
344 
345             String updates = session.getUpdatePolicy();
346             //noinspection StatementWithEmptyBody
347             if ( globalPolicy && !StringUtils.isEmpty( updates ) )
348             {
349                 // use global override
350             }
351             else
352             {
353                 updates =
354                     updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(),
355                                                                    policy2.getUpdatePolicy() );
356             }
357 
358             policy = new RepositoryPolicy( true, updates, checksums );
359         }
360 
361         return policy;
362     }
363 
364     private RepositoryPolicy merge( RepositoryPolicy policy, String updates, String checksums )
365     {
366         if ( policy != null )
367         {
368             if ( StringUtils.isEmpty( updates ) )
369             {
370                 updates = policy.getUpdatePolicy();
371             }
372             if ( StringUtils.isEmpty( checksums ) )
373             {
374                 checksums = policy.getChecksumPolicy();
375             }
376             if ( !policy.getUpdatePolicy().equals( updates ) || !policy.getChecksumPolicy().equals( checksums ) )
377             {
378                 policy = new RepositoryPolicy( policy.isEnabled(), updates, checksums );
379             }
380         }
381         return policy;
382     }
383 
384 }