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.HashSet; 023import java.util.List; 024import java.util.Set; 025 026import org.apache.commons.lang3.StringUtils; 027import org.apache.maven.artifact.Artifact; 028import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 029import org.apache.maven.enforcer.rule.api.EnforcerRuleException; 030import org.apache.maven.plugin.logging.Log; 031import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher; 032import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher.Pattern; 033 034/** 035 * This rule checks that lists of dependencies are not included. 036 * 037 * @author <a href="mailto:brianf@apache.org">Brian Fox</a> 038 * @version $Id$ 039 */ 040public class BannedDependencies 041 extends AbstractBanDependencies 042{ 043 044 /** 045 * Specify the banned dependencies. This can be a list of artifacts in the format 046 * <code>groupId[:artifactId][:version]</code>. Any of the sections can be a wildcard 047 * by using '*' (ie group:*:1.0) <br> 048 * The rule will fail if any dependency matches any exclude, unless it also matches 049 * an include rule. 050 * 051 * @see {@link #setExcludes(List)} 052 * @see {@link #getExcludes()} 053 */ 054 private List<String> excludes = null; 055 056 /** 057 * Specify the allowed dependencies. This can be a list of artifacts in the format 058 * <code>groupId[:artifactId][:version]</code>. Any of the sections can be a wildcard 059 * by using '*' (ie group:*:1.0) <br> 060 * Includes override the exclude rules. It is meant to allow wide exclusion rules 061 * with wildcards and still allow a 062 * smaller set of includes. <br> 063 * For example, to ban all xerces except xerces-api -> exclude "xerces", include "xerces:xerces-api" 064 * 065 * @see {@link #setIncludes(List)} 066 * @see {@link #getIncludes()} 067 */ 068 private List<String> includes = null; 069 070 @Override 071 protected Set<Artifact> checkDependencies( Set<Artifact> theDependencies, Log log ) 072 throws EnforcerRuleException 073 { 074 075 Set<Artifact> excluded = checkDependencies( theDependencies, excludes ); 076 077 // anything specifically included should be removed 078 // from the ban list. 079 if ( excluded != null ) 080 { 081 Set<Artifact> included = checkDependencies( theDependencies, includes ); 082 083 if ( included != null ) 084 { 085 excluded.removeAll( included ); 086 } 087 } 088 return excluded; 089 090 } 091 092 /** 093 * Checks the set of dependencies against the list of patterns. 094 * 095 * @param thePatterns the patterns 096 * @param dependencies the dependencies 097 * @return a set containing artifacts matching one of the patterns or <code>null</code> 098 * @throws EnforcerRuleException the enforcer rule exception 099 */ 100 private Set<Artifact> checkDependencies( Set<Artifact> dependencies, List<String> thePatterns ) 101 throws EnforcerRuleException 102 { 103 Set<Artifact> foundMatches = null; 104 105 if ( thePatterns != null && thePatterns.size() > 0 ) 106 { 107 108 for ( String pattern : thePatterns ) 109 { 110 String[] subStrings = pattern.split( ":" ); 111 subStrings = StringUtils.stripAll( subStrings ); 112 String resultPattern = StringUtils.join( subStrings, ":" ); 113 114 for ( Artifact artifact : dependencies ) 115 { 116 if ( compareDependency( resultPattern, artifact ) ) 117 { 118 // only create if needed 119 if ( foundMatches == null ) 120 { 121 foundMatches = new HashSet<Artifact>(); 122 } 123 foundMatches.add( artifact ); 124 } 125 } 126 } 127 } 128 return foundMatches; 129 } 130 131 /** 132 * Compares the given pattern against the given artifact. The pattern should follow the format 133 * <code>groupId:artifactId:version:type:scope:classifier</code>. 134 * 135 * @param pattern The pattern to compare the artifact with. 136 * @param artifact the artifact 137 * @return <code>true</code> if the artifact matches one of the patterns 138 * @throws EnforcerRuleException the enforcer rule exception 139 */ 140 protected boolean compareDependency( String pattern, Artifact artifact ) 141 throws EnforcerRuleException 142 { 143 144 ArtifactMatcher.Pattern am = new Pattern( pattern ); 145 boolean result; 146 try 147 { 148 result = am.match( artifact ); 149 } 150 catch ( InvalidVersionSpecificationException e ) 151 { 152 throw new EnforcerRuleException( "Invalid Version Range: ", e ); 153 } 154 155 return result; 156 } 157 158 /** 159 * Gets the excludes. 160 * 161 * @return the excludes 162 */ 163 public List<String> getExcludes() 164 { 165 return this.excludes; 166 } 167 168 /** 169 * Specify the banned dependencies. This can be a list of artifacts in the format 170 * <code>groupId[:artifactId][:version]</code>. Any of the sections can be a wildcard 171 * by using '*' (ie group:*:1.0) <br> 172 * The rule will fail if any dependency matches any exclude, unless it also matches an 173 * include rule. 174 * 175 * @see #getExcludes() 176 * @param theExcludes the excludes to set 177 */ 178 public void setExcludes( List<String> theExcludes ) 179 { 180 this.excludes = theExcludes; 181 } 182 183 /** 184 * Gets the includes. 185 * 186 * @return the includes 187 */ 188 public List<String> getIncludes() 189 { 190 return this.includes; 191 } 192 193 /** 194 * Specify the allowed dependencies. This can be a list of artifacts in the format 195 * <code>groupId[:artifactId][:version]</code>. Any of the sections can be a wildcard 196 * by using '*' (ie group:*:1.0) <br> 197 * Includes override the exclude rules. It is meant to allow wide exclusion rules with 198 * wildcards and still allow a 199 * smaller set of includes. <br> 200 * For example, to ban all xerces except xerces-api → exclude "xerces", 201 * include "xerces:xerces-api" 202 * 203 * @see #setIncludes(List) 204 * @param theIncludes the includes to set 205 */ 206 public void setIncludes( List<String> theIncludes ) 207 { 208 this.includes = theIncludes; 209 } 210 211}