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 019 /** 020 * A plugin for executing the Eclipse java source code formatter 021 * 022 * @author Jeff Caddel 023 * @goal format 024 * @aggregator 025 */ 026 public class EclipseFormatterMojo extends ExecMojo { 027 private static final String FS = System.getProperty("file.separator"); 028 029 /** 030 * Binaries representing a Java VM. Default values are "javaw.exe", "java.exe", and "java". This list is searched in 031 * order, stopping as soon as one is found. 032 * 033 * @parameter 034 */ 035 private String[] javaBinaries = new String[] { "javaw.exe", "java.exe", "java" }; 036 037 /** 038 * Full path to the Eclipse executable binary 039 * 040 * @parameter expression="${eclipse.binary}" 041 * @required 042 */ 043 private String eclipseBinary; 044 045 /** 046 * Full path to a Java VM. This gets filled in using the system property "java.home" unless a value is supplied 047 * here. 048 * 049 * @parameter expression="${eclipse.vm}" 050 */ 051 private String vm; 052 053 /** 054 * This is the name of the Eclipse application that performs the formatting 055 * 056 * @parameter expression="${eclipse.application}" default-value="org.eclipse.jdt.core.JavaCodeFormatter" 057 * @required 058 */ 059 private String application; 060 061 /** 062 * Pointer to an Eclipse "org.eclipse.jdt.core.prefs" file. Supports "classpath:" style notation 063 * 064 * @parameter expression="${eclipse.formatterPreferences}" default-value="classpath:eclipse.prefs" 065 * @required 066 */ 067 private String formatterPreferences; 068 069 /** 070 * Any arguments specified here are passed to the Eclipse binary as additional command line arguments. Default 071 * values are "-nosplash -verbose" 072 * 073 * @parameter 074 */ 075 private String[] eclipseArgs = new String[] { "-nosplash", "-verbose" }; 076 077 /** 078 * Regular expressions for directories that contain Java source code to format. Default values are 079 * **/src/main/java and **/src/test/java. The Eclipse formatter will recursively inspect any 080 * directories matching these patterns for *.java files 081 * 082 * @parameter 083 */ 084 private String[] includes = new String[] { "**/src/main/java", "**/src/test/java" }; 085 086 /** 087 * Regular expressions for directories to exclude from the formatting process. 088 * 089 * @parameter 090 */ 091 private String[] excludes = new String[] { "**/.settings", "**/.svn" }; 092 093 protected List<File> getSourceDirectories() { 094 DirectoryScanner scanner = new DirectoryScanner(); 095 scanner.setBasedir(project.getBasedir()); 096 scanner.setIncludes(includes); 097 scanner.setExcludes(excludes); 098 scanner.scan(); 099 String[] includedDirs = scanner.getIncludedDirectories(); 100 List<File> dirs = new ArrayList<File>(); 101 for (String includedDir : includedDirs) { 102 File file = new File(project.getBasedir().getAbsolutePath() + FS + includedDir); 103 dirs.add(file); 104 } 105 return dirs; 106 } 107 108 @Override 109 public void execute() throws MojoExecutionException { 110 File file = new File(eclipseBinary); 111 if (!file.exists()) { 112 throw new MojoExecutionException(eclipseBinary + " does not exist"); 113 } 114 getLog().info("Eclipse Location: " + file.getAbsolutePath()); 115 getLog().info("Java VM: " + getJavaBinary()); 116 getLog().info("Scanning directory: " + project.getBasedir()); 117 StringBuilder sb = new StringBuilder(); 118 for (String include : includes) { 119 sb.append(include + " "); 120 } 121 getLog().info("Includes: " + sb.toString()); 122 sb = new StringBuilder(); 123 for (String exclude : excludes) { 124 sb.append(exclude + " "); 125 } 126 getLog().info("Excludes: " + sb.toString()); 127 List<File> dirs = getSourceDirectories(); 128 129 if (dirs.size() == 0) { 130 getLog().info("No directories containing source code were located"); 131 return; 132 } else { 133 getLog().info("Located " + dirs.size() + " source directories:"); 134 for (File dir : dirs) { 135 getLog().info(dir.getAbsolutePath()); 136 } 137 } 138 139 super.setExecutable(quote(eclipseBinary)); 140 super.setArguments(getEclipseArguments(dirs)); 141 142 super.execute(); 143 } 144 145 protected String getJavaBinary() throws MojoExecutionException { 146 if (!StringUtils.isEmpty(vm)) { 147 return vm; 148 } 149 String javaHome = System.getProperty("java.home"); 150 String binaryHome = javaHome + FS + "bin"; 151 for (String binary : javaBinaries) { 152 File file = new File(binaryHome + FS + binary); 153 if (file.exists()) { 154 return file.getAbsolutePath(); 155 } 156 } 157 throw new MojoExecutionException( 158 "No Java VM location was supplied, and we could not locate one using the System property 'java.home'"); 159 } 160 161 protected List<String> getEclipseArguments(List<File> dirs) throws MojoExecutionException { 162 List<String> args = new ArrayList<String>(); 163 args.add("-application"); 164 args.add(quote(application)); 165 args.add("-vm"); 166 args.add(quote(getJavaBinary())); 167 args.add("-config"); 168 args.add(quote(getConfigAbsolutePath())); 169 for (String arg : eclipseArgs) { 170 addIfNotEmpty(args, arg); 171 } 172 for (File dir : dirs) { 173 args.add(quote(dir.getAbsolutePath())); 174 } 175 return args; 176 } 177 178 protected String quote(String s) { 179 return '"' + s + '"'; 180 } 181 182 protected String getConfigAbsolutePath() throws MojoExecutionException { 183 File file = new File(formatterPreferences); 184 if (file.exists()) { 185 return file.getAbsolutePath(); 186 } 187 ResourceLoader loader = new DefaultResourceLoader(); 188 Resource resource = loader.getResource(formatterPreferences); 189 if (!resource.exists()) { 190 throw new MojoExecutionException("Unable to locate " + formatterPreferences); 191 } 192 OutputStream out = null; 193 InputStream in = null; 194 try { 195 File temp = File.createTempFile("eclipse.prefs.", null); 196 out = new FileOutputStream(temp); 197 in = resource.getInputStream(); 198 IOUtils.copy(in, out); 199 return temp.getAbsolutePath(); 200 } catch (IOException e) { 201 throw new MojoExecutionException("Error copying resource " + formatterPreferences, e); 202 } finally { 203 IOUtils.closeQuietly(out); 204 IOUtils.closeQuietly(in); 205 } 206 207 } 208 209 protected void addIfNotEmpty(List<String> list, String s) { 210 if (StringUtils.isEmpty(s)) { 211 return; 212 } 213 list.add(s); 214 } 215 216 public String getEclipseBinary() { 217 return eclipseBinary; 218 } 219 220 public void setEclipseBinary(String eclipseExecutable) { 221 this.eclipseBinary = eclipseExecutable; 222 } 223 224 public String getVm() { 225 return vm; 226 } 227 228 public void setVm(String vm) { 229 this.vm = vm; 230 } 231 232 public String getApplication() { 233 return application; 234 } 235 236 public void setApplication(String application) { 237 this.application = application; 238 } 239 240 public String[] getIncludes() { 241 return includes; 242 } 243 244 public void setIncludes(String[] includes) { 245 this.includes = includes; 246 } 247 248 public String[] getExcludes() { 249 return excludes; 250 } 251 252 public void setExcludes(String[] excludes) { 253 this.excludes = excludes; 254 } 255 256 public String[] getJavaBinaries() { 257 return javaBinaries; 258 } 259 260 public void setJavaBinaries(String[] binaries) { 261 this.javaBinaries = binaries; 262 } 263 264 public String getFormatterPreferences() { 265 return formatterPreferences; 266 } 267 268 public void setFormatterPreferences(String formatterPreferences) { 269 this.formatterPreferences = formatterPreferences; 270 } 271 272 public String[] getEclipseArgs() { 273 return eclipseArgs; 274 } 275 276 public void setEclipseArgs(String[] args) { 277 this.eclipseArgs = args; 278 } 279 280 }