1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpackage org.antlr.mojo.antlr3;
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.List;
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.Set;
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.HashSet;
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.ArrayList;
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.Collections;
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.File;
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.IOException;
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.Writer;
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.FileWriter;
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.BufferedWriter;
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.net.URL;
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.net.MalformedURLException;
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.net.URLClassLoader;
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.plugin.AbstractMojo;
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.plugin.MojoExecutionException;
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.plugin.MojoFailureException;
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.project.MavenProject;
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.artifact.Artifact;
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.artifact.DependencyResolutionRequiredException;
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.artifact.versioning.ArtifactVersion;
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.artifact.versioning.DefaultArtifactVersion;
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.apache.maven.artifact.versioning.OverConstrainedVersionException;
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.util.StringUtils;
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.util.FileUtils;
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.codehaus.plexus.compiler.util.scan.InclusionScanException;
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.ANTLRFileStream;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.RecognitionException;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.gunit.GrammarInfo;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.gunit.gUnitExecutor;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.gunit.AbstractTest;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.gunit.Interp;
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/**
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Takes gUnit scripts and directly performs testing.
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @goal gunit
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @phase test
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @requiresDependencyResolution test
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @requiresProject true
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * @author Steve Ebersole
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpublic class GUnitExecuteMojo extends AbstractMojo {
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static final String ANTLR_GROUP_ID = "org.antlr";
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static final String ANTLR_ARTIFACT_NAME = "antlr";
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static final String ANTLR_RUNTIME_ARTIFACT_NAME = "antlr-runtime";
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * INTERNAL : The Maven Project to which we are attached
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @parameter expression="${project}"
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @required
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private MavenProject project;
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * INTERNAL : The artifacts associated to the dependencies defined as part
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * of our configuration within the project to which we are being attached.
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * @parameter expression="${plugin.artifacts}"
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @required
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @readonly
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private List<Artifact> pluginArtifacts;
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * Specifies the directory containing the gUnit testing files.
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @parameter expression="${basedir}/src/test/gunit"
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @required
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private File sourceDirectory;
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /**
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * A set of patterns for matching files from the sourceDirectory that
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * should be included as gUnit source files.
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @parameter
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private Set includes;
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /**
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * A set of exclude patterns.
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @parameter
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private Set excludes;
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * Specifies directory to which gUnit reports should get written.
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @parameter expression="${basedir}/target/gunit-report"
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @required
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private File reportDirectory;
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * Should gUnit functionality be completely by-passed?
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * <p/>
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * By default we skip gUnit tests if the user requested that all testing be skipped using 'maven.test.skip'
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * @parameter expression="${maven.test.skip}"
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private boolean skip;
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Set getIncludePatterns() {
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return includes == null || includes.isEmpty()
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				? Collections.singleton( "**/*.testsuite" )
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				: includes;
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Set getExcludePatterns() {
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return excludes == null
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				? Collections.emptySet()
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				: excludes;
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public final void execute() throws MojoExecutionException, MojoFailureException {
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( skip ) {
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			getLog().info( "Skipping gUnit processing" );
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Artifact pluginAntlrArtifact = determinePluginAntlrArtifact();
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		validateProjectsAntlrVersion( determineArtifactVersion( pluginAntlrArtifact ) );
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		performExecution( determineProjectCompileScopeClassLoader( pluginAntlrArtifact ) );
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private Artifact determinePluginAntlrArtifact() throws MojoExecutionException {
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for ( Artifact artifact : pluginArtifacts ) {
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			boolean match = ANTLR_GROUP_ID.equals( artifact.getGroupId() )
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					&& ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() );
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( match ) {
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return artifact;
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		throw new MojoExecutionException(
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				"Unexpected state : could not locate " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME +
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						" in plugin dependencies"
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		);
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private ArtifactVersion determineArtifactVersion(Artifact artifact) throws MojoExecutionException {
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return artifact.getVersion() != null
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					? new DefaultArtifactVersion( artifact.getVersion() )
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					: artifact.getSelectedVersion();
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch ( OverConstrainedVersionException e ) {
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "artifact [" + artifact.getId() + "] defined an overly constrained version range" );
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private void validateProjectsAntlrVersion(ArtifactVersion pluginAntlrVersion) throws MojoExecutionException {
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Artifact antlrArtifact = null;
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Artifact antlrRuntimeArtifact = null;
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( project.getCompileArtifacts() != null ) {
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			for ( Object o : project.getCompileArtifacts() ) {
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				final Artifact artifact = ( Artifact ) o;
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( ANTLR_GROUP_ID.equals( artifact.getGroupId() ) ) {
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					if ( ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						antlrArtifact = artifact;
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						break;
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					if ( ANTLR_RUNTIME_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						antlrRuntimeArtifact = artifact;
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		validateBuildTimeArtifact( antlrArtifact, pluginAntlrVersion );
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		validateRunTimeArtifact( antlrRuntimeArtifact, pluginAntlrVersion );
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@SuppressWarnings(value = "unchecked")
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void validateBuildTimeArtifact(Artifact antlrArtifact, ArtifactVersion pluginAntlrVersion)
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throws MojoExecutionException {
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( antlrArtifact == null ) {
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			validateMissingBuildtimeArtifact();
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// otherwise, lets make sure they match...
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrArtifact );
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			getLog().warn(
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			);
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void validateMissingBuildtimeArtifact() {
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// generally speaking, its ok for the project to not define a dep on the build-time artifact...
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@SuppressWarnings(value = "unchecked")
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void validateRunTimeArtifact(Artifact antlrRuntimeArtifact, ArtifactVersion pluginAntlrVersion)
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throws MojoExecutionException {
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( antlrRuntimeArtifact == null ) {
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// its possible, if the project instead depends on the build-time (or full) artifact.
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrRuntimeArtifact );
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			getLog().warn(
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_RUNTIME_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			);
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * Builds the classloader to pass to gUnit.
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * @param antlrArtifact The plugin's (our) Antlr dependency artifact.
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * @return The classloader for gUnit to use
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * @throws MojoExecutionException Problem resolving artifacts to {@link java.net.URL urls}.
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private ClassLoader determineProjectCompileScopeClassLoader(Artifact antlrArtifact)
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throws MojoExecutionException {
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ArrayList<URL> classPathUrls = new ArrayList<URL>();
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		getLog().info( "Adding Antlr artifact : " + antlrArtifact.getId() );
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		classPathUrls.add( resolveLocalURL( antlrArtifact ) );
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for ( String path : classpathElements() ) {
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			try {
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				getLog().info( "Adding project compile classpath element : " + path );
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				classPathUrls.add( new File( path ).toURI().toURL() );
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			catch ( MalformedURLException e ) {
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				throw new MojoExecutionException( "Unable to build path URL [" + path + "]" );
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return new URLClassLoader( classPathUrls.toArray( new URL[classPathUrls.size()] ), getClass().getClassLoader() );
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected static URL resolveLocalURL(Artifact artifact) throws MojoExecutionException {
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return artifact.getFile().toURI().toURL();
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch ( MalformedURLException e ) {
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "Unable to resolve artifact url : " + artifact.getId(), e );
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@SuppressWarnings( "unchecked" )
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private List<String> classpathElements() throws MojoExecutionException {
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// todo : should we combine both compile and test scoped elements?
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return ( List<String> ) project.getTestClasspathElements();
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch ( DependencyResolutionRequiredException e ) {
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "Call to Project#getCompileClasspathElements required dependency resolution" );
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private void performExecution(ClassLoader projectCompileScopeClassLoader) throws MojoExecutionException {
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		getLog().info( "gUnit report directory : " + reportDirectory.getAbsolutePath() );
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !reportDirectory.exists() ) {
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			boolean directoryCreated = reportDirectory.mkdirs();
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( !directoryCreated ) {
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				getLog().warn( "mkdirs() reported problem creating report directory" );
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Result runningResults = new Result();
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ArrayList<String> failureNames = new ArrayList<String>();
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println();
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println( "-----------------------------------------------------------" );
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println( " G U N I T   R E S U L T S" );
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println( "-----------------------------------------------------------" );
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for ( File script : collectIncludedSourceGrammars() ) {
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			final String scriptPath = script.getAbsolutePath();
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			System.out.println( "Executing script " + scriptPath );
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			try {
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				String scriptBaseName = StringUtils.chompLast( FileUtils.basename( script.getName() ), "." );
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ANTLRFileStream antlrStream = new ANTLRFileStream( scriptPath );
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				GrammarInfo grammarInfo = Interp.parse( antlrStream );
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				gUnitExecutor executor = new gUnitExecutor(
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						grammarInfo,
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						projectCompileScopeClassLoader,
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						script.getParentFile().getAbsolutePath()
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				);
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				String report = executor.execTest();
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				writeReportFile( new File( reportDirectory, scriptBaseName + ".txt" ), report );
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				Result testResult = new Result();
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				testResult.tests = executor.numOfTest;
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				testResult.failures = executor.numOfFailure;
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				testResult.invalids = executor.numOfInvalidInput;
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				System.out.println( testResult.render() );
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				runningResults.add( testResult );
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				for ( AbstractTest test : executor.failures ) {
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					failureNames.add( scriptBaseName + "#" + test.getHeader() );
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			catch ( IOException e ) {
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				throw new MojoExecutionException( "Could not open specified script file", e );
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			catch ( RecognitionException e ) {
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				throw new MojoExecutionException( "Could not parse gUnit script", e );
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println();
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println( "Summary :" );
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( ! failureNames.isEmpty() ) {
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			System.out.println( "  Found " + failureNames.size() + " failures" );
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			for ( String name : failureNames ) {
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				System.out.println( "    - " + name );
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println( runningResults.render() );
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println();
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( runningResults.failures > 0 ) {
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "Found gUnit test failures" );
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( runningResults.invalids > 0 ) {
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "Found invalid gUnit tests" );
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private Set<File> collectIncludedSourceGrammars() throws MojoExecutionException {
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		SourceMapping mapping = new SuffixMapping( "g", Collections.EMPTY_SET );
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        SourceInclusionScanner scan = new SimpleSourceInclusionScanner( getIncludePatterns(), getExcludePatterns() );
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        scan.addSourceMapping( mapping );
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Set scanResults = scan.getIncludedSources( sourceDirectory, null );
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Set<File> results = new HashSet<File>();
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			for ( Object result : scanResults ) {
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( result instanceof File ) {
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					results.add( ( File ) result );
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				else if ( result instanceof String ) {
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					results.add( new File( ( String ) result ) );
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				else {
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					throw new MojoExecutionException( "Unexpected result type from scanning [" + result.getClass().getName() + "]" );
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return results;
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch ( InclusionScanException e ) {
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new MojoExecutionException( "Error determining gUnit sources", e );
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private void writeReportFile(File reportFile, String results) {
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Writer writer = new FileWriter( reportFile );
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			writer = new BufferedWriter( writer );
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			try {
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				writer.write( results );
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				writer.flush();
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			finally {
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				try {
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					writer.close();
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				catch ( IOException ignore ) {
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch ( IOException e ) {
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			getLog().warn(  "Error writing gUnit report file", e );
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private static class Result {
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		private int tests = 0;
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		private int failures = 0;
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		private int invalids = 0;
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		public String render() {
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return String.format( "Tests run: %d,  Failures: %d,  Invalid: %d", tests, failures, invalids );
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		public void add(Result result) {
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			this.tests += result.tests;
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			this.failures += result.failures;
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			this.invalids += result.invalids;
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
411