001 package org.codehaus.mojo.exec; 002 003 import java.io.File; 004 import java.io.FileOutputStream; 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.io.OutputStream; 008 import java.util.ArrayList; 009 import java.util.List; 010 011 import org.apache.commons.io.IOUtils; 012 import org.apache.maven.plugin.MojoExecutionException; 013 import org.apache.tools.ant.DirectoryScanner; 014 import org.codehaus.plexus.util.StringUtils; 015 import org.springframework.core.io.DefaultResourceLoader; 016 import org.springframework.core.io.Resource; 017 import org.springframework.core.io.ResourceLoader; 018 import static org.codehaus.plexus.util.StringUtils.isEmpty; 019 020 /** 021 * A plugin for executing the Eclipse java source code formatter 022 * 023 * @author Jeff Caddel 024 * @goal format 025 * @aggregator 026 */ 027 public class EclipseFormatterMojo extends ExecMojo { 028 private static final String FS = System.getProperty("file.separator"); 029 030 /** 031 * Binaries representing a Java VM. Default values are "javaw.exe", "java.exe", and "java". This list is searched in 032 * order, stopping as soon as one is found. 033 * 034 * @parameter 035 */ 036 private String[] javaBinaries = new String[] { "javaw.exe", "java.exe", "java" }; 037 038 /** 039 * Full path to the Eclipse executable binary 040 * 041 * @parameter expression="${eclipse.binary}" 042 * @required 043 */ 044 private String eclipseBinary; 045 046 /** 047 * Full path to a Java VM. This gets filled in using the system property "java.home" unless a value is supplied 048 * here. 049 * 050 * @parameter expression="${eclipse.vm}" 051 */ 052 private String vm; 053 054 /** 055 * This is the name of the Eclipse application that performs the formatting 056 * 057 * @parameter expression="${eclipse.application}" default-value="org.eclipse.jdt.core.JavaCodeFormatter" 058 * @required 059 */ 060 private String application; 061 062 /** 063 * Pointer to an Eclipse "org.eclipse.jdt.core.prefs" file. Supports "classpath:" style notation 064 * 065 * @parameter expression="${eclipse.formatterPreferences}" default-value="classpath:eclipse.prefs" 066 * @required 067 */ 068 private String formatterPreferences; 069 070 /** 071 * Any arguments specified here are passed to the Eclipse binary as additional command line arguments. Default 072 * values are "-nosplash -verbose" 073 * 074 * @parameter 075 */ 076 private String[] eclipseArgs = new String[] { "-nosplash", "-verbose" }; 077 078 /** 079 * Regular expressions for directories that contain Java source code to format. Default value is 080 * **/src/main/java. The Eclipse formatter will recursively inspect any directories matching these 081 * patterns for *.java files 082 * 083 * @parameter 084 */ 085 private String[] includes = new String[] { "**/src/main/java" }; 086 087 /** 088 * Regular expressions for directories to exclude from the process that scans for *.java files 089 * 090 * @parameter 091 */ 092 private String[] excludes = new String[] { "**/.settings", "**/.svn" }; 093 094 protected List<File> getSourceDirectories() { 095 DirectoryScanner scanner = new DirectoryScanner(); 096 scanner.setBasedir(project.getBasedir()); 097 scanner.setIncludes(includes); 098 scanner.setExcludes(excludes); 099 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 }