1 4 package uk.ac.roe.antigen.builder; 5 6 import java.io.BufferedInputStream ; 7 import java.io.File ; 8 import java.io.FileInputStream ; 9 import java.io.FileNotFoundException ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.net.MalformedURLException ; 13 import java.net.URL ; 14 import java.net.URLDecoder ; 15 import java.util.Enumeration ; 16 import java.util.Hashtable ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Properties ; 20 import java.util.logging.Handler ; 21 import java.util.logging.Level ; 22 import java.util.logging.Logger ; 23 24 import org.apache.commons.cli.CommandLine; 25 import org.apache.commons.cli.HelpFormatter; 26 import org.apache.commons.cli.Option; 27 import org.apache.commons.cli.OptionBuilder; 28 import org.apache.commons.cli.Options; 29 import org.apache.commons.cli.ParseException; 30 import org.apache.commons.cli.Parser; 31 import org.apache.commons.cli.PosixParser; 32 import org.apache.tools.ant.BuildException; 33 import org.apache.tools.ant.BuildLogger; 34 import org.apache.tools.ant.DefaultLogger; 35 import org.apache.tools.ant.Project; 36 import org.apache.tools.ant.ProjectHelper; 37 import org.apache.tools.ant.Target; 38 import org.apache.tools.ant.input.InputHandler; 39 import org.apache.velocity.exception.MethodInvocationException; 40 import org.apache.velocity.exception.ParseErrorException; 41 import org.apache.velocity.exception.ResourceNotFoundException; 42 43 import uk.ac.roe.antigen.ant.BuildGrabber; 44 import uk.ac.roe.antigen.ant.GeneralInputHandler; 45 import uk.ac.roe.antigen.ant.TaskTreeCalcuator; 46 import uk.ac.roe.antigen.dialogs.AbortDialog; 47 import uk.ac.roe.antigen.dialogs.BuildLoggerFrame; 48 import uk.ac.roe.antigen.dialogs.InfoFrame; 49 import uk.ac.roe.antigen.dialogs.SplashScreen; 50 import uk.ac.roe.antigen.dialogs.TargetChoiceFrame; 51 import uk.ac.roe.antigen.textcomponents.DefaultPromptingInputHandler; 52 import uk.ac.roe.antigen.textcomponents.TextInfoDisplay; 53 import uk.ac.roe.antigen.textcomponents.TextTargetChooser; 54 import uk.ac.roe.antigen.utils.Config; 55 import uk.ac.roe.antigen.utils.CopyableFile; 56 57 65 public class Installer { 66 67 private static final String ANTIGEN_HOME = "antigen.home"; 68 69 private static final String ANTIGEN_JARFILE = "antigen.jarfile"; 70 71 74 private static final Logger logger = Logger.getLogger(Installer.class.getName()); 75 76 private static final String PROPERTY_OPTION = "D"; 77 78 private static final String PROXY_OPTION="p"; 79 80 private static final String PROPERTYFILE_OPTION = "f"; 81 82 private static final String CMDLINE_OPTION = "c"; 83 84 private static final String HELP_OPTION = "h"; 85 86 private static final String DEBUG_OPTION = "d"; 87 88 private static final String PROXYUSER_OPTION = "u"; 89 90 private static final String PROPERTY_ANTIGEN_OPTION = "A"; 91 92 public static void main(String [] args) throws Throwable { 93 94 95 CommandLine line = parseCommandLine(args); 96 97 Config.load("/config.properties"); 98 99 if (line.hasOption(PROPERTY_ANTIGEN_OPTION)) { 101 String [] keyValuePairs=line.getOptionValues(PROPERTY_ANTIGEN_OPTION); 102 logger.fine("Found "+keyValuePairs.length/2+" antigen properties"); 103 for (int i=0;i<keyValuePairs.length/2;++i) { 104 String key=keyValuePairs[2*i]; 105 String value=keyValuePairs[2*i+1]; 106 logger.fine("Overriding property "+key+"="+value); 107 Config.setProperty(key,value); 108 } 109 } 110 111 String levelString = Config.getProperty("antigen.loglevel","SEVERE"); 112 boolean debug = line.hasOption(DEBUG_OPTION); 113 if (debug) { 114 levelString = line.getOptionValue(DEBUG_OPTION); 115 } 116 Level logLevel = Level.parse(levelString); 117 118 Logger rootLogger = Logger.getLogger(""); 121 rootLogger.setLevel(logLevel); 122 Handler [] handlers = rootLogger.getHandlers(); 123 assert handlers.length != 0; 124 Handler handler = handlers[0]; 125 handler.setLevel(logLevel); 126 logger.info("Debug mode: "+levelString); 127 128 boolean textOnly = line.hasOption(CMDLINE_OPTION); 129 logger.info("Text only mode: " + textOnly); 130 131 Properties sysprops = System.getProperties(); 132 if (line.hasOption(PROXY_OPTION)) { 133 logger.fine("Setting proxy"); 134 String hostAndPort = line.getOptionValue(PROXY_OPTION); 135 String [] hostAndPortSplit = hostAndPort.split(":"); 136 String host = hostAndPortSplit[0]; 137 String port = hostAndPortSplit.length>1 ? hostAndPortSplit[1] : "80"; 138 logger.fine("Proxying through "+host+" on port "+port); 139 140 sysprops.put("http.proxyHost", host); 142 sysprops.put("http.proxyPort", port); 143 if (line.hasOption(PROXYUSER_OPTION)) { 144 String userAndPass = line.getOptionValue(PROXYUSER_OPTION); 145 String [] userAndPassSplit = userAndPass.split(":"); 146 String proxyUser = userAndPassSplit[0]; 147 String proxyPassword = userAndPassSplit.length>1 ? userAndPassSplit[1] : ""; 148 sysprops.put("http.proxyUser", proxyUser); 149 sysprops.put("http.proxyPassword", proxyPassword); 150 } 151 } 152 153 File thisJar; 154 logger.fine("Getting this jar"); 155 try { 156 thisJar = new Installer().getEnclosingJar(); } catch (FileNotFoundException fe) { 158 logger.warning(fe.getMessage()); 159 logger.warning("Unable to set property "+ANTIGEN_JARFILE); 160 thisJar = new File ("Unknown"); 161 } 162 163 if ((Config.getProperty("antigen.splash.logo")!=null || Config.getProperty("antigen.splash.text")!=null) && !textOnly) { 165 new SplashScreen().show(); 166 } 167 168 169 170 171 172 173 String buildSrcType = Config.getProperty("build.src.type"); 175 String buildSrcLoc = Config.getProperty("build.src.location"); 176 assert buildSrcLoc != null; 177 CopyableFile tmpDir = null; 178 179 String buildDir = Config.getProperty("antigen.tmp.dir"); 180 try { 181 BuildGrabber buildGrabber; 182 if (buildDir!=null) { 183 buildGrabber= new BuildGrabber(new File (buildDir)); 184 } else { 185 buildGrabber= new BuildGrabber(); 186 } 187 if ("dir".equals(buildSrcType)) { 188 logger.fine("Grabbing from directory " + buildSrcLoc); 190 tmpDir = buildGrabber.grab(new File (buildSrcLoc)); 191 } else if ("classpath".equals(buildSrcType)) { 192 logger.fine("Grabbing from the classpath off " + buildSrcLoc); 195 tmpDir = buildGrabber.grab(buildSrcLoc); 196 } else if ("self".equals(buildSrcType)) { 197 logger.fine("Grabbing from self"); 198 tmpDir = buildGrabber.grab(thisJar.toURL()); 199 } else { 200 tmpDir = buildGrabber.grab(new URL (buildSrcLoc)); 202 } 203 } catch (MalformedURLException e1) { 204 logger.severe("Unable to load build script from " + buildSrcType + " " + buildSrcLoc); 205 logger.severe("Sorry, but I can't continue"); 206 logger.fine(e1.getMessage()); 207 throw e1; 208 } catch (IOException e1) { 209 logger.severe("Unable to load build script from " + buildSrcType + " " + buildSrcLoc); 210 logger.severe("Sorry, but I can't continue"); 211 logger.fine(e1.getMessage()); 212 throw e1; 213 } 214 215 BuildLoggerFrame builddialog = null; 216 if (!textOnly) { 217 builddialog = new BuildLoggerFrame(); 218 } 219 showInfoDialog(builddialog, sysprops, "antigen.intro.text", "antigen.intro.template", textOnly); 220 221 File buildFile = new File (tmpDir, "build.xml"); 222 223 Project project = new Project(); 224 project.init(); 225 ProjectHelper.configureProject(project, buildFile); 226 227 229 project.setProperty(ANTIGEN_HOME, System.getProperty("user.dir")); project.setProperty(ANTIGEN_JARFILE, thisJar.getAbsolutePath()); 231 232 if (line.hasOption(PROPERTY_OPTION)) { 235 String [] keyValuePairs=line.getOptionValues(PROPERTY_OPTION); 236 logger.fine("Found "+keyValuePairs.length/2+" command line properties"); 237 for (int i=0;i<keyValuePairs.length/2;++i) { 238 String key=keyValuePairs[2*i]; 239 String value=keyValuePairs[2*i+1]; 240 logger.fine("Setting property "+key+"="+value); 241 project.setProperty(key, value); 242 } 243 } 244 245 if (line.hasOption(PROPERTYFILE_OPTION)) { 247 logger.fine("Attempting to load properties from a file"); 248 File inputFile = new File (line.getOptionValue(PROPERTYFILE_OPTION)); 249 Properties props = new Properties (); 252 InputStream is = null; 253 try { 254 is = new BufferedInputStream (new FileInputStream (inputFile)); 255 props.load(is); 256 } catch (IOException ie) { 257 logger.warning("Was unable to load properties file " + ie.getMessage() + "...continuing"); 258 } finally { 259 if (is != null) 260 try { 261 is.close(); 262 } catch (IOException swallow) { 263 } 265 } 266 Enumeration enumer = props.keys(); 267 while (enumer.hasMoreElements()) { 268 String key = (String ) enumer.nextElement(); 269 logger.fine("Putting property " + key + "=" + props.getProperty(key)); 270 project.setProperty(key, props.getProperty(key)); 271 } 272 } 273 274 String targetName = project.getDefaultTarget(); 276 277 String anyChosenTargets = Config.getProperty(TargetChoiceFrame.ANTIGEN_TARGETS); 278 if (anyChosenTargets != null) { 279 if (anyChosenTargets.split(",").length == 1) { 280 targetName = anyChosenTargets; } else { 284 TargetChooser targetChoiceFrame; 285 if (textOnly) { 286 targetChoiceFrame = new TextTargetChooser(project); 287 } else { 288 targetChoiceFrame = new TargetChoiceFrame(project); 289 } 290 List targetNames = targetChoiceFrame.showAndWaitForResponse(); 291 Target master = new Target(); 292 293 Iterator it = targetNames.iterator(); 295 while (it.hasNext()) { 296 String next = (String ) it.next(); 297 logger.fine("Adding target " + next); 298 master.addDependency(next); 299 } 300 final String masterTargetName = "master"; 301 master.setName(masterTargetName); 302 master.setDescription("One project to rule them all"); 303 project.addTarget(masterTargetName, master); 305 targetName = masterTargetName; 306 project.init(); 307 } 308 } 309 310 312 int numberOfTasks = new TaskTreeCalcuator(project).getNumberOfTasksToRun(targetName); 313 logger.fine("main(String[])" + numberOfTasks); 314 315 InputHandler inputHandler; 316 BuildLogger buildLogger; 317 if (!textOnly) { 318 builddialog.setVisible(true); 319 builddialog.setNumberOfTasks(numberOfTasks); BuildLogger dialogBuildLogger = builddialog.getBuildLogger(); 322 323 inputHandler = new GeneralInputHandler(builddialog); 324 buildLogger = dialogBuildLogger; 325 326 } else { 327 inputHandler = new DefaultPromptingInputHandler(); 328 DefaultLogger defaultListener = new DefaultLogger(); 329 buildLogger = defaultListener; 330 buildLogger.setOutputPrintStream(System.out); 331 buildLogger.setErrorPrintStream(System.err); 332 } 333 334 int antOutputLevel = Integer.parseInt(Config.getProperty("antigen.antoutput","2")); 335 buildLogger.setMessageOutputLevel(antOutputLevel); 336 project.addBuildListener(buildLogger); 337 project.setInputHandler(inputHandler); 338 339 try { 340 project.executeTarget(targetName); 341 if (!textOnly) { 342 builddialog.setFinished(); 343 } 344 345 showInfoDialog(builddialog, project.getProperties(), "antigen.outro.text", "antigen.outro.template", 346 textOnly); 347 348 } catch (BuildException e) { 349 logger.info("There was an error in the build process"); 350 logger.info("e.getClass()"); 351 logger.info("e"); 352 if (textOnly) { 353 System.out.println(e.getMessage()); 354 } else { 355 new AbortDialog(builddialog, e.getMessage()).show(); 356 } 357 } finally { 358 if (buildDir==null) { 360 tmpDir.recursivelyDelete(); 361 } 362 } 363 364 } 365 366 369 private static CommandLine parseCommandLine(String [] args) { 370 Parser parser = new PosixParser(); 371 Options options = new Options(); 372 options.addOption(HELP_OPTION, "help", false, "Display this help.") 373 .addOption(CMDLINE_OPTION, "commandline", false, "Execute on the command line (without a GUI)") 374 .addOption(DEBUG_OPTION, "debug", true,"Set the commandline debug output level - see java doc for java/util/logging/Level for values, defaults to SEVERE") 375 .addOption(PROPERTYFILE_OPTION, "properties", true,"Supply a .property file") 376 .addOption(PROXY_OPTION,"proxy",true,"Supply a web proxy host (host:port)") 378 .addOption(PROXYUSER_OPTION,"user",true, "Supply a user name for the proxy (user:password)"); 379 Option propertyOpt = OptionBuilder.withArgName( "property=value" ) 380 .withLongOpt("antproperty") 381 .hasArg() 382 .withValueSeparator() 383 .withDescription( "use value for given property in the Ant build" ) 384 .create( PROPERTY_OPTION ); 385 options.addOption(propertyOpt); 386 propertyOpt.setArgs(Option.UNLIMITED_VALUES); 387 388 Option antigenPropertyOpt = OptionBuilder.withArgName( "property=value" ) 389 .withLongOpt("antigenproperty") 390 .hasArg() 391 .withValueSeparator() 392 .withDescription( "use value for given property, overriding the value in the Antigen config.properties file" ) 393 .create( PROPERTY_ANTIGEN_OPTION ); 394 options.addOption(antigenPropertyOpt); 395 antigenPropertyOpt.setArgs(Option.UNLIMITED_VALUES); 396 397 CommandLine line = null; 398 try { 399 line = parser.parse(options, args); 400 } catch (ParseException e) { 401 logger.severe("Error parsing command line " + e.getMessage()); 402 displayHelp(options); 403 System.exit(1); } 405 if (line.hasOption(HELP_OPTION)) { 406 displayHelp(options); 407 System.exit(0); } 409 return line; 410 } 411 412 416 private static void displayHelp(Options options) { 417 new HelpFormatter().printHelp("java -jar (jarname) option", options); 418 } 419 420 431 private static void showInfoDialog(BuildLoggerFrame builddialog, Hashtable properties, String textKey, 432 String templateKey, boolean textOnly) throws Exception { 433 String text = Config.getProperty(textKey); 434 String template = Config.getProperty(templateKey); 435 String message = template != null ? MessageProcessor.processMessage(properties, template) : text; 436 437 if (message == null) { 438 logger.fine("No information text"); 439 return; 440 } 441 442 InfoDisplay display; 443 if (textOnly) { 444 display = new TextInfoDisplay(message); 445 } else { 446 display = new InfoFrame(message); 447 } 448 449 display.showAndWaitForResponse(); 450 } 451 452 459 460 private File getEnclosingJar() throws FileNotFoundException { 461 logger.fine("Attempting to get enclosing jar name"); 462 String thisClass = "/" + getClass().getName().replace('.', '/') + ".class"; 463 logger.finer("This class " + thisClass); 464 URL jarUrl = this.getClass().getResource(thisClass); 465 String stringForm = jarUrl.toString(); 466 logger.finer("Jar URL " + stringForm); 467 String fileForm = jarUrl.getFile(); 468 469 int endIdx = stringForm.indexOf("!/"); 470 if (endIdx == -1) { 471 throw new FileNotFoundException ("Could not locate enclosing jar: !/ not found in URL"); 472 } 473 474 String fileNamePart = stringForm.substring("jar:file:".length(), endIdx); 475 logger.finer("Extracted file name: " + fileNamePart); 476 String unescaped = URLDecoder.decode(fileNamePart); 477 logger.finer("Unescaped Extracted file name: " + unescaped); 478 File file = new File (unescaped); 479 if (!file.exists()) { 480 throw new FileNotFoundException ("Could not locate enclosing jar: file "+file+" not found"); 481 } 482 return file; 483 } 484 485 } | Popular Tags |