moved property expansion from api package to private method of ConfigurationLoader (bug #670594)

also added property expansion of ANT properties
This commit is contained in:
Lars Kühne 2003-01-28 19:56:24 +00:00
parent 9d11d6a0b0
commit ee2e1a5cb3
4 changed files with 169 additions and 156 deletions

View File

@ -57,6 +57,8 @@ This task is included in the checkstyle distribution.</p>
<td>
Specifies a file that contains properties for <a href="config.html#properties">
expanded property values</a> of the configuration.
Ant properties (like ${basedir}) and nested property elements override
the properties in this file.
</td>
<td class="required">No</td>
</tr>

View File

@ -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());

View File

@ -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 <code>${xxx}</code> 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 <code>null</code>, 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 <code>null</code>.
*
* @throws CheckstyleException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* @return the original string with the properties replaced, or
* <code>null</code> if the original string is <code>null</code>.
*
* 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 <code>${xxx}</code> 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.
* <code>null</code> entries in the first list indicate a property
* reference from the second list.
*
* @param aValue Text to parse. Must not be <code>null</code>.
* @param aFragments List to add text fragments to.
* Must not be <code>null</code>.
* @param aPropertyRefs List to add property names to.
* Must not be <code>null</code>.
*
* @throws CheckstyleException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* 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));
}
}
}

View File

@ -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 <code>${xxx}</code> 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 <code>null</code>, 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 <code>null</code>.
*
* @throws CheckstyleException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* @return the original string with the properties replaced, or
* <code>null</code> if the original string is <code>null</code>.
*
* 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 <code>${xxx}</code> 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.
* <code>null</code> entries in the first list indicate a property
* reference from the second list.
*
* @param aValue Text to parse. Must not be <code>null</code>.
* @param aFragments List to add text fragments to.
* Must not be <code>null</code>.
* @param aPropertyRefs List to add property names to.
* Must not be <code>null</code>.
*
* @throws CheckstyleException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* 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));
}
}
}