View Javadoc

1   /*
2    * Jour - bytecode instrumentation library
3    *
4    * Copyright (C) 2007-2008 Vlad Skarzhevskyy
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Library General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public
17   * License along with this library; if not, write to the
18   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   * Boston, MA  02111-1307, USA.
20   */
21  package net.sf.jour.maven;
22  
23  import java.io.File;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import net.sf.jour.signature.APICompare;
28  import net.sf.jour.signature.APICompareConfig;
29  import net.sf.jour.signature.APIFilter;
30  import net.sf.jour.signature.ChangeDetectedException;
31  
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.plugin.AbstractMojo;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.MojoFailureException;
36  import org.apache.maven.plugin.logging.Log;
37  import org.apache.maven.project.MavenProject;
38  
39  import com.pyx4j.log4j.MavenLogAppender;
40  
41  /**
42   * The jour:signatureVerify will compare API descriptor and API classes.
43   * 
44   * @author vlads
45   * 
46   * @goal signatureVerify
47   * 
48   * @phase test
49   * 
50   * @requiresDependencyResolution compile
51   * 
52   * @description Verification of compatibility between Java APIs
53   */
54  public class SignatureVerifyMojo extends AbstractMojo {
55  
56  	/**
57  	 * The API descriptor XML.
58  	 * 
59  	 * @parameter
60  	 * @required
61  	 */
62  	private File signature;
63  
64  	/**
65  	 * The directory or jar containing API classes.
66  	 * 
67  	 * @parameter expression="${project.build.outputDirectory}"
68  	 * @required
69  	 */
70  	private File classes;
71  
72  	/**
73  	 * Appends the system search path to the end of the search path. The system
74  	 * search path usually includes the platform library, extension libraries,
75  	 * and the search path specified by the <code>-classpath</code> option or
76  	 * the <code>CLASSPATH</code> environment variable.
77  	 * 
78  	 * @parameter expression="true"
79  	 */
80  	private boolean useSystemClassPath;
81  
82  	/**
83  	 * Generate error if new API member with access level public or protected
84  	 * has been added to class.
85  	 * 
86  	 * @parameter expression="true"
87  	 */
88  	private boolean allowAPIextension;
89  
90  	/**
91  	 * Generate error if new API member throw less exception than declared in
92  	 * API
93  	 * 
94  	 * @parameter expression="true"
95  	 */
96  	private boolean allowThrowsLess;
97  
98  	/**
99  	 * Compare API level public|[protected]|package|private
100 	 * 
101 	 * @parameter expression="protected"
102 	 */
103 	private String level;
104 
105 	/**
106 	 * Compare Only selected packages
107 	 * 
108 	 * @parameter
109 	 */
110 	private String packages;
111 
112 	/**
113 	 * The Maven project reference where the plugin is currently being executed.
114 	 * Used for dependency resolution during compilation. The default value is
115 	 * populated from maven.
116 	 * 
117 	 * @parameter expression="${project}"
118 	 * @readonly
119 	 * @required
120 	 */
121 	protected MavenProject mavenProject;
122 
123 	public void execute() throws MojoExecutionException, MojoFailureException {
124 		Log log = getLog();
125 		MavenLogAppender.startPluginLog(this);
126 		log.info("use signature: " + signature);
127 
128 		APICompareConfig config = new APICompareConfig();
129 
130 		config.allowAPIextension = allowAPIextension;
131 		config.allowThrowsLess = allowThrowsLess;
132 
133 		config.packages = packages;
134 		config.apiLevel = APIFilter.getAPILevel(level);
135 
136 		StringBuffer supportingJars = new StringBuffer();
137 
138 		List dependancy = this.mavenProject.getTestArtifacts();
139 		for (Iterator i = dependancy.iterator(); i.hasNext();) {
140 			Artifact artifact = (Artifact) i.next();
141 			File file = InstrumentationMojo.getClasspathElement(artifact, mavenProject);
142 			log.debug("dependancy:" + file.toString());
143 			if (supportingJars.length() < 0) {
144 				supportingJars.append(File.pathSeparatorChar);
145 			}
146 			supportingJars.append(file.toString());
147 		}
148 
149 		try {
150 			APICompare.compare(classes.getAbsolutePath(), signature.getAbsolutePath(), config, useSystemClassPath,
151 					(supportingJars.length() > 0) ? supportingJars.toString() : null);
152 		} catch (ChangeDetectedException e) {
153 			log.error("API compare FAILED, processed " + APICompare.getClassesCount() + " classes");
154 			log.error(e.getMessage());
155 			throw new MojoExecutionException("API compare FAILED", e);
156 		}
157 		log.info("API compare PASSED in " + APICompare.getClassesCount() + " classes");
158 	}
159 
160 }