make AutomaticBean.configure() final and provide defined extension points

to prevent programming errors in user classes.
This commit is contained in:
Lars Kühne 2002-12-10 19:13:35 +00:00
parent 987da3a4c5
commit 08d6efe49d
3 changed files with 126 additions and 50 deletions

View File

@ -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 <code>Checker</code> 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());
}
}

View File

@ -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 <code>TreeWalker</code> 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);
}
/**

View File

@ -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 <code>aConfiguration</code>.
*
* @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.
* <p>
* The default implementation does nothing.
* </p>
* @throws CheckstyleException if there is a configuration error.
*/
protected void finishLocalSetup() throws CheckstyleException
{
}
/**
* Called by configure() for every child of this component's Configuration.
* <p>
* The default implementation does nothing.
* </p>
* @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
{
}
}
/**