001package org.apache.maven.plugins.enforcer; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025 026import org.apache.maven.enforcer.rule.api.EnforcerRuleException; 027import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; 028import org.apache.maven.execution.MavenSession; 029import org.apache.maven.model.Model; 030import org.apache.maven.model.Repository; 031import org.apache.maven.plugin.logging.Log; 032import org.apache.maven.project.MavenProject; 033import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; 034import org.codehaus.plexus.util.StringUtils; 035 036/** 037 * This rule checks that this pom or its parents don't define a repository. 038 * 039 * @author <a href="mailto:brianf@apache.org">Brian Fox</a> 040 */ 041public class RequireNoRepositories 042 extends AbstractNonCacheableEnforcerRule 043{ 044 private static final String VERSION = " version:"; 045 046 /** 047 * Whether to ban non-plugin repositories. By default they are banned. 048 * 049 * @see #setBanRepositories(boolean) 050 */ 051 private boolean banRepositories = true; 052 053 /** 054 * Whether to ban plugin repositories. By default they are banned. 055 * 056 * @see #setBanPluginRepositories(boolean) 057 */ 058 private boolean banPluginRepositories = true; 059 060 /** 061 * Specify explicitly allowed non-plugin repositories. This is a list of ids. 062 * 063 * @see #setAllowedRepositories(List) 064 */ 065 private List<String> allowedRepositories = Collections.emptyList(); 066 067 /** 068 * Specify explicitly allowed plugin repositories. This is a list of ids. 069 * 070 * @see #setAllowedPluginRepositories(List) 071 */ 072 private List<String> allowedPluginRepositories = Collections.emptyList(); 073 074 /** 075 * Whether to allow repositories which only resolve snapshots. By default they are banned. 076 * 077 * @see #setAllowSnapshotRepositories(boolean) 078 */ 079 private boolean allowSnapshotRepositories = false; 080 081 /** 082 * Whether to allow plugin repositories which only resolve snapshots. By default they are banned. 083 * 084 * @see {@link #setAllowSnapshotPluginRepositories(boolean)} 085 */ 086 private boolean allowSnapshotPluginRepositories = false; 087 088 public final void setBanRepositories( boolean banRepositories ) 089 { 090 this.banRepositories = banRepositories; 091 } 092 093 public final void setBanPluginRepositories( boolean banPluginRepositories ) 094 { 095 this.banPluginRepositories = banPluginRepositories; 096 } 097 098 public final void setAllowedRepositories( List<String> allowedRepositories ) 099 { 100 this.allowedRepositories = allowedRepositories; 101 } 102 103 public final void setAllowedPluginRepositories( List<String> allowedPluginRepositories ) 104 { 105 this.allowedPluginRepositories = allowedPluginRepositories; 106 } 107 108 public final void setAllowSnapshotRepositories( boolean allowSnapshotRepositories ) 109 { 110 this.allowSnapshotRepositories = allowSnapshotRepositories; 111 } 112 113 public final void setAllowSnapshotPluginRepositories( boolean allowSnapshotPluginRepositories ) 114 { 115 this.allowSnapshotPluginRepositories = allowSnapshotPluginRepositories; 116 } 117 118 private Log logger; 119 120 @Override 121 public void execute( EnforcerRuleHelper helper ) 122 throws EnforcerRuleException 123 { 124 logger = helper.getLog(); 125 126 MavenSession session; 127 try 128 { 129 session = (MavenSession) helper.evaluate( "${session}" ); 130 131 List<MavenProject> sortedProjects = session.getProjectDependencyGraph().getSortedProjects(); 132 133 List<Model> models = new ArrayList<>(); 134 for ( MavenProject mavenProject : sortedProjects ) 135 { 136 logger.debug( "Scanning project: " + mavenProject.getGroupId() + ":" + mavenProject.getArtifactId() 137 + VERSION + mavenProject.getVersion() ); 138 models.add( mavenProject.getOriginalModel() ); 139 } 140 141 List<Model> badModels = new ArrayList<>(); 142 143 StringBuilder newMsg = new StringBuilder(); 144 newMsg.append( "Some poms have repositories defined:" + System.lineSeparator() ); 145 146 for ( Model model : models ) 147 { 148 if ( banRepositories ) 149 { 150 List<Repository> repos = model.getRepositories(); 151 if ( repos != null && !repos.isEmpty() ) 152 { 153 List<String> bannedRepos = 154 findBannedRepositories( repos, allowedRepositories, allowSnapshotRepositories ); 155 if ( !bannedRepos.isEmpty() ) 156 { 157 badModels.add( model ); 158 newMsg.append( 159 model.getGroupId() + ":" + model.getArtifactId() + VERSION + model.getVersion() 160 + " has repositories " + bannedRepos ); 161 } 162 } 163 } 164 if ( banPluginRepositories ) 165 { 166 List<Repository> repos = model.getPluginRepositories(); 167 if ( repos != null && !repos.isEmpty() ) 168 { 169 List<String> bannedRepos = 170 findBannedRepositories( repos, allowedPluginRepositories, allowSnapshotPluginRepositories ); 171 if ( !bannedRepos.isEmpty() ) 172 { 173 badModels.add( model ); 174 newMsg.append( 175 model.getGroupId() + ":" + model.getArtifactId() + VERSION + model.getVersion() 176 + " has plugin repositories " + bannedRepos ); 177 } 178 } 179 } 180 } 181 182 // if anything was found, log it then append the 183 // optional message. 184 if ( !badModels.isEmpty() ) 185 { 186 String message = getMessage(); 187 if ( StringUtils.isNotEmpty( message ) ) 188 { 189 newMsg.append( message ); 190 } 191 192 throw new EnforcerRuleException( newMsg.toString() ); 193 } 194 195 } 196 catch ( ExpressionEvaluationException e ) 197 { 198 throw new EnforcerRuleException( e.getLocalizedMessage() ); 199 } 200 } 201 202 /** 203 * 204 * @param repos all repositories, never {@code null} 205 * @param allowedRepos allowed repositories, never {@code null} 206 * @param allowSnapshots 207 * @return List of banned repositoreis. 208 */ 209 private static List<String> findBannedRepositories( List<Repository> repos, List<String> allowedRepos, 210 boolean allowSnapshots ) 211 { 212 List<String> bannedRepos = new ArrayList<>( allowedRepos.size() ); 213 for ( Repository r : repos ) 214 { 215 if ( !allowedRepos.contains( r.getId() ) ) 216 { 217 if ( !allowSnapshots || r.getReleases() == null || r.getReleases().isEnabled() ) 218 { 219 // if we are not allowing snapshots and this repo is enabled for releases 220 // it is banned. We don't care whether it is enabled for snapshots 221 // if you define a repo and don't enable it for anything, then we have nothing 222 // to worry about 223 bannedRepos.add( r.getId() ); 224 } 225 } 226 } 227 return bannedRepos; 228 } 229}