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