001package com.ganteater.ae; 002 003import java.io.ByteArrayOutputStream; 004import java.io.File; 005import java.io.IOException; 006import java.io.PrintStream; 007import java.net.ServerSocket; 008import java.util.Enumeration; 009import java.util.List; 010import java.util.Map; 011import java.util.Properties; 012 013import javax.net.ssl.SSLServerSocketFactory; 014import javax.swing.JOptionPane; 015 016import org.apache.commons.cli.CommandLine; 017import org.apache.commons.cli.CommandLineParser; 018import org.apache.commons.cli.DefaultParser; 019import org.apache.commons.cli.HelpFormatter; 020import org.apache.commons.cli.Option; 021import org.apache.commons.cli.Options; 022import org.apache.commons.cli.ParseException; 023import org.apache.commons.lang.ObjectUtils; 024import org.apache.commons.lang.exception.ExceptionUtils; 025import org.apache.commons.lang3.StringUtils; 026 027import com.ganteater.ae.processor.BaseProcessor; 028import com.ganteater.ae.processor.Processor; 029import com.ganteater.ae.processor.TaskProcessorThread; 030import com.ganteater.ae.util.AEUtils; 031import com.ganteater.ae.util.xml.easyparser.Node; 032 033/** 034 * @author victort 035 * @version 1.0, 29-Jul-2005 036 */ 037public class RecipeRunner implements RecipeListener { 038 039 private static final String WELCOME_MESSAGE = "Giant anteater looking for recipes ..."; 040 041 public static int STATUS_SUCCESS = 0; 042 043 public static int STATUS_FAILED = 1; 044 045 public static String RUN_MODE_APPLICATION = "Application"; 046 047 public static String RUN_MODE_WEB = "Web"; 048 049 protected Node fConfigNode; 050 051 private Map<String, Object> fSystemVariables; 052 053 private Processor processor = null; 054 055 private String fNameTask; 056 057 private String fRunMode = RUN_MODE_APPLICATION; 058 059 private int fStatus = STATUS_SUCCESS; 060 061 protected AEManager manager; 062 063 private Node fTaskNode; 064 065 private ILogger log; 066 067 public RecipeRunner(AEManager manager) { 068 this(manager, manager.getConfigNode(), manager.getSystemVariables()); 069 } 070 071 public RecipeRunner(AEManager manager, Node aConfigNode, Map<String, Object> aSystemVariables) { 072 fConfigNode = aConfigNode; 073 this.manager = manager; 074 fSystemVariables = aSystemVariables; 075 this.manager.addRunner(this); 076 } 077 078 public Processor getTaskProcessor() { 079 return processor; 080 } 081 082 public Node getTaskNode() { 083 return fTaskNode; 084 } 085 086 public void setProcessor(Processor processor) { 087 this.processor = processor; 088 } 089 090 public void makeRecipe(String file) throws CommandException { 091 Processor newProcessor = new BaseProcessor(fSystemVariables, fConfigNode, manager.getStartDir()); 092 newProcessor.setTestListener(this); 093 newProcessor.setLogger(log); 094 setProcessor(newProcessor); 095 getTaskProcessor().make(file); 096 } 097 098 public void runTest(Node testNode[]) throws Exception { 099 setTaskNode(testNode[0]); 100 processor = new BaseProcessor(fConfigNode, fSystemVariables, this, manager.getStartDir(), getLogger(), 101 getTaskProcessor()); 102 processor.runNodes(testNode); 103 endTask(false); 104 } 105 106 public void setTaskNode(Node object) { 107 fTaskNode = object; 108 } 109 110 public void criticalError(CommandException aThrowable, Processor processor) { 111 this.endTask(true); 112 fStatus = STATUS_FAILED; 113 StringBuilder taskTrace = new StringBuilder(aThrowable.getTaskTrace() + "\n\n"); 114 Throwable rootCause = ExceptionUtils.getRootCause(aThrowable); 115 processor.getLogger().error(taskTrace.toString(), (Throwable) ObjectUtils.defaultIfNull(rootCause, aThrowable)); 116 } 117 118 public void checkFailure(CommandException e, Processor processor) { 119 fStatus = STATUS_FAILED; 120 processor.getLogger().error("Check Failure. Message: " + e.getMessage() + "\n" + e.getTaskTrace()); 121 this.endTask(true); 122 getLogger().debug(e); 123 } 124 125 public void startTask(String aNameTask) { 126 setTestName(aNameTask); 127 } 128 129 public void setTestName(String aNameTask) { 130 fNameTask = aNameTask; 131 } 132 133 public void setProgress(String aCurrentTaskName, long aMaxTags, long aCurrTags, boolean aErrorState) { 134 } 135 136 public AEManager getManager() { 137 return manager; 138 } 139 140 public void endTask(boolean aErrorState) { 141 manager.removeRunner(this); 142 } 143 144 public void changeVariable(String aAttribut, Object aValue) { 145 } 146 147 public void startCommand(int i) { 148 } 149 150 public void startChildProcess(TaskProcessorThread aMaxTestRunnable) { 151 } 152 153 public void stopChildProcess(TaskProcessorThread aMaxTestRunnable) { 154 } 155 156 public Node getConfigNode() { 157 return fConfigNode; 158 } 159 160 public void stopTest() { 161 if (processor != null) { 162 processor.stop(); 163 } 164 } 165 166 public String getTitle() { 167 return fNameTask; 168 } 169 170 public String inputFile(File aDefaultFile, Processor taskProcessor) { 171 return aDefaultFile.getAbsolutePath(); 172 } 173 174 public void aboutTest(String theTaskName, Node aCurrentAction) { 175 176 } 177 178 public void setRunMode(String aMode) { 179 fRunMode = aMode; 180 } 181 182 public String getRunMode() { 183 return fRunMode; 184 } 185 186 public void exceptionIgnored(Throwable e) { 187 List<Node> callTaskTrace = getTaskProcessor().getLocalTaskTrace(); 188 ByteArrayOutputStream stack = new ByteArrayOutputStream(); 189 e.printStackTrace(new PrintStream(stack)); 190 getLogger().debug("Exception ignored. Recipe: " + StringUtils.join(callTaskTrace, " - ") + "\nException: " 191 + stack.toString()); 192 } 193 194 public ILogger getLogger() { 195 return log; 196 } 197 198 public int getStatus() { 199 return fStatus; 200 } 201 202 public ServerSocket createPort(int thePort, String aDescription) throws IOException { 203 ServerSocket serverSocket = null; 204 205 if (thePort < 0) { 206 SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 207 serverSocket = factory.createServerSocket(-thePort); 208 } else { 209 serverSocket = new ServerSocket(thePort); 210 } 211 212 return serverSocket; 213 } 214 215 public void closePort(int thePort) { 216 } 217 218 public void errorInformation(Processor processor, Throwable e, Node command) throws CommandException { 219 if (e instanceof CommandException) { 220 throw (CommandException) e; 221 } else { 222 throw new CommandException(e, processor, command); 223 } 224 } 225 226 public void outToFrame(Processor processor, Properties aProperties, Object aTheValue) { 227 } 228 229 public void runCommandFrame(Properties params) throws Throwable { 230 } 231 232 public ILogger createLog(String aName, boolean mainLog) { 233 return log; 234 } 235 236 public void pause() { 237 } 238 239 public void resume() { 240 } 241 242 @Override 243 public boolean isNotifyMe() { 244 return false; 245 } 246 247 public Map<String, Object> getSystemVariables() { 248 return fSystemVariables; 249 } 250 251 public void setLog(ILogger log) { 252 this.log = log; 253 } 254 255 public static void main(String... args) throws IOException { 256 257 Options options = new Options(); 258 Option helpOption = new Option("h", "help", false, "Displays help information for usage."); 259 Option versionOption = new Option("v", "version", false, 260 "Use this option to check which version of Anteater you are running, ensuring compatibility with your recipes and plugins."); 261 Option commandPortOption = new Option("c", "commandPort", true, 262 "Specifies the port for command communication."); 263 Option configNameOption = new Option("n", "configName", true, "Specifies the configuration name to use."); 264 Option commandServerPortOption = new Option("s", "serverPort", true, 265 "Specifies the port for the command server."); 266 Option consoleOption = new Option("con", "console", false, "Force application to run in console mode"); 267 268 options.addOption(helpOption); 269 options.addOption(versionOption); 270 options.addOption(commandPortOption); 271 options.addOption(configNameOption); 272 options.addOption(commandServerPortOption); 273 options.addOption(consoleOption); 274 275 CommandLineParser parser = new DefaultParser(); 276 HelpFormatter formatter = new HelpFormatter(); 277 278 try { 279 CommandLine cmd = parser.parse(options, args); 280 281 if (cmd.hasOption(versionOption)) { 282 System.out.println("Anteater Version: " + AEUtils.getPrjProperty("application.version")); 283 return; 284 } 285 286 if (cmd.hasOption(helpOption)) { 287 help(options, formatter); 288 return; 289 } 290 291 if (!cmd.hasOption(consoleOption) && System.console() == null) { 292 JOptionPane.showMessageDialog(null, 293 "ae.jar is a command line tool and should be run in a terminal or command prompt."); 294 System.exit(1); 295 } 296 297 if (cmd.hasOption(commandPortOption)) { 298 int port = Integer.parseInt(cmd.getOptionValue(commandPortOption)); 299 String[] commands = cmd.getArgs(); 300 CommandServer.sendCommand(port, commands); 301 System.exit(0); 302 } 303 304 if (cmd.hasOption(configNameOption)) { 305 String configName = cmd.getOptionValue(configNameOption); 306 System.setProperty(ConfigConstants.CONFIG_NAME_SYS_PRPERTY_NAME, configName); 307 } 308 309 AEWorkspace workspace = new AEWorkspace(); 310 try { 311 if (cmd.hasOption(commandServerPortOption)) { 312 int port = Integer.parseInt(cmd.getOptionValue(commandServerPortOption)); 313 CommandServer.openCommandPort(workspace, port); 314 } 315 316 String[] recipes = cmd.getArgs(); 317 System.setProperty(ConfigConstants.RECIPES_PARAM_NAME, StringUtils.join(recipes, ",")); 318 319 System.out.println(WELCOME_MESSAGE); 320 workspace.loadConfiguration(true); 321 322 System.out.println("Configuration: [" + workspace.getConfigurationName() + "]"); 323 workspace.runSetupNodes(); 324 325 if (recipes.length == 0) { 326 String[] testsList = workspace.getTestsList(); 327 Processor processor = new BaseProcessor(workspace.getSystemVariables(), workspace.getConfigNode(), 328 workspace.getStartDir()); 329 recipes = workspace.inputMultiChoice("Recipe", testsList, null, processor); 330 } 331 332 if (recipes != null) { 333 for (String name : recipes) { 334 System.out.println("Recipe: [" + name + "]"); 335 RecipeRunner runTask = workspace.runTask(name, false); 336 337 if (runTask == null) { 338 System.out.println("Recipe: [" + name + "] not found."); 339 340 Enumeration<Object> keys = workspace.getTestsDescList().keys(); 341 System.out.println("Recipe list:"); 342 while (keys.hasMoreElements()) { 343 Object taskName = (Object) keys.nextElement(); 344 System.out.println("\t" + taskName); 345 } 346 } 347 348 if (runTask.getStatus() == STATUS_FAILED) { 349 System.exit(STATUS_FAILED); 350 } 351 } 352 } 353 354 } catch ( 355 356 Exception e) { 357 e.printStackTrace(); 358 System.exit(STATUS_FAILED); 359 } 360 361 workspace.close(); 362 } catch ( 363 364 ParseException e) { 365 System.err.println("Error parsing arguments: " + e.getMessage()); 366 help(options, formatter); 367 } 368 } 369 370 private static void help(Options options, HelpFormatter formatter) { 371 formatter.printHelp("java -jar ae.jar <recipe_name> ...", options); 372 } 373 374}