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