diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java
index ced196559..ea7b46249 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/CheckStyleTask.java
@@ -40,6 +40,8 @@ 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
* of the task for usage.
@@ -319,9 +321,15 @@ public class CheckStyleTask
final Configuration config =
ConfigurationLoader.loadConfiguration(
mConfigFile.getAbsolutePath(), props);
- config.setClassLoader(new AntClassLoader(getProject(),
- mClasspath));
- c = new Checker(config);
+
+ DefaultContext context = new DefaultContext();
+ ClassLoader loader = new AntClassLoader(getProject(), mClasspath);
+ context.add("classloader", loader);
+
+ c = new Checker();
+ c.contextualize(context);
+ c.configure(config);
+
// setup the listeners
AuditListener[] listeners = getListeners();
for (int i = 0; i < listeners.length; i++) {
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
index 5a2209ebc..e5cf2e116 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
@@ -18,22 +18,25 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
-import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
-import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
-import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
+import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
+import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
+import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
+import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+
/**
* This class provides the functionality to check a set of files.
* @author Oliver Burn
* @author Stephane Bailliez
* @author lkuehne
*/
-public class Checker
+public class Checker extends AutomaticBean
implements Defn, MessageDispatcher
{
/**
@@ -89,73 +92,81 @@ public class Checker
/** maintains error count */
private final ErrorCounter mCounter = new ErrorCounter();
- /** configuration */
- private final GlobalProperties mConfig;
-
/** vector of listeners */
private final ArrayList mListeners = new ArrayList();
/** vector of fileset checks */
private final ArrayList mFileSetChecks = new ArrayList();
- /**
- * Creates a new Checker instance.
- *
- * @param aConfig the configuration to use
- * @throws CheckstyleException if an error occurs
- */
- public Checker(Configuration aConfig)
- throws CheckstyleException
+ /** class loader to resolve classes with. **/
+ private ClassLoader mLoader =
+ Thread.currentThread().getContextClassLoader();
+
+ /** the basedir to strip off in filenames */
+ private String mBasedir;
+
+ public void setLocaleCountry(String aLocaleCountry)
{
- this(aConfig.getGlobalProperties(), aConfig.getCheckConfigurations());
+ mLocaleCountry = aLocaleCountry;
}
+ public void setLocaleLanguage(String aLocaleLanguage)
+ {
+ mLocaleLanguage = aLocaleLanguage;
+ }
+
+ /** locale country to report messages **/
+ private String mLocaleCountry = Locale.getDefault().getCountry();
+ /** locale language to report messages **/
+ private String mLocaleLanguage = Locale.getDefault().getLanguage();
+
/**
* Creates a new Checker instance.
+ * The instance needs to be contextualized and configured.
*
- * @param aConfig the configuration to use
- * @param aConfigs the configuation of the checks to use
* @throws CheckstyleException if an error occurs
*/
- public Checker(GlobalProperties aConfig, CheckConfiguration[] aConfigs)
+ public Checker()
throws CheckstyleException
{
- mConfig = aConfig;
- LocalizedMessage.setLocale(new Locale(mConfig.getLocaleLanguage(),
- mConfig.getLocaleCountry()));
-
- // TODO: create, configure and register the FileSetChecks from config
- // file instead of hardcoding it here in the Checker constructor.
- // Probably the addFileSetCheck mthod must be called from outside
- // the checker, just like the TreeWalker is not concerned with
- // finding all the checks it has to execute (IOC principle).
-
- // TODO: uncommenting the addFileSetCheck calls breaks the tests
- // because the packageHtml check is always executed and yields
- // additional errors that are not expected in the current test code
- // (which should stay like it currently is!)
-
- //FileSetCheck translationCheck = new TranslationCheck();
- // addFileSetCheck(translationCheck);
-
- //FileSetCheck packageHtmlCheck = new PackageHtmlCheck();
- // addFileSetCheck(packageHtmlCheck);
-
- final TreeWalker walker = new TreeWalker(mConfig);
- // TODO: improve the error handing
- for (int i = 0; i < aConfigs.length; i++) {
- final CheckConfiguration config = aConfigs[i];
- // IMPORTANT! Need to use the same class loader that created this
- // class. Otherwise can get ClassCastException problems.
- walker.registerCheck(
- config.createInstance(this.getClass().getClassLoader()),
- config);
- }
- addFileSetCheck(walker);
-
this.addListener(mCounter);
}
+ /** @see AutomaticBean */
+ public void configure(Configuration aConfiguration)
+ throws CheckstyleException
+ {
+ super.configure(aConfiguration);
+
+ final Locale locale = new Locale(mLocaleLanguage, mLocaleCountry);
+ LocalizedMessage.setLocale(locale);
+
+ DefaultContext context = new DefaultContext();
+ context.add("classLoader", this.getClassLoader());
+ Configuration[] fileSetChecks = aConfiguration.getChildren();
+ for (int i = 0; i < fileSetChecks.length; i++) {
+ Configuration fscConf = fileSetChecks[i];
+ String className = fscConf.getAttribute("classname");
+ try {
+ Class clazz = Class.forName(className);
+ FileSetCheck fsc = (FileSetCheck) clazz.newInstance();
+ fsc.contextualize(context);
+ fsc.configure(fscConf);
+ addFileSetCheck(fsc);
+ }
+ catch (Exception ex) {
+ // TODO i18n
+ throw new CheckstyleException(
+ "cannot initialize filesetcheck of class " + className);
+ }
+ }
+ }
+
+ private ClassLoader getClassLoader()
+ {
+ return mLoader;
+ }
+
/**
* Adds a FileSetCheck to the list of FileSetChecks
* that is executed in process().
@@ -211,18 +222,21 @@ public class Checker
private String getStrippedFileName(final String aFileName)
{
final String stripped;
- final String basedir = mConfig.getBasedir();
- if ((basedir == null) || !aFileName.startsWith(basedir)) {
+ if ((mBasedir == null) || !aFileName.startsWith(mBasedir)) {
stripped = aFileName;
}
else {
// making the assumption that there is text after basedir
- final int skipSep = basedir.endsWith(File.separator) ? 0 : 1;
- stripped = aFileName.substring(basedir.length() + skipSep);
+ final int skipSep = mBasedir.endsWith(File.separator) ? 0 : 1;
+ stripped = aFileName.substring(mBasedir.length() + skipSep);
}
return stripped;
}
+ public void setBasedir(String aBasedir)
+ {
+ mBasedir = aBasedir;
+ }
/** notify all listeners about the audit start */
protected void fireAuditStarted()
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java
index 62e6cc106..26f60b150 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java
@@ -21,14 +21,12 @@ package com.puppycrawl.tools.checkstyle;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.Properties;
-
+import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
-import org.apache.regexp.RESyntaxException;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -51,20 +49,10 @@ class ConfigurationLoader
private Properties mOverrideProps = new Properties();
/** parser to read XML files **/
private final XMLReader mParser;
- /** the loaded global properties **/
- private final Properties mProps = new Properties();
- /** the loaded configurations **/
- private final ArrayList mCheckConfigs = new ArrayList();
/** the loaded configuration **/
- private Configuration mConfig = null;
- /** the current check configuration being created **/
- private CheckConfiguration mCurrent;
- /** buffer for collecting text **/
- private final StringBuffer mBuf = new StringBuffer();
- /** in global element **/
- private boolean mIsInGlobalElement = false;
- /** started processing check configurations **/
- private boolean mIsInCheckMode = false;
+ private Stack mConfigStack = new Stack();
+ /** the Configuration that is beeing built */
+ private Configuration mConfiguration = null;
/**
* Creates a new ConfigurationLoader instance.
@@ -91,71 +79,50 @@ class ConfigurationLoader
mParser.parse(new InputSource(new FileReader(aFilename)));
}
- /**
- * Returns the configuration information in the last file parsed.
- * @return list of CheckConfiguration objects
- */
- CheckConfiguration[] getConfigs()
- {
- return (CheckConfiguration[]) mCheckConfigs.toArray(
- new CheckConfiguration[mCheckConfigs.size()]);
- }
-
-
///////////////////////////////////////////////////////////////////////////
// Document handler methods
///////////////////////////////////////////////////////////////////////////
- /** @see org.xml.sax.helpers.DefaultHandler **/
- public void characters(char[] aChars, int aStart, int aLength)
- {
- mBuf.append(String.valueOf(aChars, aStart, aLength));
- }
-
/** @see org.xml.sax.helpers.DefaultHandler **/
public void startElement(String aNamespaceURI,
String aLocalName,
String aQName,
Attributes aAtts)
+ throws SAXException
{
- mBuf.setLength(0);
- if ("global".equals(aQName)) {
- mIsInGlobalElement = true;
- }
- else if ("check".equals(aQName)) {
- //first apply overriding properties
- if (!mIsInCheckMode) {
- mIsInCheckMode = true;
- for (Enumeration enum = mOverrideProps.keys();
- enum.hasMoreElements();)
- {
- final String key = (String) enum.nextElement();
- final String value = (String) mOverrideProps.get(key);
- mProps.setProperty(key, value);
+ // TODO: debug logging for support puposes
+ DefaultConfiguration conf = new DefaultConfiguration(aQName);
+ System.out.println("aQName = " + aQName);
+ final int attCount = aAtts.getLength();
+ for (int i = 0; i < attCount; i++) {
+ String name = aAtts.getQName(i);
+ String value = aAtts.getValue(i);
+ System.out.println(" value of " + name + " is " + value);
+
+ // expand properties
+ if (value.startsWith("${") && value.endsWith("}")) {
+ String propName = value.substring(2, value.length() - 1);
+ value = mOverrideProps.getProperty(propName);
+ if (value == null) {
+ throw new SAXException("missing external property " + propName);
}
+ System.out.println(" propName = " + propName);
+ System.out.println(" new value = " + value);
}
- mCurrent = new CheckConfiguration();
- mCurrent.setClassname(aAtts.getValue("classname"));
- }
- else if ("property".equals(aQName)) {
- final String name = aAtts.getValue("name");
- String value = aAtts.getValue("value");
-
- if (value == null) {
- //try global
- String globalKey = aAtts.getValue("from-global");
- value = (String) mProps.get(globalKey);
- }
-
- if (mIsInGlobalElement) {
- mProps.setProperty(name, value);
- }
- else {
- mCurrent.addProperty(name, value);
- }
+ conf.addAttribute(name, value);
}
+ if (mConfiguration == null) {
+ mConfiguration = conf;
+ }
+
+ if (!mConfigStack.isEmpty()) {
+ DefaultConfiguration top = (DefaultConfiguration) mConfigStack.peek();
+ top.addChild(conf);
+ }
+
+ mConfigStack.push(conf);
}
/** @see org.xml.sax.helpers.DefaultHandler **/
@@ -163,44 +130,7 @@ class ConfigurationLoader
String aLocalName,
String aQName)
{
- if ("global".equals(aQName)) {
- mIsInGlobalElement = false;
- }
- else if ("check".equals(aQName)) {
- mCheckConfigs.add(mCurrent);
- mCurrent = null;
- }
- else if ("tokens".equals(aQName)) {
- mCurrent.addTokens(mBuf.toString());
- }
- }
-
- /**
- * Returns the check configurations in a specified file.
- * @param aConfigFname name of config file
- * @return the check configurations
- * @throws CheckstyleException if an error occurs
- */
- public static CheckConfiguration[] loadConfigs(String aConfigFname)
- throws CheckstyleException
- {
- try {
- final ConfigurationLoader loader = new ConfigurationLoader();
- loader.parseFile(aConfigFname);
- return loader.getConfigs();
- }
- catch (FileNotFoundException e) {
- throw new CheckstyleException("unable to find " + aConfigFname);
- }
- catch (ParserConfigurationException e) {
- throw new CheckstyleException("unable to parse " + aConfigFname);
- }
- catch (SAXException e) {
- throw new CheckstyleException("unable to parse " + aConfigFname);
- }
- catch (IOException e) {
- throw new CheckstyleException("unable to read " + aConfigFname);
- }
+ mConfigStack.pop();
}
/**
@@ -227,32 +157,20 @@ class ConfigurationLoader
throw new CheckstyleException("unable to parse " + aConfigFname);
}
catch (SAXException e) {
- throw new CheckstyleException("unable to parse " + aConfigFname);
+ throw new CheckstyleException("unable to parse "
+ + aConfigFname + " - " + e.getMessage());
}
catch (IOException e) {
throw new CheckstyleException("unable to read " + aConfigFname);
}
- catch (RESyntaxException e) {
- throw new CheckstyleException(
- "A regular expression error exists in " + aConfigFname);
- }
}
/**
* Returns the configuration in the last file parsed.
* @return Configuration object
- * @throws RESyntaxException if an error occurs
- * @throws FileNotFoundException if an error occurs
- * @throws IOException if an error occurs
*/
private Configuration getConfiguration()
- throws IOException, FileNotFoundException, RESyntaxException
{
- final GlobalProperties globalProps =
- new GlobalProperties(mProps, System.out);
- final CheckConfiguration[] checkConfigs =
- (CheckConfiguration[]) mCheckConfigs.toArray(
- new CheckConfiguration[mCheckConfigs.size()]);
- return new Configuration(globalProps, checkConfigs);
+ return mConfiguration;
}
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Defn.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Defn.java
index 6615c8831..be58e8d06 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Defn.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Defn.java
@@ -28,32 +28,4 @@ public interface Defn
// TODO: Change to a class - follow the advice of Bloch.
/** name of resource bundle for Checkstyle */
String CHECKSTYLE_BUNDLE = "com.puppycrawl.tools.checkstyle.messages";
-
- /** property name for allowing protected data **/
- String TAB_WIDTH_PROP = "checkstyle.tab.width";
- /** property name for cache file **/
- String CACHE_FILE_PROP = "checkstyle.cache.file";
-
- /** property name for the base directory **/
- String BASEDIR_PROP = "checkstyle.basedir";
-
- /** property name for the locale language for reporting **/
- String LOCALE_LANGUAGE_PROP = "checkstyle.locale.language";
- /** property name for the locale country for reporting **/
- String LOCALE_COUNTRY_PROP = "checkstyle.locale.country";
-
- /** All the integer properties */
- String[] ALL_INT_PROPS = new String[]
- {
- TAB_WIDTH_PROP,
- };
-
- /** All the String properties */
- String[] ALL_STRING_PROPS = new String[]
- {
- BASEDIR_PROP,
- CACHE_FILE_PROP,
- LOCALE_COUNTRY_PROP,
- LOCALE_LANGUAGE_PROP,
- };
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Main.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Main.java
index a4199964e..94d19164e 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Main.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Main.java
@@ -34,6 +34,7 @@ import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
@@ -86,24 +87,11 @@ public final class Main
usage();
}
- // Load the config file
-// CheckConfiguration[] checkConfigs = null;
-// try {
-// checkConfigs =
-// ConfigurationLoader.loadConfigs(line.getOptionValue("c"));
-// }
-// catch (CheckstyleException e) {
-// System.out.println("Error loading configuration file");
-// e.printStackTrace(System.out);
-// System.exit(1);
-// }
-
// Load the config file
Configuration config = null;
try {
- config =
- ConfigurationLoader.loadConfiguration(line.getOptionValue("c"),
- props);
+ config = ConfigurationLoader.loadConfiguration(
+ line.getOptionValue("c"), props);
}
catch (CheckstyleException e) {
System.out.println("Error loading configuration file");
@@ -166,24 +154,11 @@ public final class Main
usage();
}
-// // create the checker
-// Checker c = null;
-// try {
-// c = new Checker(new GlobalProperties(props, System.out),
-// checkConfigs);
-// c.addListener(listener);
-// }
-// catch (Exception e) {
-// System.out.println("Unable to create Checker: "
-// + e.getMessage());
-// e.printStackTrace(System.out);
-// System.exit(1);
-// }
-
// create the checker
Checker c = null;
try {
- c = new Checker(config);
+ c = new Checker();
+ c.configure(config);
c.addListener(listener);
}
catch (Exception e) {
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java
index 1690790b6..54bd245a7 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java
@@ -24,13 +24,16 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.util.Properties;
import java.security.MessageDigest;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
+
/**
* This class maintains a persistent store of the files that have
* checked ok and their associated timestamp. It uses a property file
- * for storage. A hashcode of the GlobalProperties is stored in the
+ * for storage. A hashcode of the Configuration is stored in the
* cache file to ensure the cache is invalidated when the
* configuration has changed.
*
@@ -56,10 +59,10 @@ class PropertyCacheFile
*
* @param aCurrentConfig the current configuration, not null
*/
- PropertyCacheFile(GlobalProperties aCurrentConfig)
+ PropertyCacheFile(Configuration aCurrentConfig, String aFileName)
{
boolean setInActive = true;
- final String fileName = aCurrentConfig.getCacheFile();
+ final String fileName = aFileName;
if (fileName != null) {
try {
mDetails.load(new FileInputStream(fileName));
@@ -79,6 +82,7 @@ class PropertyCacheFile
setInActive = false;
}
catch (IOException e) {
+ // TODO: use logger
System.out.println("Unable to open cache file, ignoring.");
e.printStackTrace(System.out);
}
@@ -128,10 +132,10 @@ class PropertyCacheFile
* @param aConfiguration the GlobalProperties
* @return the hashcode for aConfiguration
*/
- private String getConfigHashCode(GlobalProperties aConfiguration)
+ private String getConfigHashCode(Serializable aConfiguration)
{
try {
- // im-memory serialization of GlobalProperties
+ // im-memory serialization of Configuration
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
index 8662925d1..7c3d3892b 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
@@ -18,29 +18,30 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
-import com.puppycrawl.tools.checkstyle.api.Check;
-import com.puppycrawl.tools.checkstyle.api.DetailAST;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
-import com.puppycrawl.tools.checkstyle.api.TokenTypes;
-import com.puppycrawl.tools.checkstyle.api.FileContents;
-import com.puppycrawl.tools.checkstyle.api.Utils;
-import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
-import com.puppycrawl.tools.checkstyle.checks.AbstractFileSetCheck;
-
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import java.util.Arrays;
-import java.io.Reader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
import antlr.RecognitionException;
import antlr.TokenStreamException;
+import com.puppycrawl.tools.checkstyle.api.Check;
+import com.puppycrawl.tools.checkstyle.api.Configuration;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FileContents;
+import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
+import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+import com.puppycrawl.tools.checkstyle.api.Utils;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+import com.puppycrawl.tools.checkstyle.checks.AbstractFileSetCheck;
/**
* Responsible for walking an abstract syntax tree and notifying interested
@@ -105,27 +106,72 @@ public final class TreeWalker
private final Set mAllChecks = new HashSet();
/** collects the error messages */
private final LocalizedMessages mMessages;
- /** the tab width for error reporting */
- private final int mTabWidth;
+ /** the distance between tab stops */
+ private int mTabWidth = 8;
/** cache file **/
- private final PropertyCacheFile mCache;
+ private PropertyCacheFile mCache = new PropertyCacheFile(null, null);
+
/**
* the global configuration.
* TODO: should only know the treewalker part of the config
*/
- private final GlobalProperties mConfig;
+ private Configuration mConfig;
+
+ private ClassLoader mClassLoader;
/**
* Creates a new TreeWalker instance.
- *
- * @param aConfig the configuration to use
*/
- public TreeWalker(GlobalProperties aConfig)
+ public TreeWalker()
{
mMessages = new LocalizedMessages();
- mConfig = aConfig;
- mTabWidth = aConfig.getTabWidth();
- mCache = new PropertyCacheFile(aConfig);
+ }
+
+ /** sets the distance between tab stops */
+ public void setTabWidth(int aTabWidth)
+ {
+ mTabWidth = aTabWidth;
+ }
+
+ public void setCacheFile(String aFileName)
+ {
+ mCache = new PropertyCacheFile(mConfig, aFileName);
+ }
+
+ // TODO: Call from contextualize
+ public void setClassLoader(ClassLoader aClassLoader)
+ {
+ mClassLoader = aClassLoader;
+ }
+
+ public void configure(Configuration aConfiguration)
+ throws CheckstyleException
+ {
+ super.configure(aConfiguration);
+ mConfig = aConfiguration;
+
+ DefaultContext checkContext = new DefaultContext();
+ checkContext.add("classLoader", mClassLoader);
+ checkContext.add("messages", mMessages);
+ // TODO: hmmm.. this looks less than elegant
+ checkContext.add("tabWidth", String.valueOf(mTabWidth));
+
+ // TODO: improve the error handing
+ Configuration[] checkConfigs = aConfiguration.getChildren();
+ for (int i = 0; i < checkConfigs.length; i++) {
+ final Configuration config = checkConfigs[i];
+ // IMPORTANT! Need to use the same class loader that created this
+ // class. Otherwise can get ClassCastException problems.
+ final String className = config.getAttribute("classname");
+ final Check check = createCheck(
+ this.getClass().getClassLoader(), className);
+
+ check.contextualize(checkContext);
+ check.configure(config);
+
+ registerCheck(check);
+ }
+
}
/**
@@ -147,7 +193,7 @@ public final class TreeWalker
final String[] lines = Utils.getLines(fileName);
final FileContents contents = new FileContents(fileName, lines);
final DetailAST rootAST = TreeWalker.parse(contents);
- walk(rootAST, contents, mConfig.getClassLoader());
+ walk(rootAST, contents);
}
catch (FileNotFoundException fnfe) {
mMessages.add(new LocalizedMessage(0, Defn.CHECKSTYLE_BUNDLE,
@@ -184,16 +230,15 @@ public final class TreeWalker
/**
* Register a check for a given configuration.
* @param aCheck the check to register
- * @param aConfig the configuration to use
*/
- void registerCheck(Check aCheck, CheckConfiguration aConfig)
+ void registerCheck(Check aCheck)
+ throws CheckstyleException
{
- aCheck.setMessages(mMessages);
- aCheck.setTabWidth(mTabWidth);
- if (!aConfig.getTokens().isEmpty()) {
+ final Set checkTokens = aCheck.getTokens();
+ if (!checkTokens.isEmpty()) {
int acceptableTokens[] = aCheck.getAcceptableTokens();
Arrays.sort(acceptableTokens);
- final Iterator it = aConfig.getTokens().iterator();
+ final Iterator it = checkTokens.iterator();
while (it.hasNext()) {
String token = (String) it.next();
int tokenId = TokenTypes.getTokenId(token);
@@ -242,12 +287,11 @@ public final class TreeWalker
* Initiates the walk of an AST.
* @param aAST the root AST
* @param aContents the contents of the file the AST was generated from
- * @param aLoader the class loader for resolving classes
*/
- void walk(DetailAST aAST, FileContents aContents, ClassLoader aLoader)
+ private void walk(DetailAST aAST, FileContents aContents)
{
mMessages.reset();
- notifyBegin(aContents, aLoader);
+ notifyBegin(aContents);
// empty files are not flagged by javac, will yield aAST == null
if (aAST != null) {
@@ -261,9 +305,8 @@ public final class TreeWalker
/**
* Notify interested checks that about to begin walking a tree.
* @param aContents the contents of the file the AST was generated from
- * @param aLoader the class loader for resolving classes
*/
- private void notifyBegin(FileContents aContents, ClassLoader aLoader)
+ private void notifyBegin(FileContents aContents)
{
// TODO: do not track Context properly for token
final Iterator it = mAllChecks.iterator();
@@ -272,7 +315,6 @@ public final class TreeWalker
final HashMap treeContext = new HashMap();
check.setTreeContext(treeContext);
check.setFileContents(aContents);
- check.setClassLoader(aLoader);
check.beginTree();
}
}
@@ -355,7 +397,7 @@ public final class TreeWalker
}
/**
- *
+ * Static helper method to parses a Java source file.
* @param aContents contains the contents of the file
* @return the root of the AST
* @throws TokenStreamException if lexing failed
@@ -418,4 +460,37 @@ public final class TreeWalker
super.destroy();
mCache.destroy();
}
+
+ /**
+ * Create an instance of the check that is properly initialised.
+ *
+ * @param aLoader the ClassLoader to create the instance with
+ * @return the created check
+ * @throws CheckstyleException if an error occurs
+ */
+ private Check createCheck(
+ ClassLoader aLoader, String aClassName)
+ throws CheckstyleException
+ {
+ try {
+ final Class clazz = Class.forName(aClassName, true, aLoader);
+ final Check check = (Check) clazz.newInstance();
+ return check;
+ }
+ catch (ClassNotFoundException e) {
+ throw new CheckstyleException(
+ "Unable to find class for " + aClassName);
+ }
+ catch (InstantiationException e) {
+ throw new CheckstyleException(
+ "Unable to instantiate " + aClassName);
+ }
+ catch (IllegalAccessException e) {
+ throw new CheckstyleException(
+ "Unable to instantiate " + aClassName);
+ }
+ }
+
+
+
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
index 2e4203155..855dcdc01 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
@@ -18,7 +18,9 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.api;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* The base class for checks.
@@ -26,18 +28,18 @@ import java.util.Map;
* @author Oliver Burn
* @version 1.0
*/
-public abstract class Check
+public abstract class Check extends AutomaticBean
{
/** resuable constant for message formating */
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/** name to store file contents under */
private static final String FILE_CONTENTS_ATTRIBUTE = "fILEcONTENTS";
- /** name to store class loader under */
- private static final String CLASS_LOADER_ATTRIBUTE = "cLaSsLoAdEr";
/** the global context for the check */
private Map mGlobalContext;
+ /** the tokens the check is interested in */
+ private final Set mTokens = new HashSet();
/**
* the object for collecting messages. decided to not put in the global
* context for performance and ease of use.
@@ -50,6 +52,8 @@ public abstract class Check
/** the tab with for column reporting */
private int mTabWidth = 8; // meaningful default
+ private ClassLoader mLoader = Thread.currentThread().getContextClassLoader();
+
/**
* Returns the default token a check is interested in. Only used if the
* configuration for a check does not define the tokens.
@@ -84,6 +88,27 @@ public abstract class Check
//
// Lets worry about it when it becomes a problem.
+ /**
+ * Adds a set of tokens the check is interested in.
+ * @param aStrRep the string representation of the tokens interested in
+ */
+ final public void setTokens(String[] aStrRep)
+ {
+ for (int i = 0; i < aStrRep.length; i++) {
+ String s = aStrRep[i];
+ mTokens.add(s);
+ }
+ }
+
+ /**
+ * Returns the tokens registered for the check.
+ * @return the set of token names
+ */
+ final public Set getTokens()
+ {
+ return mTokens;
+ }
+
/**
* Return the global context object for check. This context is valid for
@@ -231,7 +256,7 @@ public abstract class Check
*/
public final void setClassLoader(ClassLoader aLoader)
{
- getTreeContext().put(CLASS_LOADER_ATTRIBUTE, aLoader);
+ mLoader = aLoader;
}
/**
@@ -240,7 +265,7 @@ public abstract class Check
*/
public final ClassLoader getClassLoader()
{
- return (ClassLoader) getTreeContext().get(CLASS_LOADER_ATTRIBUTE);
+ return mLoader;
}
/** @return the tab width to report errors with */
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FileSetCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FileSetCheck.java
index 0cc55a370..8436f574e 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FileSetCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FileSetCheck.java
@@ -25,7 +25,7 @@ import java.io.File;
*
* @author lkuehne
*/
-public interface FileSetCheck
+public interface FileSetCheck extends Configurable, Contextualizable
{
/**
* Sets the MessageDispatcher that is used to dispatch error
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AbstractFileSetCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AbstractFileSetCheck.java
index 9405947f7..d13a04896 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AbstractFileSetCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AbstractFileSetCheck.java
@@ -24,6 +24,7 @@ import java.io.File;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
+import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
/**
* Provides common functionality for many FileSetChecks.
@@ -34,7 +35,8 @@ import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
*
* @author lkuehne
*/
-public abstract class AbstractFileSetCheck implements FileSetCheck
+public abstract class AbstractFileSetCheck
+ extends AutomaticBean implements FileSetCheck
{
/** The dispatcher errors are fired to. */
private MessageDispatcher mDispatcher = null;
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java
index c22826221..b1e5a241f 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java
@@ -210,7 +210,7 @@ public class TranslationCheck extends AbstractFileSetCheck
for (Iterator it = keysClone.iterator(); it.hasNext();) {
Object[] key = new Object[]{it.next()};
LocalizedMessage[] errors = new LocalizedMessage[1];
- final String bundle = getClass().getName() + ".messages";
+ final String bundle = getClass().getPackage().getName() + ".messages";
errors[0] = new LocalizedMessage(
0, bundle, "translation.missingKey", key);
getMessageDispatcher().fireErrors(path, errors);