001 /* 002 $Id: CompilerConfiguration.java,v 1.11 2005/02/28 14:47:10 jstrachan Exp $ 003 004 Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. 005 006 Redistribution and use of this software and associated documentation 007 ("Software"), with or without modification, are permitted provided 008 that the following conditions are met: 009 010 1. Redistributions of source code must retain copyright 011 statements and notices. Redistributions must also contain a 012 copy of this document. 013 014 2. Redistributions in binary form must reproduce the 015 above copyright notice, this list of conditions and the 016 following disclaimer in the documentation and/or other 017 materials provided with the distribution. 018 019 3. The name "groovy" must not be used to endorse or promote 020 products derived from this Software without prior written 021 permission of The Codehaus. For written permission, 022 please contact info@codehaus.org. 023 024 4. Products derived from this Software may not be called "groovy" 025 nor may "groovy" appear in their names without prior written 026 permission of The Codehaus. "groovy" is a registered 027 trademark of The Codehaus. 028 029 5. Due credit should be given to The Codehaus - 030 http://groovy.codehaus.org/ 031 032 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS 033 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 034 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 035 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 036 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 037 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 039 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 040 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 041 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 042 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 043 OF THE POSSIBILITY OF SUCH DAMAGE. 044 045 */ 046 047 package org.codehaus.groovy.control; 048 049 import org.codehaus.groovy.control.io.NullWriter; 050 import org.codehaus.groovy.control.messages.WarningMessage; 051 052 import java.io.File; 053 import java.io.PrintWriter; 054 import java.util.LinkedList; 055 import java.util.List; 056 import java.util.Properties; 057 import java.util.StringTokenizer; 058 059 060 /** 061 * Compilation control flags and coordination stuff. 062 * 063 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a> 064 * @version $Id: CompilerConfiguration.java,v 1.11 2005/02/28 14:47:10 jstrachan Exp $ 065 */ 066 067 public class CompilerConfiguration { 068 public static final CompilerConfiguration DEFAULT = new CompilerConfiguration(); 069 070 /** Whether to use the JSR parser or not if no property is explicitly stated */ 071 protected static final boolean DEFAULT_JSR_FLAG = true; 072 073 private static boolean jsrGroovy; 074 075 /** 076 * See WarningMessage for levels 077 */ 078 private int warningLevel; 079 /** 080 * Encoding for source files 081 */ 082 private String sourceEncoding; 083 /** 084 * A PrintWriter for communicating with the user 085 */ 086 private PrintWriter output; 087 /** 088 * Directory into which to write classes 089 */ 090 private File targetDirectory; 091 /** 092 * Classpath for use during compilation 093 */ 094 private LinkedList classpath; 095 /** 096 * If true, the compiler should produce action information 097 */ 098 private boolean verbose; 099 /** 100 * If true, debugging code should be activated 101 */ 102 private boolean debug; 103 /** 104 * The number of non-fatal errors to allow before bailing 105 */ 106 private int tolerance; 107 /** 108 * Base class name for scripts (must derive from Script) 109 */ 110 private String scriptBaseClass; 111 /** 112 * should we use the New JSR Groovy parser or stay with the static one 113 */ 114 private boolean useNewGroovy = getDefaultJsrFlag(); 115 116 private ParserPluginFactory pluginFactory; 117 118 119 /** 120 * Sets the Flags to defaults. 121 */ 122 123 public CompilerConfiguration() { 124 // 125 // Set in safe defaults 126 127 setWarningLevel(WarningMessage.LIKELY_ERRORS); 128 setSourceEncoding("US-ASCII"); 129 setOutput(null); 130 setTargetDirectory((File) null); 131 setClasspath(""); 132 setVerbose(false); 133 setDebug(false); 134 setTolerance(10); 135 setScriptBaseClass(null); 136 137 138 // 139 // Try for better defaults, ignore errors. 140 141 try { 142 setSourceEncoding(System.getProperty("file.encoding", "US-ASCII")); 143 } 144 catch (Exception e) { 145 } 146 try { 147 setOutput(new PrintWriter(System.err)); 148 } 149 catch (Exception e) { 150 } 151 try { 152 setClasspath(System.getProperty("java.class.path")); 153 } 154 catch (Exception e) { 155 } 156 157 try { 158 String target = System.getProperty("groovy.target.directory"); 159 if (target != null) { 160 setTargetDirectory(target); 161 } 162 } 163 catch (Exception e) { 164 } 165 } 166 167 168 /** 169 * Sets the Flags to the specified configuration, with defaults 170 * for those not supplied. 171 */ 172 173 public CompilerConfiguration(Properties configuration) throws ConfigurationException { 174 this(); 175 176 String text = null; 177 int numeric = 0; 178 179 180 // 181 // Warning level 182 183 numeric = getWarningLevel(); 184 try { 185 text = configuration.getProperty("groovy.warnings", "likely errors"); 186 numeric = Integer.parseInt(text); 187 } 188 catch (NumberFormatException e) { 189 if (text.equals("none")) { 190 numeric = WarningMessage.NONE; 191 } 192 else if (text.startsWith("likely")) { 193 numeric = WarningMessage.LIKELY_ERRORS; 194 } 195 else if (text.startsWith("possible")) { 196 numeric = WarningMessage.POSSIBLE_ERRORS; 197 } 198 else if (text.startsWith("paranoia")) { 199 numeric = WarningMessage.PARANOIA; 200 } 201 else { 202 throw new ConfigurationException("unrecogized groovy.warnings: " + text); 203 } 204 } 205 206 setWarningLevel(numeric); 207 208 209 // 210 // Source file encoding 211 212 text = configuration.getProperty("groovy.source.encoding"); 213 if (text != null) { 214 setSourceEncoding(text); 215 } 216 217 218 // 219 // Target directory for classes 220 221 text = configuration.getProperty("groovy.target.directory"); 222 if (text != null) { 223 setTargetDirectory(text); 224 } 225 226 227 // 228 // Classpath 229 230 text = configuration.getProperty("groovy.classpath"); 231 if (text != null) { 232 setClasspath(text); 233 } 234 235 236 // 237 // Verbosity 238 239 text = configuration.getProperty("groovy.output.verbose"); 240 if (text != null && text.equals("true")) { 241 setVerbose(true); 242 } 243 244 245 // 246 // Debugging 247 248 text = configuration.getProperty("groovy.output.debug"); 249 if (text != null && text.equals("true")) { 250 setDebug(true); 251 } 252 253 254 // 255 // Tolerance 256 257 numeric = 10; 258 259 try { 260 text = configuration.getProperty("groovy.errors.tolerance", "10"); 261 numeric = Integer.parseInt(text); 262 } 263 catch (NumberFormatException e) { 264 throw new ConfigurationException(e); 265 } 266 267 setTolerance(numeric); 268 269 270 // 271 // Script Base Class 272 273 text = configuration.getProperty("groovy.script.base"); 274 setScriptBaseClass(text); 275 276 text = configuration.getProperty("groovy.jsr"); 277 if (text != null) { 278 setUseNewGroovy(text.equalsIgnoreCase("true")); 279 } 280 } 281 282 283 /** 284 * Gets the currently configured warning level. See WarningMessage 285 * for level details. 286 */ 287 288 public int getWarningLevel() { 289 return this.warningLevel; 290 } 291 292 293 /** 294 * Sets the warning level. See WarningMessage for level details. 295 */ 296 297 public void setWarningLevel(int level) { 298 if (level < WarningMessage.NONE || level > WarningMessage.PARANOIA) { 299 this.warningLevel = WarningMessage.LIKELY_ERRORS; 300 } 301 else { 302 this.warningLevel = level; 303 } 304 } 305 306 307 /** 308 * Gets the currently configured source file encoding. 309 */ 310 311 public String getSourceEncoding() { 312 return this.sourceEncoding; 313 } 314 315 316 /** 317 * Sets the encoding to be used when reading source files. 318 */ 319 320 public void setSourceEncoding(String encoding) { 321 this.sourceEncoding = encoding; 322 } 323 324 325 /** 326 * Gets the currently configured output writer. 327 */ 328 329 public PrintWriter getOutput() { 330 return this.output; 331 } 332 333 334 /** 335 * Sets the output writer. 336 */ 337 338 public void setOutput(PrintWriter output) { 339 if (this.output == null) { 340 this.output = new PrintWriter(NullWriter.DEFAULT); 341 } 342 else { 343 this.output = output; 344 } 345 } 346 347 348 /** 349 * Gets the target directory for writing classes. 350 */ 351 352 public File getTargetDirectory() { 353 return this.targetDirectory; 354 } 355 356 357 /** 358 * Sets the target directory. 359 */ 360 361 public void setTargetDirectory(String directory) { 362 if (directory != null && directory.length() > 0) { 363 this.targetDirectory = new File(directory); 364 } 365 else { 366 this.targetDirectory = null; 367 } 368 } 369 370 371 /** 372 * Sets the target directory. 373 */ 374 375 public void setTargetDirectory(File directory) { 376 this.targetDirectory = directory; 377 } 378 379 380 /** 381 * Gets the classpath. 382 */ 383 384 public List getClasspath() { 385 return this.classpath; 386 } 387 388 389 /** 390 * Sets the output writer. 391 */ 392 393 public void setClasspath(String classpath) { 394 this.classpath = new LinkedList(); 395 396 StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); 397 while (tokenizer.hasMoreTokens()) { 398 this.classpath.add(tokenizer.nextToken()); 399 } 400 } 401 402 403 /** 404 * Returns true if verbose operation has been requested. 405 */ 406 407 public boolean getVerbose() { 408 return this.verbose; 409 } 410 411 412 /** 413 * Turns verbose operation on or off. 414 */ 415 416 public void setVerbose(boolean verbose) { 417 this.verbose = verbose; 418 } 419 420 421 /** 422 * Returns true if debugging operation has been requested. 423 */ 424 425 public boolean getDebug() { 426 return this.debug; 427 } 428 429 430 /** 431 * Turns debugging operation on or off. 432 */ 433 434 public void setDebug(boolean debug) { 435 this.debug = debug; 436 } 437 438 439 /** 440 * Returns the requested error tolerance. 441 */ 442 443 public int getTolerance() { 444 return this.tolerance; 445 } 446 447 448 /** 449 * Sets the error tolerance, which is the number of 450 * non-fatal errors (per unit) that should be tolerated before 451 * compilation is aborted. 452 */ 453 454 public void setTolerance(int tolerance) { 455 this.tolerance = tolerance; 456 } 457 458 459 /** 460 * Gets the name of the base class for scripts. It must be a subclass 461 * of Script. 462 */ 463 464 public String getScriptBaseClass() { 465 return this.scriptBaseClass; 466 } 467 468 469 /** 470 * Sets the name of the base class for scripts. It must be a subclass 471 * of Script. 472 */ 473 public void setScriptBaseClass(String scriptBaseClass) { 474 this.scriptBaseClass = scriptBaseClass; 475 } 476 477 /** 478 * Returns true if the new groovy (JSR) parser is enabled 479 */ 480 public boolean isUseNewGroovy() { 481 return useNewGroovy; 482 } 483 484 public void setUseNewGroovy(boolean useNewGroovy) { 485 this.useNewGroovy = useNewGroovy; 486 } 487 488 public ParserPluginFactory getPluginFactory() { 489 if (pluginFactory == null) { 490 pluginFactory = ParserPluginFactory.newInstance(isUseNewGroovy()); 491 } 492 return pluginFactory; 493 } 494 495 public void setPluginFactory(ParserPluginFactory pluginFactory) { 496 this.pluginFactory = pluginFactory; 497 } 498 499 /** 500 * Returns true if we are the JSR compatible Groovy language 501 */ 502 public static boolean isJsrGroovy() { 503 return jsrGroovy; 504 } 505 506 /** 507 * Should only be called by the JSR parser 508 */ 509 public static void setJsrGroovy(boolean value) { 510 jsrGroovy = value; 511 } 512 513 protected static boolean getDefaultJsrFlag() { 514 // TODO a temporary hack while we have 2 parsers 515 String property = null; 516 try { 517 property = System.getProperty("groovy.jsr"); 518 } 519 catch (Throwable e) { 520 // ignore security warnings 521 } 522 if (property != null) { 523 return "true".equalsIgnoreCase(property); 524 } 525 return DEFAULT_JSR_FLAG; 526 } 527 528 } 529 530 531 532