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