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.enforcer.rules;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Objects;
28  
29  import org.apache.maven.artifact.repository.ArtifactRepository;
30  import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
31  import org.apache.maven.project.MavenProject;
32  
33  /**
34   * This rule checks that this project's maven session whether have banned repositories.
35   *
36   * @author <a href="mailto:wangyf2010@gmail.com">Simon Wang</a>
37   */
38  @Named("bannedRepositories")
39  public final class BannedRepositories extends AbstractStandardEnforcerRule {
40  
41      // ----------------------------------------------------------------------
42      // Mojo parameters
43      // ----------------------------------------------------------------------
44  
45      /**
46       * Specify explicitly banned non-plugin repositories. This is a list of repository url patterns. Support wildcard
47       * "*".
48       */
49      private List<String> bannedRepositories = Collections.emptyList();
50  
51      /**
52       * Specify explicitly banned plugin repositories. This is a list of repository url patterns. Support wildcard "*".
53       */
54      private List<String> bannedPluginRepositories = Collections.emptyList();
55  
56      /**
57       * Specify explicitly allowed non-plugin repositories, then all others repositories would be banned. This is a list
58       * of repository url patterns. Support wildcard "*".
59       */
60      private List<String> allowedRepositories = Collections.emptyList();
61  
62      /**
63       * Specify explicitly allowed plugin repositories, then all others repositories would be banned. This is a list of
64       * repository url patterns. Support wildcard "*".
65       */
66      private List<String> allowedPluginRepositories = Collections.emptyList();
67  
68      private final MavenProject project;
69  
70      @Inject
71      public BannedRepositories(MavenProject project) {
72          this.project = Objects.requireNonNull(project);
73      }
74  
75      // ----------------------------------------------------------------------
76      // Public methods
77      // ----------------------------------------------------------------------
78  
79      @Override
80      public void execute() throws EnforcerRuleException {
81  
82          List<ArtifactRepository> resultBannedRepos = checkRepositories(
83                  project.getRemoteArtifactRepositories(), this.allowedRepositories, this.bannedRepositories);
84  
85          List<ArtifactRepository> resultBannedPluginRepos = checkRepositories(
86                  project.getPluginArtifactRepositories(), this.allowedPluginRepositories, this.bannedPluginRepositories);
87  
88          String repoErrMsg = populateErrorMessage(resultBannedRepos, " ");
89          String pluginRepoErrMsg = populateErrorMessage(resultBannedPluginRepos, " plugin ");
90  
91          String errMsg = repoErrMsg + pluginRepoErrMsg;
92  
93          if (errMsg != null && !errMsg.isEmpty()) {
94              throw new EnforcerRuleException(errMsg);
95          }
96      }
97  
98      // ----------------------------------------------------------------------
99      // Protected methods
100     // ----------------------------------------------------------------------
101 
102     protected void setBannedRepositories(List<String> bannedRepositories) {
103         this.bannedRepositories = bannedRepositories;
104     }
105 
106     protected void setAllowedRepositories(List<String> allowedRepositories) {
107         this.allowedRepositories = allowedRepositories;
108     }
109 
110     protected void setAllowedPluginRepositories(List<String> allowedPluginRepositories) {
111         this.allowedPluginRepositories = allowedPluginRepositories;
112     }
113 
114     // ----------------------------------------------------------------------
115     // Private methods
116     // ----------------------------------------------------------------------
117 
118     /**
119      * Check whether specified repositories have banned repositories.
120      *
121      * @param repositories: candidate repositories.
122      * @param includes : 'include' patterns.
123      * @param excludes : 'exclude' patterns.
124      * @return Banned repositories.
125      */
126     private List<ArtifactRepository> checkRepositories(
127             List<ArtifactRepository> repositories, List<String> includes, List<String> excludes) {
128 
129         getLog().debug(() -> String.format(
130                 "Check repositories: %s, for includes=%s and excludes=%s", repositories, includes, excludes));
131 
132         List<ArtifactRepository> bannedRepos = new ArrayList<>();
133 
134         for (ArtifactRepository repo : repositories) {
135             String url = repo.getUrl().trim();
136             if (includes.size() > 0 && !match(url, includes)) {
137                 bannedRepos.add(repo);
138                 continue;
139             }
140 
141             if (excludes.size() > 0 && match(url, excludes)) {
142                 bannedRepos.add(repo);
143             }
144         }
145 
146         return bannedRepos;
147     }
148 
149     private boolean match(String url, List<String> patterns) {
150         for (String pattern : patterns) {
151             if (this.match(url, pattern)) {
152                 return true;
153             }
154         }
155 
156         return false;
157     }
158 
159     private boolean match(String text, String pattern) {
160         return text.matches(pattern.replace("?", ".?").replace("*", ".*?"));
161     }
162 
163     private String populateErrorMessage(List<ArtifactRepository> resultBannedRepos, String errorMessagePrefix) {
164         StringBuffer errMsg = new StringBuffer("");
165         if (!resultBannedRepos.isEmpty()) {
166             errMsg.append("Current maven session contains banned" + errorMessagePrefix
167                     + "repository urls, please double check your pom or settings.xml:" + System.lineSeparator()
168                     + getRepositoryUrlString(resultBannedRepos) + System.lineSeparator() + System.lineSeparator());
169         }
170 
171         return errMsg.toString();
172     }
173 
174     private String getRepositoryUrlString(List<ArtifactRepository> resultBannedRepos) {
175         StringBuilder urls = new StringBuilder("");
176         for (ArtifactRepository repo : resultBannedRepos) {
177             urls.append(repo.getId() + " - " + repo.getUrl() + System.lineSeparator());
178         }
179         return urls.toString();
180     }
181 
182     @Override
183     public String toString() {
184         return String.format(
185                 "BannedRepositories[bannedRepositories=%s, bannedPluginRepositories=%s, allowedRepositories=%s, allowedPluginRepositories=%s",
186                 bannedRepositories, bannedPluginRepositories, allowedRepositories, allowedPluginRepositories);
187     }
188 }