View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.repository;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.util.List;
27  
28  import org.apache.maven.RepositoryUtils;
29  import org.apache.maven.artifact.repository.ArtifactRepository;
30  import org.apache.maven.settings.Mirror;
31  
32  /**
33   * DefaultMirrorSelector
34   */
35  @Named
36  @Singleton
37  @Deprecated
38  public class DefaultMirrorSelector implements MirrorSelector {
39  
40      private static final String WILDCARD = "*";
41  
42      private static final String EXTERNAL_WILDCARD = "external:*";
43  
44      private static final String EXTERNAL_HTTP_WILDCARD = "external:http:*";
45  
46      public Mirror getMirror(ArtifactRepository repository, List<Mirror> mirrors) {
47          String repoId = repository.getId();
48  
49          if (repoId != null && mirrors != null) {
50              for (Mirror mirror : mirrors) {
51                  if (repoId.equals(mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {
52                      return mirror;
53                  }
54              }
55  
56              for (Mirror mirror : mirrors) {
57                  if (matchPattern(repository, mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {
58                      return mirror;
59                  }
60              }
61          }
62  
63          return null;
64      }
65  
66      /**
67       * This method checks if the pattern matches the originalRepository. Valid patterns:
68       * <ul>
69       * <li>{@code *} = everything,</li>
70       * <li>{@code external:*} = everything not on the localhost and not file based,</li>
71       * <li>{@code external:http:*} = any repository not on the localhost using HTTP,</li>
72       * <li>{@code repo,repo1} = {@code repo} or {@code repo1},</li>
73       * <li>{@code *,!repo1} = everything except {@code repo1}.</li>
74       * </ul>
75       *
76       * @param originalRepository to compare for a match.
77       * @param pattern used for match.
78       * @return true if the repository is a match to this pattern.
79       */
80      static boolean matchPattern(ArtifactRepository originalRepository, String pattern) {
81          boolean result = false;
82          String originalId = originalRepository.getId();
83  
84          // simple checks first to short circuit processing below.
85          if (WILDCARD.equals(pattern) || pattern.equals(originalId)) {
86              result = true;
87          } else {
88              // process the list
89              String[] repos = pattern.split(",");
90              for (String repo : repos) {
91                  repo = repo.trim();
92                  // see if this is a negative match
93                  if (repo.length() > 1 && repo.startsWith("!")) {
94                      if (repo.substring(1).equals(originalId)) {
95                          // explicitly exclude. Set result and stop processing.
96                          result = false;
97                          break;
98                      }
99                  }
100                 // check for exact match
101                 else if (repo.equals(originalId)) {
102                     result = true;
103                     break;
104                 }
105                 // check for external:*
106                 else if (EXTERNAL_WILDCARD.equals(repo) && isExternalRepo(originalRepository)) {
107                     result = true;
108                     // don't stop processing in case a future segment explicitly excludes this repo
109                 }
110                 // check for external:http:*
111                 else if (EXTERNAL_HTTP_WILDCARD.equals(repo) && isExternalHttpRepo(originalRepository)) {
112                     result = true;
113                     // don't stop processing in case a future segment explicitly excludes this repo
114                 } else if (WILDCARD.equals(repo)) {
115                     result = true;
116                     // don't stop processing in case a future segment explicitly excludes this repo
117                 }
118             }
119         }
120         return result;
121     }
122 
123     /**
124      * Checks the URL to see if this repository refers to an external repository
125      *
126      * @param originalRepository
127      * @return true if external.
128      */
129     static boolean isExternalRepo(ArtifactRepository originalRepository) {
130         try {
131             URL url = new URL(originalRepository.getUrl());
132             return !(isLocal(url.getHost()) || url.getProtocol().equals("file"));
133         } catch (MalformedURLException e) {
134             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
135             return false;
136         }
137     }
138 
139     private static boolean isLocal(String host) {
140         return "localhost".equals(host) || "127.0.0.1".equals(host);
141     }
142 
143     /**
144      * Checks the URL to see if this repository refers to a non-localhost repository using HTTP.
145      *
146      * @param originalRepository
147      * @return true if external.
148      */
149     static boolean isExternalHttpRepo(ArtifactRepository originalRepository) {
150         try {
151             URL url = new URL(originalRepository.getUrl());
152             return ("http".equalsIgnoreCase(url.getProtocol())
153                             || "dav".equalsIgnoreCase(url.getProtocol())
154                             || "dav:http".equalsIgnoreCase(url.getProtocol())
155                             || "dav+http".equalsIgnoreCase(url.getProtocol()))
156                     && !isLocal(url.getHost());
157         } catch (MalformedURLException e) {
158             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
159             return false;
160         }
161     }
162 
163     static boolean matchesLayout(ArtifactRepository repository, Mirror mirror) {
164         return matchesLayout(RepositoryUtils.getLayout(repository), mirror.getMirrorOfLayouts());
165     }
166 
167     /**
168      * Checks whether the layouts configured for a mirror match with the layout of the repository.
169      *
170      * @param repoLayout The layout of the repository, may be {@code null}.
171      * @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
172      * @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
173      *         {@code false} otherwise.
174      */
175     static boolean matchesLayout(String repoLayout, String mirrorLayout) {
176         boolean result = false;
177 
178         // simple checks first to short circuit processing below.
179         if ((mirrorLayout == null || mirrorLayout.isEmpty()) || WILDCARD.equals(mirrorLayout)) {
180             result = true;
181         } else if (mirrorLayout.equals(repoLayout)) {
182             result = true;
183         } else {
184             // process the list
185             String[] layouts = mirrorLayout.split(",");
186             for (String layout : layouts) {
187                 // see if this is a negative match
188                 if (layout.length() > 1 && layout.startsWith("!")) {
189                     if (layout.substring(1).equals(repoLayout)) {
190                         // explicitly exclude. Set result and stop processing.
191                         result = false;
192                         break;
193                     }
194                 }
195                 // check for exact match
196                 else if (layout.equals(repoLayout)) {
197                     result = true;
198                     break;
199                 } else if (WILDCARD.equals(layout)) {
200                     result = true;
201                     // don't stop processing in case a future segment explicitly excludes this repo
202                 }
203             }
204         }
205 
206         return result;
207     }
208 }