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.maven.artifact.Artifact; 027import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 028import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 029import org.apache.maven.artifact.versioning.VersionRange; 030import org.apache.maven.enforcer.rule.api.EnforcerRuleException; 031import org.apache.maven.plugin.logging.Log; 032import org.codehaus.plexus.util.StringUtils; 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: BannedDependencies.java 1496229 2013-06-24 21:43:56Z rfscholte $ 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 <code>groupId[:artifactId][:version]</code>. 046 * Any of the sections can be a wildcard by using '*' (ie group:*:1.0) <br> 047 * The rule will fail if any dependency matches any exclude, unless it also matches an include rule. 048 * 049 * @deprecated the visibility will be reduced to private with the next major version 050 * @see {@link #setExcludes(List)} 051 * @see {@link #getExcludes()} 052 */ 053 public List<String> excludes = null; 054 055 /** 056 * Specify the allowed dependencies. This can be a list of artifacts in the format <code>groupId[:artifactId][:version]</code>. 057 * Any of the sections can be a wildcard by using '*' (ie group:*:1.0) <br> 058 * Includes override the exclude rules. It is meant to allow wide exclusion rules with wildcards and still allow a 059 * smaller set of includes. <br> 060 * For example, to ban all xerces except xerces-api -> exclude "xerces", include "xerces:xerces-api" 061 * 062 * @deprecated the visibility will be reduced to private with the next major version 063 * @see {@link #setIncludes(List)} 064 * @see {@link #getIncludes()} 065 */ 066 public List<String> includes = null; 067 068 069 /** 070 * {@inheritDoc} 071 */ 072 protected Set<Artifact> checkDependencies( Set<Artifact> theDependencies, Log log ) 073 throws EnforcerRuleException 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 if ( included != null ) 083 { 084 excluded.removeAll( included ); 085 } 086 } 087 return excluded; 088 089 } 090 091 /** 092 * Checks the set of dependencies against the list of patterns. 093 * 094 * @param thePatterns the patterns 095 * @param dependencies the dependencies 096 * @return a set containing artifacts matching one of the patterns or <code>null</code> 097 * @throws EnforcerRuleException the enforcer rule exception 098 */ 099 private Set<Artifact> checkDependencies( Set<Artifact> dependencies, List<String> thePatterns ) 100 throws EnforcerRuleException 101 { 102 Set<Artifact> foundMatches = null; 103 104 if ( thePatterns != null && thePatterns.size() > 0 ) 105 { 106 107 for ( String pattern : thePatterns ) 108 { 109 110 String[] subStrings = pattern.split( ":" ); 111 subStrings = StringUtils.stripAll( subStrings ); 112 113 for ( Artifact artifact : dependencies ) 114 { 115 if ( compareDependency( subStrings, artifact ) ) 116 { 117 // only create if needed 118 if ( foundMatches == null ) 119 { 120 foundMatches = new HashSet<Artifact>(); 121 } 122 foundMatches.add( artifact ); 123 } 124 } 125 } 126 } 127 return foundMatches; 128 } 129 130 /** 131 * Compares the parsed array of substrings against the artifact. 132 * The pattern should follow the format "groupId:artifactId:version:type:scope" 133 * 134 * @param pattern the array of patterns 135 * @param artifact the artifact 136 * @return <code>true</code> if the artifact matches one of the patterns 137 * @throws EnforcerRuleException the enforcer rule exception 138 */ 139 protected boolean compareDependency( String[] pattern, Artifact artifact ) 140 throws EnforcerRuleException 141 { 142 143 boolean result = false; 144 if ( pattern.length > 0 ) 145 { 146 result = pattern[0].equals( "*" ) || artifact.getGroupId().equals( pattern[0] ); 147 } 148 149 if ( result && pattern.length > 1 ) 150 { 151 result = pattern[1].equals( "*" ) || artifact.getArtifactId().equals( pattern[1] ); 152 } 153 154 if ( result && pattern.length > 2 ) 155 { 156 // short circuit if the versions are exactly the same 157 if ( pattern[2].equals( "*" ) || artifact.getVersion().equals( pattern[2] ) ) 158 { 159 result = true; 160 } 161 else 162 { 163 try 164 { 165 result = 166 AbstractVersionEnforcer.containsVersion( VersionRange.createFromVersionSpec( pattern[2] ), 167 new DefaultArtifactVersion( artifact.getBaseVersion() ) ); 168 } 169 catch ( InvalidVersionSpecificationException e ) 170 { 171 throw new EnforcerRuleException( "Invalid Version Range: ", e ); 172 } 173 } 174 } 175 176 if ( result && pattern.length > 3 ) 177 { 178 String type = artifact.getType(); 179 if ( type == null || type.equals( "" ) ) 180 { 181 type = "jar"; 182 } 183 result = pattern[3].equals( "*" ) || type.equals( pattern[3] ); 184 } 185 186 if ( result && pattern.length > 4 ) 187 { 188 String scope = artifact.getScope(); 189 if ( scope == null || scope.equals( "" ) ) 190 { 191 scope = "compile"; 192 } 193 result = pattern[4].equals( "*" ) || scope.equals( pattern[4] ); 194 } 195 196 return result; 197 } 198 199 /** 200 * Gets the excludes. 201 * 202 * @return the excludes 203 */ 204 public List<String> getExcludes() 205 { 206 return this.excludes; 207 } 208 209 /** 210 * Sets the excludes. 211 * 212 * @param theExcludes the excludes to set 213 */ 214 public void setExcludes( List<String> theExcludes ) 215 { 216 this.excludes = theExcludes; 217 } 218 219 /** 220 * Gets the includes. 221 * 222 * @return the includes 223 */ 224 public List<String> getIncludes() 225 { 226 return this.includes; 227 } 228 229 /** 230 * Sets the includes. 231 * 232 * @param theIncludes the includes to set 233 */ 234 public void setIncludes( List<String> theIncludes ) 235 { 236 this.includes = theIncludes; 237 } 238 239}