1 package org.apache.maven.plugin.pmd;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.MojoExecutionException;
23 import org.apache.maven.plugin.MojoFailureException;
24 import org.apache.maven.plugin.pmd.model.PmdErrorDetail;
25 import org.apache.maven.plugin.pmd.model.PmdFile;
26 import org.apache.maven.plugin.pmd.model.Violation;
27 import org.apache.maven.plugin.pmd.model.io.xpp3.PmdXpp3Reader;
28 import org.apache.maven.plugins.annotations.Execute;
29 import org.apache.maven.plugins.annotations.LifecyclePhase;
30 import org.apache.maven.plugins.annotations.Mojo;
31 import org.apache.maven.plugins.annotations.Parameter;
32 import org.codehaus.plexus.util.IOUtil;
33 import org.codehaus.plexus.util.StringUtils;
34 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
35
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.FileReader;
39 import java.io.IOException;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Map.Entry;
46 import java.util.Properties;
47 import java.util.Set;
48
49
50
51
52
53
54
55 @Mojo( name = "check", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true )
56 @Execute( goal = "pmd" )
57 public class PmdViolationCheckMojo
58 extends AbstractPmdViolationCheckMojo<Violation>
59 {
60
61
62
63
64
65
66 @Parameter( property = "pmd.failurePriority", defaultValue = "5", required = true )
67 private int failurePriority;
68
69
70
71
72
73 @Parameter( property = "pmd.skip", defaultValue = "false" )
74 private boolean skip;
75
76 private final Map<String, Set<String>> excludeFromFailureClasses = new HashMap<String, Set<String>>();
77
78
79
80
81 public void execute()
82 throws MojoExecutionException, MojoFailureException
83 {
84 if ( !skip )
85 {
86 executeCheck( "pmd.xml", "violation", "PMD violation", failurePriority );
87 }
88 }
89
90 @Override
91 protected void loadExcludeFromFailuresData( final String excludeFromFailureFile )
92 throws MojoExecutionException
93 {
94 File file = new File( excludeFromFailureFile );
95 if ( !file.exists() )
96 {
97 return;
98 }
99 final Properties props = new Properties();
100 FileInputStream fileInputStream = null;
101 try
102 {
103 fileInputStream = new FileInputStream( new File( excludeFromFailureFile ) );
104 props.load( fileInputStream );
105 }
106 catch ( final IOException e )
107 {
108 throw new MojoExecutionException( "Cannot load properties file " + excludeFromFailureFile, e );
109 }
110 finally
111 {
112 IOUtil.close( fileInputStream );
113 }
114 for ( final Entry<Object, Object> propEntry : props.entrySet() )
115 {
116 final Set<String> excludedRuleSet = new HashSet<String>();
117 final String className = propEntry.getKey().toString();
118 final String[] excludedRules = propEntry.getValue().toString().split( "," );
119 for ( final String excludedRule : excludedRules )
120 {
121 excludedRuleSet.add( excludedRule.trim() );
122 }
123 excludeFromFailureClasses.put( className, excludedRuleSet );
124 }
125 }
126
127 @Override
128 protected boolean isExcludedFromFailure( final Violation errorDetail )
129 {
130 final String className = extractClassName( errorDetail );
131 final Set<String> excludedRuleSet = excludeFromFailureClasses.get( className );
132 return excludedRuleSet != null && excludedRuleSet.contains( errorDetail.getRule() );
133 }
134
135 private String extractClassName( final Violation errorDetail )
136 {
137
138 if ( errorDetail.getViolationPackage() != null && errorDetail.getViolationClass() != null )
139 {
140 return errorDetail.getViolationPackage() + "." + errorDetail.getViolationClass();
141 }
142 else
143 {
144 final String fileName = errorDetail.getFileName();
145 final int javaIdx = fileName.indexOf( "\\java\\" );
146 return fileName.substring( javaIdx >= 0 ? javaIdx + 6 : 0, fileName.length() - 5 ).replace( '\\', '.' );
147 }
148 }
149
150
151
152
153 protected void printError( Violation item, String severity )
154 {
155
156 StringBuilder buff = new StringBuilder( 100 );
157 buff.append( "PMD " + severity + ": " );
158 if ( item.getViolationClass() != null )
159 {
160 if ( item.getViolationPackage() != null )
161 {
162 buff.append( item.getViolationPackage() );
163 buff.append( "." );
164 }
165 buff.append( item.getViolationClass() );
166 }
167 else
168 {
169 buff.append( item.getFileName() );
170 }
171 buff.append( ":" );
172 buff.append( item.getBeginline() );
173 buff.append( " Rule:" ).append( item.getRule() );
174 buff.append( " Priority:" ).append( item.getPriority() );
175 buff.append( " " ).append( item.getText() ).append( "." );
176
177 this.getLog().info( buff.toString() );
178 }
179
180 @Override
181 protected List<Violation> getErrorDetails( File pmdFile )
182 throws XmlPullParserException, IOException
183 {
184 PmdXpp3Reader reader = new PmdXpp3Reader();
185 PmdErrorDetail details = reader.read( new FileReader( pmdFile ), false );
186
187 List<Violation> violations = new ArrayList<Violation>();
188 for ( PmdFile file : details.getFiles() )
189 {
190 String fullPath = file.getName();
191
192 for ( Violation violation : file.getViolations() )
193 {
194 violation.setFileName( getFilename( fullPath, violation.getViolationPackage() ) );
195 violations.add( violation );
196 }
197 }
198 return violations;
199 }
200
201 @Override
202 protected int getPriority( Violation errorDetail )
203 {
204 return errorDetail.getPriority();
205 }
206
207 @Override
208 protected ViolationDetails<Violation> newViolationDetailsInstance()
209 {
210 return new ViolationDetails<Violation>();
211 }
212
213 private String getFilename( String fullpath, String pkg )
214 {
215 int index = fullpath.lastIndexOf( File.separatorChar );
216
217 while ( StringUtils.isNotEmpty( pkg ) )
218 {
219 index = fullpath.substring( 0, index ).lastIndexOf( File.separatorChar );
220
221 int dot = pkg.indexOf( '.' );
222
223 if ( dot < 0 )
224 {
225 break;
226 }
227 pkg = pkg.substring( dot + 1 );
228 }
229
230 return fullpath.substring( index + 1 );
231 }
232 }