View Javadoc

1   package org.codehaus.mojo.exec;
2   
3   import java.io.File;
4   import java.io.FileOutputStream;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.io.OutputStream;
8   import java.util.ArrayList;
9   import java.util.List;
10  
11  import org.apache.commons.io.IOUtils;
12  import org.apache.maven.plugin.MojoExecutionException;
13  import org.apache.tools.ant.DirectoryScanner;
14  import org.codehaus.plexus.util.StringUtils;
15  import org.springframework.core.io.DefaultResourceLoader;
16  import org.springframework.core.io.Resource;
17  import org.springframework.core.io.ResourceLoader;
18  import static org.codehaus.plexus.util.StringUtils.isEmpty;
19  
20  /**
21   * A plugin for executing the Eclipse java source code formatter
22   * 
23   * @author Jeff Caddel
24   * @goal format
25   * @aggregator
26   */
27  public class EclipseFormatterMojo extends ExecMojo {
28  	private static final String FS = System.getProperty("file.separator");
29  
30  	/**
31  	 * Binaries representing a Java VM. Default values are "javaw.exe", "java.exe", and "java". This list is searched in
32  	 * order, stopping as soon as one is found.
33  	 * 
34  	 * @parameter
35  	 */
36  	private String[] javaBinaries = new String[] { "javaw.exe", "java.exe", "java" };
37  
38  	/**
39  	 * Full path to the Eclipse executable binary
40  	 * 
41  	 * @parameter expression="${eclipse.binary}"
42  	 * @required
43  	 */
44  	private String eclipseBinary;
45  
46  	/**
47  	 * Full path to a Java VM. This gets filled in using the system property "java.home" unless a value is supplied
48  	 * here.
49  	 * 
50  	 * @parameter expression="${eclipse.vm}"
51  	 */
52  	private String vm;
53  
54  	/**
55  	 * This is the name of the Eclipse application that performs the formatting
56  	 * 
57  	 * @parameter expression="${eclipse.application}" default-value="org.eclipse.jdt.core.JavaCodeFormatter"
58  	 * @required
59  	 */
60  	private String application;
61  
62  	/**
63  	 * Pointer to an Eclipse "org.eclipse.jdt.core.prefs" file. Supports "classpath:" style notation
64  	 * 
65  	 * @parameter expression="${eclipse.formatterPreferences}" default-value="classpath:eclipse.prefs"
66  	 * @required
67  	 */
68  	private String formatterPreferences;
69  
70  	/**
71  	 * Any arguments specified here are passed to the Eclipse binary as additional command line arguments. Default
72  	 * values are "-nosplash -verbose"
73  	 * 
74  	 * @parameter
75  	 */
76  	private String[] eclipseArgs = new String[] { "-nosplash", "-verbose" };
77  
78  	/**
79  	 * Regular expressions for directories that contain Java source code to format. Default value is
80  	 * **/src/main/java. The Eclipse formatter will recursively inspect any directories matching these
81  	 * patterns for *.java files
82  	 * 
83  	 * @parameter
84  	 */
85  	private String[] includes = new String[] { "**/src/main/java" };
86  
87  	/**
88  	 * Regular expressions for directories to exclude from the process that scans for *.java files
89  	 * 
90  	 * @parameter
91  	 */
92  	private String[] excludes = new String[] { "**/.settings", "**/.svn" };
93  
94  	protected List<File> getSourceDirectories() {
95  		DirectoryScanner scanner = new DirectoryScanner();
96  		scanner.setBasedir(project.getBasedir());
97  		scanner.setIncludes(includes);
98  		scanner.setExcludes(excludes);
99  		scanner.scan();
100 		String[] includedDirs = scanner.getIncludedDirectories();
101 		List<File> dirs = new ArrayList<File>();
102 		for (String includedDir : includedDirs) {
103 			File file = new File(project.getBasedir().getAbsolutePath() + FS + includedDir);
104 			dirs.add(file);
105 		}
106 		return dirs;
107 	}
108 
109 	protected void showDirs(List<File> srcDirs) {
110 		getLog().info("Located " + srcDirs.size() + " source directories:");
111 		for (File dir : srcDirs) {
112 			getLog().info(dir.getAbsolutePath());
113 		}
114 	}
115 
116 	protected void showConfig(File eclipseBinary, File javaBinary) {
117 		getLog().info("Eclipse Location: " + eclipseBinary.getAbsolutePath());
118 		getLog().info("Java VM: " + javaBinary.getAbsolutePath());
119 		getLog().info("Scanning directory: " + project.getBasedir());
120 		StringBuilder sb = new StringBuilder();
121 		for (String include : includes) {
122 			sb.append(include + " ");
123 		}
124 		getLog().info("Includes: " + sb.toString());
125 		sb = new StringBuilder();
126 		for (String exclude : excludes) {
127 			sb.append(exclude + " ");
128 		}
129 		getLog().info("Excludes: " + sb.toString());
130 	}
131 
132 	@Override
133 	public void execute() throws MojoExecutionException {
134 		if (!fileExists(eclipseBinary)) {
135 			throw new MojoExecutionException(eclipseBinary + " does not exist");
136 		}
137 		File eclipseBinaryFile = new File(eclipseBinary);
138 		File javaBinary = getJavaBinary();
139 		showConfig(eclipseBinaryFile, javaBinary);
140 
141 		List<File> dirs = getSourceDirectories();
142 		if (dirs.size() == 0) {
143 			getLog().info("No directories containing source code were located");
144 			return;
145 		}
146 		showDirs(dirs);
147 
148 		super.setExecutable(eclipseBinaryFile.getAbsolutePath());
149 		super.setArguments(getEclipseArguments(javaBinary, dirs));
150 
151 		super.execute();
152 	}
153 
154 	protected boolean fileExists(String filename) {
155 		return new File(filename).exists();
156 	}
157 
158 	protected File getJavaBinary() throws MojoExecutionException {
159 		// They provided us with a VM, and we found a file in the location they specified
160 		if (!isEmpty(vm) && fileExists(vm)) {
161 			return new File(vm);
162 		}
163 
164 		// They asked us to use a specific VM, but it doesn't exist
165 		if (!isEmpty(vm) && !fileExists(vm)) {
166 			throw new MojoExecutionException(vm + " does not exist");
167 		}
168 
169 		// They did not specify a VM, attempt to locate one
170 		String javaHome = System.getProperty("java.home");
171 		String binaryHome = javaHome + FS + "bin";
172 		for (String binary : javaBinaries) {
173 			File file = new File(binaryHome + FS + binary);
174 			if (file.exists()) {
175 				return file;
176 			}
177 		}
178 		throw new MojoExecutionException(
179 				"No Java VM location was supplied, and we could not locate one using the System property 'java.home'");
180 	}
181 
182 	protected List<String> getEclipseArguments(File javaBinary, List<File> dirs) throws MojoExecutionException {
183 		List<String> args = new ArrayList<String>();
184 		args.add("-application");
185 		args.add(application);
186 		args.add("-vm");
187 		args.add(javaBinary.getAbsolutePath());
188 		args.add("-config");
189 		args.add(getConfigAbsolutePath());
190 		for (String arg : eclipseArgs) {
191 			addIfNotEmpty(args, arg);
192 		}
193 		for (File dir : dirs) {
194 			args.add(dir.getAbsolutePath());
195 		}
196 		return args;
197 	}
198 
199 	protected String getConfigAbsolutePath() throws MojoExecutionException {
200 		File file = new File(formatterPreferences);
201 		if (file.exists()) {
202 			return file.getAbsolutePath();
203 		}
204 		ResourceLoader loader = new DefaultResourceLoader();
205 		Resource resource = loader.getResource(formatterPreferences);
206 		if (!resource.exists()) {
207 			throw new MojoExecutionException("Unable to locate " + formatterPreferences);
208 		}
209 		OutputStream out = null;
210 		InputStream in = null;
211 		try {
212 			File temp = File.createTempFile("eclipse.prefs.", null);
213 			temp.deleteOnExit();
214 			out = new FileOutputStream(temp);
215 			in = resource.getInputStream();
216 			IOUtils.copy(in, out);
217 			return temp.getAbsolutePath();
218 		} catch (IOException e) {
219 			throw new MojoExecutionException("Error copying resource " + formatterPreferences, e);
220 		} finally {
221 			IOUtils.closeQuietly(out);
222 			IOUtils.closeQuietly(in);
223 		}
224 
225 	}
226 
227 	protected void addIfNotEmpty(List<String> list, String s) {
228 		if (StringUtils.isEmpty(s)) {
229 			return;
230 		}
231 		list.add(s);
232 	}
233 
234 	public String getEclipseBinary() {
235 		return eclipseBinary;
236 	}
237 
238 	public void setEclipseBinary(String eclipseExecutable) {
239 		this.eclipseBinary = eclipseExecutable;
240 	}
241 
242 	public String getVm() {
243 		return vm;
244 	}
245 
246 	public void setVm(String vm) {
247 		this.vm = vm;
248 	}
249 
250 	public String getApplication() {
251 		return application;
252 	}
253 
254 	public void setApplication(String application) {
255 		this.application = application;
256 	}
257 
258 	public String[] getIncludes() {
259 		return includes;
260 	}
261 
262 	public void setIncludes(String[] includes) {
263 		this.includes = includes;
264 	}
265 
266 	public String[] getExcludes() {
267 		return excludes;
268 	}
269 
270 	public void setExcludes(String[] excludes) {
271 		this.excludes = excludes;
272 	}
273 
274 	public String[] getJavaBinaries() {
275 		return javaBinaries;
276 	}
277 
278 	public void setJavaBinaries(String[] binaries) {
279 		this.javaBinaries = binaries;
280 	}
281 
282 	public String getFormatterPreferences() {
283 		return formatterPreferences;
284 	}
285 
286 	public void setFormatterPreferences(String formatterPreferences) {
287 		this.formatterPreferences = formatterPreferences;
288 	}
289 
290 	public String[] getEclipseArgs() {
291 		return eclipseArgs;
292 	}
293 
294 	public void setEclipseArgs(String[] args) {
295 		this.eclipseArgs = args;
296 	}
297 
298 }