diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
index ea7f80742..265467e25 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
@@ -30,6 +30,7 @@ import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.PackageNamesBean;
+import com.puppycrawl.tools.checkstyle.api.Context;
/**
* This class provides the functionality to check a set of files.
@@ -117,6 +118,9 @@ public class Checker extends AutomaticBean
*/
private String[] mPackageNames;
+ /** the context of all child components */
+ private Context mChildContext;
+
/**
* Creates a new Checker instance.
* The instance needs to be contextualized and configured.
@@ -130,37 +134,42 @@ public class Checker extends AutomaticBean
}
/** @see AutomaticBean */
- public void configure(Configuration aConfig)
+ public void finishLocalSetup()
throws CheckstyleException
{
- super.configure(aConfig);
-
final Locale locale = new Locale(mLocaleLanguage, mLocaleCountry);
LocalizedMessage.setLocale(locale);
final DefaultContext context = new DefaultContext();
context.add("classLoader", mLoader);
- final Configuration[] fileSetChecks = aConfig.getChildren();
- for (int i = 0; i < fileSetChecks.length; i++) {
- final Configuration fscConf = fileSetChecks[i];
- final String name = fscConf.getName();
- try {
- final FileSetCheck fsc =
+ mChildContext = context;
+ }
+
+ /**
+ * Instantiates, configures and registers a FileSetCheck
+ * that is specified in the provided configuration.
+ * @see com.puppycrawl.tools.checkstyle.api.AutomaticBean
+ */
+ protected void setupChild(Configuration aChildConf)
+ throws CheckstyleException
+ {
+ final String name = aChildConf.getName();
+ try {
+ final FileSetCheck fsc =
(FileSetCheck) PackageObjectFactory.makeObject(
- getPackageNames(),
- getClass().getClassLoader(),
- name);
- fsc.setPackageNames(getPackageNames());
- fsc.contextualize(context);
- fsc.configure(fscConf);
- addFileSetCheck(fsc);
- }
- catch (Exception ex) {
- // TODO i18n
- throw new CheckstyleException(
- "cannot initialize filesetcheck with name "
- + name + " - " + ex.getMessage());
- }
+ getPackageNames(),
+ getClass().getClassLoader(),
+ name);
+ fsc.setPackageNames(getPackageNames());
+ fsc.contextualize(mChildContext);
+ fsc.configure(aChildConf);
+ addFileSetCheck(fsc);
+ }
+ catch (Exception ex) {
+ // TODO i18n
+ throw new CheckstyleException(
+ "cannot initialize filesetcheck with name "
+ + name + " - " + ex.getMessage());
}
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
index 96a4fe446..1aa5e87a0 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java
@@ -42,6 +42,7 @@ 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.api.AbstractFileSetCheck;
+import com.puppycrawl.tools.checkstyle.api.Context;
/**
* Responsible for walking an abstract syntax tree and notifying interested
@@ -111,15 +112,12 @@ public final class TreeWalker
/** cache file **/
private PropertyCacheFile mCache = new PropertyCacheFile(null, null);
- /**
- * the global configuration.
- * TODO: should only know the treewalker part of the config
- */
- private Configuration mConfig;
-
/** class loader to resolve classes with. **/
private ClassLoader mClassLoader;
+ /** context of child components */
+ private Context mChildContext;
+
/**
* Creates a new TreeWalker instance.
*/
@@ -137,7 +135,8 @@ public final class TreeWalker
/** @param aFileName the cache file */
public void setCacheFile(String aFileName)
{
- mCache = new PropertyCacheFile(mConfig, aFileName);
+ final Configuration configuration = getConfiguration();
+ mCache = new PropertyCacheFile(configuration, aFileName);
}
// TODO: Call from contextualize
@@ -148,35 +147,39 @@ public final class TreeWalker
}
/** @see com.puppycrawl.tools.checkstyle.api.Configurable */
- public void configure(Configuration aConfiguration)
- throws CheckstyleException
+ public void finishLocalSetup()
{
- 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));
+ mChildContext = checkContext;
+ }
+
+ /**
+ * Instantiates, configures and registers a Check that is specified
+ * in the provided configuration.
+ * @see com.puppycrawl.tools.checkstyle.api.AutomaticBean
+ */
+ public void setupChild(Configuration aChildConf)
+ throws CheckstyleException
+ {
// 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 name = config.getName();
- final String[] packageNames = getPackageNames();
- final Check check =
- (Check) PackageObjectFactory.makeObject(
+
+ // IMPORTANT! Need to use the same class loader that created this
+ // class. Otherwise can get ClassCastException problems.
+ final String name = aChildConf.getName();
+ final String[] packageNames = getPackageNames();
+ final Check check =
+ (Check) PackageObjectFactory.makeObject(
packageNames, this.getClass().getClassLoader(), name);
- check.contextualize(checkContext);
- check.configure(config);
+ check.contextualize(mChildContext);
+ check.configure(aChildConf);
- registerCheck(check);
- }
+ registerCheck(check);
}
/**
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
index 832ad7bc2..fc56959e1 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
@@ -64,6 +64,12 @@ public class AutomaticBean implements Configurable, Contextualizable
private static void initConverters()
{
// TODO: is there a smarter way to tell beanutils not to use defaults?
+
+ // If any runtime environment like ANT or an IDE would use beanutils
+ // with different converters we would really be stuck here.
+ // Having to configure a static utility class in this way is really
+ // strange, it seems like a design problem in BeanUtils
+
boolean[] booleanArray = new boolean[0];
byte[] byteArray = new byte[0];
char[] charArray = new char[0];
@@ -114,13 +120,27 @@ public class AutomaticBean implements Configurable, Contextualizable
// do not use defaults in the default configuration of ConvertUtils
}
+ /** the configuration of this bean */
+ private Configuration mConfiguration;
+
/**
* Implements the Configurable interface using bean introspection.
+ *
+ * Subclasses are allowed to add behaviour. After the bean
+ * based setup has completed first the method
+ * {@link #finishLocalSetup finishLocalSetup}
+ * is called to allow completion of the bean's local setup,
+ * after that the method {@link #setupChild setupChild}
+ * is called for each {@link Configuration#getChildren child Configuration}
+ * of aConfiguration.
+ *
* @see Configurable
*/
- public void configure(Configuration aConfiguration)
+ public final void configure(Configuration aConfiguration)
throws CheckstyleException
{
+ mConfiguration = aConfiguration;
+
// TODO: debug log messages
final String[] attributes = aConfiguration.getAttributeNames();
@@ -142,13 +162,22 @@ public class AutomaticBean implements Configurable, Contextualizable
+ this.getClass().getName());
}
}
+
+ finishLocalSetup();
+
+ Configuration[] childConfigs = aConfiguration.getChildren();
+ for (int i = 0; i < childConfigs.length; i++) {
+ Configuration childConfig = childConfigs[i];
+ setupChild(childConfig);
+ }
}
/**
* Implements the Contextualizable interface using bean introspection.
* @see Contextualizable
*/
- public void contextualize(Context aContext) throws CheckstyleException
+ public final void contextualize(Context aContext)
+ throws CheckstyleException
{
// TODO: debug log messages
final String[] attributes = aContext.getAttributeNames();
@@ -174,6 +203,41 @@ public class AutomaticBean implements Configurable, Contextualizable
}
}
}
+
+ /**
+ * Returns the configuration that was used to configure this component.
+ * @return the configuration that was used to configure this component.
+ */
+ protected final Configuration getConfiguration()
+ {
+ return mConfiguration;
+ }
+
+ /**
+ * Provides a hook to finish the part of this compoent's setup that
+ * was not handled by the bean introspection.
+ *
+ * The default implementation does nothing. + *
+ * @throws CheckstyleException if there is a configuration error. + */ + protected void finishLocalSetup() throws CheckstyleException + { + } + + /** + * Called by configure() for every child of this component's Configuration. + *+ * The default implementation does nothing. + *
+ * @param aChildConf a child of this component's Configuration + * @throws CheckstyleException if there is a configuration error. + * @see Configuration#getChildren + */ + protected void setupChild(Configuration aChildConf) + throws CheckstyleException + { + } } /**