diff --git a/docs/anttask.html b/docs/anttask.html index 56e53981b..3a479e3de 100644 --- a/docs/anttask.html +++ b/docs/anttask.html @@ -57,6 +57,8 @@ This task is included in the checkstyle distribution.

Specifies a file that contains properties for expanded property values of the configuration. + Ant properties (like ${basedir}) and nested property elements override + the properties in this file. No diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java index fccbd5280..dd5a5358d 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java @@ -18,6 +18,19 @@ //////////////////////////////////////////////////////////////////////////////// package com.puppycrawl.tools.checkstyle; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Hashtable; + +import com.puppycrawl.tools.checkstyle.api.Configuration; import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -27,20 +40,6 @@ import org.apache.tools.ant.taskdefs.LogOutputStream; import org.apache.tools.ant.types.EnumeratedAttribute; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; -//import org.apache.regexp.RESyntaxException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.Iterator; - -import com.puppycrawl.tools.checkstyle.api.Configuration; /** * An implementation of a ANT task for calling checkstyle. See the documentation @@ -267,7 +266,7 @@ public class CheckStyleTask /** * Create the Properties object based on the arguments specified * to the ANT task. - * @return Properties object + * @return the properties for property expansion expansion * @throws BuildException if an error occurs */ private Properties createOverridingProperties() @@ -306,7 +305,15 @@ public class CheckStyleTask } } - // Now override the properties specified + // override with Ant properties like ${basedir} + Hashtable antProps = this.getProject().getProperties(); + for (Iterator it = antProps.keySet().iterator(); it.hasNext();) { + final String key = (String) it.next(); + final String value = String.valueOf(antProps.get(key)); + retVal.put(key, value); + } + + // override with properties specified in subelements for (Iterator it = mOverrideProps.iterator(); it.hasNext();) { final Property p = (Property) it.next(); retVal.put(p.getKey(), p.getValue()); diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java index 6ac8acce6..bc6eae7b2 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java @@ -18,15 +18,18 @@ //////////////////////////////////////////////////////////////////////////////// package com.puppycrawl.tools.checkstyle; -import com.puppycrawl.tools.checkstyle.api.CheckstyleException; -import com.puppycrawl.tools.checkstyle.api.Configuration; -import com.puppycrawl.tools.checkstyle.api.Utils; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.Properties; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Stack; +import java.util.Properties; import javax.xml.parsers.ParserConfigurationException; + +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; +import com.puppycrawl.tools.checkstyle.api.Configuration; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -115,8 +118,8 @@ class ConfigurationLoader final String name = aAtts.getValue("name"); final String value; try { - value = Utils.replaceProperties(aAtts.getValue("value"), - mOverrideProps); + value = replaceProperties(aAtts.getValue("value"), + mOverrideProps); } catch (CheckstyleException ex) { throw new SAXException(ex.getMessage()); @@ -179,4 +182,138 @@ class ConfigurationLoader { return mConfiguration; } + + /** + * Replaces ${xxx} style constructions in the given value + * with the string value of the corresponding data types. + * + * The method is package visible to facilitate testing. + * + * @param aValue The string to be scanned for property references. + * May be null, in which case this + * method returns immediately with no effect. + * @param aProps Mapping (String to String) of property names to their + * values. Must not be null. + * + * @throws CheckstyleException if the string contains an opening + * ${ without a closing + * } + * @return the original string with the properties replaced, or + * null if the original string is null. + * + * Code copied from ant - + * http://cvs.apache.org/viewcvs/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java + */ + static String replaceProperties( + String aValue, Properties aProps) + throws CheckstyleException + { + if (aValue == null) { + return null; + } + + final List fragments = new ArrayList(); + final List propertyRefs = new ArrayList(); + parsePropertyString(aValue, fragments, propertyRefs); + + final StringBuffer sb = new StringBuffer(); + final Iterator i = fragments.iterator(); + final Iterator j = propertyRefs.iterator(); + while (i.hasNext()) { + String fragment = (String) i.next(); + if (fragment == null) { + final String propertyName = (String) j.next(); + if (!aProps.containsKey(propertyName)) { + throw new CheckstyleException("Property ${" + + propertyName + "} has not been set"); + } + fragment = aProps.getProperty(propertyName); + } + sb.append(fragment); + } + + return sb.toString(); + } + + /** + * Parses a string containing ${xxx} style property + * references into two lists. The first list is a collection + * of text fragments, while the other is a set of string property names. + * null entries in the first list indicate a property + * reference from the second list. + * + * @param aValue Text to parse. Must not be null. + * @param aFragments List to add text fragments to. + * Must not be null. + * @param aPropertyRefs List to add property names to. + * Must not be null. + * + * @throws CheckstyleException if the string contains an opening + * ${ without a closing + * } + * Code copied from ant - + * http://cvs.apache.org/viewcvs/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java + */ + private static void parsePropertyString(String aValue, + List aFragments, + List aPropertyRefs) + throws CheckstyleException + { + int prev = 0; + int pos; + //search for the next instance of $ from the 'prev' position + while ((pos = aValue.indexOf("$", prev)) >= 0) { + + //if there was any text before this, add it as a fragment + //TODO, this check could be modified to go if pos>prev; + //seems like this current version could stick empty strings + //into the list + if (pos > 0) { + aFragments.add(aValue.substring(prev, pos)); + } + //if we are at the end of the string, we tack on a $ + //then move past it + if (pos == (aValue.length() - 1)) { + aFragments.add("$"); + prev = pos + 1; + } + else if (aValue.charAt(pos + 1) != '{') { + //peek ahead to see if the next char is a property or not + //not a property: insert the char as a literal + /* + fragments.addElement(value.substring(pos + 1, pos + 2)); + prev = pos + 2; + */ + if (aValue.charAt(pos + 1) == '$') { + //backwards compatibility two $ map to one mode + aFragments.add("$"); + prev = pos + 2; + } + else { + //new behaviour: $X maps to $X for all values of X!='$' + aFragments.add(aValue.substring(pos, pos + 2)); + prev = pos + 2; + } + + } + else { + //property found, extract its name or bail on a typo + final int endName = aValue.indexOf('}', pos); + if (endName < 0) { + throw new CheckstyleException("Syntax error in property: " + + aValue); + } + final String propertyName = aValue.substring(pos + 2, endName); + aFragments.add(null); + aPropertyRefs.add(propertyName); + prev = endName + 1; + } + } + //no more $ signs found + //if there is any tail to the file, append it + if (prev < aValue.length()) { + aFragments.add(aValue.substring(prev)); + } + } + } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Utils.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Utils.java index 0c0d439e7..d781533e2 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Utils.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Utils.java @@ -24,10 +24,8 @@ import java.io.IOException; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.Properties; + import org.apache.commons.beanutils.ConversionException; import org.apache.regexp.RE; import org.apache.regexp.RESyntaxException; @@ -175,135 +173,4 @@ public final class Utils return retVal; } - /** - * Replaces ${xxx} style constructions in the given value - * with the string value of the corresponding data types. - * - * @param aValue The string to be scanned for property references. - * May be null, in which case this - * method returns immediately with no effect. - * @param aProps Mapping (String to String) of property names to their - * values. Must not be null. - * - * @throws CheckstyleException if the string contains an opening - * ${ without a closing - * } - * @return the original string with the properties replaced, or - * null if the original string is null. - * - * Code copied from ant - - * http://cvs.apache.org/viewcvs/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java - */ - public static String replaceProperties(String aValue, Properties aProps) - throws CheckstyleException - { - if (aValue == null) { - return null; - } - - final List fragments = new ArrayList(); - final List propertyRefs = new ArrayList(); - parsePropertyString(aValue, fragments, propertyRefs); - - final StringBuffer sb = new StringBuffer(); - final Iterator i = fragments.iterator(); - final Iterator j = propertyRefs.iterator(); - while (i.hasNext()) { - String fragment = (String) i.next(); - if (fragment == null) { - final String propertyName = (String) j.next(); - if (!aProps.containsKey(propertyName)) { - throw new CheckstyleException("Property ${" - + propertyName + "} has not been set"); - } - fragment = (aProps.containsKey(propertyName)) - ? (String) aProps.get(propertyName) - : "${" + propertyName + "}"; - } - sb.append(fragment); - } - - return sb.toString(); - } - - /** - * Parses a string containing ${xxx} style property - * references into two lists. The first list is a collection - * of text fragments, while the other is a set of string property names. - * null entries in the first list indicate a property - * reference from the second list. - * - * @param aValue Text to parse. Must not be null. - * @param aFragments List to add text fragments to. - * Must not be null. - * @param aPropertyRefs List to add property names to. - * Must not be null. - * - * @throws CheckstyleException if the string contains an opening - * ${ without a closing - * } - * Code copied from ant - - * http://cvs.apache.org/viewcvs/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java - */ - public static void parsePropertyString(String aValue, - List aFragments, - List aPropertyRefs) - throws CheckstyleException - { - int prev = 0; - int pos; - //search for the next instance of $ from the 'prev' position - while ((pos = aValue.indexOf("$", prev)) >= 0) { - - //if there was any text before this, add it as a fragment - //TODO, this check could be modified to go if pos>prev; - //seems like this current version could stick empty strings - //into the list - if (pos > 0) { - aFragments.add(aValue.substring(prev, pos)); - } - //if we are at the end of the string, we tack on a $ - //then move past it - if (pos == (aValue.length() - 1)) { - aFragments.add("$"); - prev = pos + 1; - } - else if (aValue.charAt(pos + 1) != '{') { - //peek ahead to see if the next char is a property or not - //not a property: insert the char as a literal - /* - fragments.addElement(value.substring(pos + 1, pos + 2)); - prev = pos + 2; - */ - if (aValue.charAt(pos + 1) == '$') { - //backwards compatibility two $ map to one mode - aFragments.add("$"); - prev = pos + 2; - } - else { - //new behaviour: $X maps to $X for all values of X!='$' - aFragments.add(aValue.substring(pos, pos + 2)); - prev = pos + 2; - } - - } - else { - //property found, extract its name or bail on a typo - final int endName = aValue.indexOf('}', pos); - if (endName < 0) { - throw new CheckstyleException("Syntax error in property: " - + aValue); - } - final String propertyName = aValue.substring(pos + 2, endName); - aFragments.add(null); - aPropertyRefs.add(propertyName); - prev = endName + 1; - } - } - //no more $ signs found - //if there is any tail to the file, append it - if (prev < aValue.length()) { - aFragments.add(aValue.substring(prev)); - } - } }