001: /*
002: $Id: CompilerConfiguration.java 3906 2006-07-19 00:11:46Z glaforge $
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: * Compilation control flags and coordination stuff.
061: *
062: * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
063: * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
064: * @version $Id: CompilerConfiguration.java 3906 2006-07-19 00:11:46Z glaforge $
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: * extension used to find a groovy file
120: */
121: private String defaultScriptExtension = ".groovy";
122:
123: /**
124: * if set to true recompilation is enabled
125: */
126: private boolean recompileGroovySource;
127:
128: /**
129: * sets the minimum of time after a script can be recompiled.
130: */
131: private int minimumRecompilationInterval;
132:
133: /**
134: * Sets the Flags to defaults.
135: */
136: public CompilerConfiguration() {
137: //
138: // Set in safe defaults
139:
140: setWarningLevel(WarningMessage.LIKELY_ERRORS);
141: setSourceEncoding("US-ASCII");
142: setOutput(null);
143: setTargetDirectory((File) null);
144: setClasspath("");
145: setVerbose(false);
146: setDebug(false);
147: setTolerance(10);
148: setScriptBaseClass(null);
149: setRecompileGroovySource(false);
150: setMinimumRecompilationInterval(100);
151:
152: //
153: // Try for better defaults, ignore errors.
154:
155: try {
156: setSourceEncoding(System.getProperty("file.encoding",
157: "US-ASCII"));
158: } catch (Exception e) {
159: }
160: try {
161: setOutput(new PrintWriter(System.err));
162: } catch (Exception e) {
163: }
164: /*try {
165: setClasspath(System.getProperty("java.class.path"));
166: }
167: catch (Exception e) {
168: }*/
169:
170: try {
171: String target = System
172: .getProperty("groovy.target.directory");
173: if (target != null) {
174: setTargetDirectory(target);
175: }
176: } catch (Exception e) {
177: }
178: }
179:
180: /**
181: * Sets the Flags to the specified configuration, with defaults
182: * for those not supplied.
183: */
184:
185: public CompilerConfiguration(Properties configuration)
186: throws ConfigurationException {
187: this ();
188:
189: String text = null;
190: int numeric = 0;
191:
192: //
193: // Warning level
194:
195: numeric = getWarningLevel();
196: try {
197: text = configuration.getProperty("groovy.warnings",
198: "likely errors");
199: numeric = Integer.parseInt(text);
200: } catch (NumberFormatException e) {
201: if (text.equals("none")) {
202: numeric = WarningMessage.NONE;
203: } else if (text.startsWith("likely")) {
204: numeric = WarningMessage.LIKELY_ERRORS;
205: } else if (text.startsWith("possible")) {
206: numeric = WarningMessage.POSSIBLE_ERRORS;
207: } else if (text.startsWith("paranoia")) {
208: numeric = WarningMessage.PARANOIA;
209: } else {
210: throw new ConfigurationException(
211: "unrecogized groovy.warnings: " + text);
212: }
213: }
214:
215: setWarningLevel(numeric);
216:
217: //
218: // Source file encoding
219:
220: text = configuration.getProperty("groovy.source.encoding");
221: if (text != null) {
222: setSourceEncoding(text);
223: }
224:
225: //
226: // Target directory for classes
227:
228: text = configuration.getProperty("groovy.target.directory");
229: if (text != null) {
230: setTargetDirectory(text);
231: }
232:
233: //
234: // Classpath
235:
236: text = configuration.getProperty("groovy.classpath");
237: if (text != null) {
238: setClasspath(text);
239: }
240:
241: //
242: // Verbosity
243:
244: text = configuration.getProperty("groovy.output.verbose");
245: if (text != null && text.equals("true")) {
246: setVerbose(true);
247: }
248:
249: //
250: // Debugging
251:
252: text = configuration.getProperty("groovy.output.debug");
253: if (text != null && text.equals("true")) {
254: setDebug(true);
255: }
256:
257: //
258: // Tolerance
259:
260: numeric = 10;
261:
262: try {
263: text = configuration.getProperty("groovy.errors.tolerance",
264: "10");
265: numeric = Integer.parseInt(text);
266: } catch (NumberFormatException e) {
267: throw new ConfigurationException(e);
268: }
269:
270: setTolerance(numeric);
271:
272: //
273: // Script Base Class
274:
275: text = configuration.getProperty("groovy.script.base");
276: setScriptBaseClass(text);
277:
278: text = configuration.getProperty("groovy.jsr");
279: if (text != null) {
280: setUseNewGroovy(text.equalsIgnoreCase("true"));
281: }
282:
283: //
284: // recompilation options
285: //
286: text = configuration.getProperty("groovy.recompile");
287: if (text != null) {
288: setRecompileGroovySource(text.equalsIgnoreCase("true"));
289: }
290:
291: numeric = 100;
292: try {
293: text = configuration.getProperty(
294: "groovy.recompile.minimumIntervall", "" + numeric);
295: numeric = Integer.parseInt(text);
296: } catch (NumberFormatException e) {
297: throw new ConfigurationException(e);
298: }
299: setMinimumRecompilationInterval(numeric);
300:
301: }
302:
303: /**
304: * Gets the currently configured warning level. See WarningMessage
305: * for level details.
306: */
307: public int getWarningLevel() {
308: return this .warningLevel;
309: }
310:
311: /**
312: * Sets the warning level. See WarningMessage for level details.
313: */
314: public void setWarningLevel(int level) {
315: if (level < WarningMessage.NONE
316: || level > WarningMessage.PARANOIA) {
317: this .warningLevel = WarningMessage.LIKELY_ERRORS;
318: } else {
319: this .warningLevel = level;
320: }
321: }
322:
323: /**
324: * Gets the currently configured source file encoding.
325: */
326: public String getSourceEncoding() {
327: return this .sourceEncoding;
328: }
329:
330: /**
331: * Sets the encoding to be used when reading source files.
332: */
333: public void setSourceEncoding(String encoding) {
334: this .sourceEncoding = encoding;
335: }
336:
337: /**
338: * Gets the currently configured output writer.
339: */
340: public PrintWriter getOutput() {
341: return this .output;
342: }
343:
344: /**
345: * Sets the output writer.
346: */
347: public void setOutput(PrintWriter output) {
348: if (this .output == null) {
349: this .output = new PrintWriter(NullWriter.DEFAULT);
350: } else {
351: this .output = output;
352: }
353: }
354:
355: /**
356: * Gets the target directory for writing classes.
357: */
358: public File getTargetDirectory() {
359: return this .targetDirectory;
360: }
361:
362: /**
363: * Sets the target directory.
364: */
365: public void setTargetDirectory(String directory) {
366: if (directory != null && directory.length() > 0) {
367: this .targetDirectory = new File(directory);
368: } else {
369: this .targetDirectory = null;
370: }
371: }
372:
373: /**
374: * Sets the target directory.
375: */
376: public void setTargetDirectory(File directory) {
377: this .targetDirectory = directory;
378: }
379:
380: /**
381: * Gets the classpath.
382: */
383: public List getClasspath() {
384: return this .classpath;
385: }
386:
387: /**
388: * Sets the classpath.
389: */
390: public void setClasspath(String classpath) {
391: this .classpath = new LinkedList();
392:
393: StringTokenizer tokenizer = new StringTokenizer(classpath,
394: File.pathSeparator);
395: while (tokenizer.hasMoreTokens()) {
396: this .classpath.add(tokenizer.nextToken());
397: }
398: }
399:
400: /**
401: * Returns true if verbose operation has been requested.
402: */
403: public boolean getVerbose() {
404: return this .verbose;
405: }
406:
407: /**
408: * Turns verbose operation on or off.
409: */
410: public void setVerbose(boolean verbose) {
411: this .verbose = verbose;
412: }
413:
414: /**
415: * Returns true if debugging operation has been requested.
416: */
417: public boolean getDebug() {
418: return this .debug;
419: }
420:
421: /**
422: * Turns debugging operation on or off.
423: */
424: public void setDebug(boolean debug) {
425: this .debug = debug;
426: }
427:
428: /**
429: * Returns the requested error tolerance.
430: */
431: public int getTolerance() {
432: return this .tolerance;
433: }
434:
435: /**
436: * Sets the error tolerance, which is the number of
437: * non-fatal errors (per unit) that should be tolerated before
438: * compilation is aborted.
439: */
440: public void setTolerance(int tolerance) {
441: this .tolerance = tolerance;
442: }
443:
444: /**
445: * Gets the name of the base class for scripts. It must be a subclass
446: * of Script.
447: */
448: public String getScriptBaseClass() {
449: return this .scriptBaseClass;
450: }
451:
452: /**
453: * Sets the name of the base class for scripts. It must be a subclass
454: * of Script.
455: */
456: public void setScriptBaseClass(String scriptBaseClass) {
457: this .scriptBaseClass = scriptBaseClass;
458: }
459:
460: /**
461: * Returns true if the new groovy (JSR) parser is enabled
462: */
463: public boolean isUseNewGroovy() {
464: return useNewGroovy;
465: }
466:
467: public void setUseNewGroovy(boolean useNewGroovy) {
468: this .useNewGroovy = useNewGroovy;
469: }
470:
471: public ParserPluginFactory getPluginFactory() {
472: if (pluginFactory == null) {
473: pluginFactory = ParserPluginFactory
474: .newInstance(isUseNewGroovy());
475: }
476: return pluginFactory;
477: }
478:
479: public void setPluginFactory(ParserPluginFactory pluginFactory) {
480: this .pluginFactory = pluginFactory;
481: }
482:
483: /**
484: * Returns true if we are the JSR compatible Groovy language
485: */
486: public static boolean isJsrGroovy() {
487: return jsrGroovy;
488: }
489:
490: /**
491: * Should only be called by the JSR parser
492: */
493: public static void setJsrGroovy(boolean value) {
494: jsrGroovy = value;
495: }
496:
497: protected static boolean getDefaultJsrFlag() {
498: // TODO a temporary hack while we have 2 parsers
499: String property = null;
500: try {
501: property = System.getProperty("groovy.jsr");
502: } catch (Throwable e) {
503: // ignore security warnings
504: }
505: if (property != null) {
506: return "true".equalsIgnoreCase(property);
507: }
508: return DEFAULT_JSR_FLAG;
509: }
510:
511: public String getDefaultScriptExtension() {
512: return defaultScriptExtension;
513: }
514:
515: public void setDefaultScriptExtension(String defaultScriptExtension) {
516: this .defaultScriptExtension = defaultScriptExtension;
517: }
518:
519: public void setRecompileGroovySource(boolean recompile) {
520: recompileGroovySource = recompile;
521: }
522:
523: public boolean getRecompileGroovySource() {
524: return recompileGroovySource;
525: }
526:
527: public void setMinimumRecompilationInterval(int time) {
528: minimumRecompilationInterval = Math.max(0, time);
529: }
530:
531: public int getMinimumRecompilationInterval() {
532: return minimumRecompilationInterval;
533: }
534:
535: }
|