Fields Summary |
---|
private CacheName | cacheNameCache name for later instantiation. |
private String | cacheClassUser specified classname for Cache. |
private AlgorithmName | algoNameAlgorithm name for later instantiation. |
private String | algorithmClassUser specified classname for Algorithm. |
private ComparatorName | compNameComparator name for later instantiation. |
private String | comparatorClassUser specified classname for Comparator. |
private boolean | updateShould the cache be updated? |
private boolean | selectDirectoriesAre directories selected? |
private boolean | selectResourcesWithoutInputStreamShould Resources whithout an InputStream, and
therefore without checking, be selected? |
private boolean | delayUpdateDelay the writing of the cache file |
private Comparator | comparatorHow should the cached value and the new one compared? |
private Algorithm | algorithmAlgorithm for computing new values and updating the cache. |
private Cache | cacheThe Cache containing the old values. |
private int | modifiedCount of modified properties |
private boolean | isConfiguredFlag whether this object is configured. Configuration is only done once. |
private Vector | configParameterParameter vector with parameters for later initialization. |
private Vector | specialParameterParameter vector with special parameters for later initialization.
The names have the pattern '*.*', e.g. 'cache.cachefile'.
These parameters are used after the parameters with the pattern '*'. |
private ClassLoader | myClassLoaderThe classloader of this class. |
private org.apache.tools.ant.types.Path | classpathprovided classpath for the classloader |
Methods Summary |
---|
public void | addClasspath(org.apache.tools.ant.types.Path path)Add the classpath.
if (classpath != null) {
throw new BuildException("<classpath> can be set only once.");
}
classpath = path;
|
public void | addParam(java.lang.String key, java.lang.Object value)Support for nested <param> tags.
Parameter par = new Parameter();
par.setName(key);
par.setValue(String.valueOf(value));
configParameter.add(par);
|
public void | addParam(org.apache.tools.ant.types.Parameter parameter)Support for nested <param> tags.
configParameter.add(parameter);
|
public void | buildFinished(org.apache.tools.ant.BuildEvent event)Signals that the last target has finished.
if (getDelayUpdate()) {
saveCache();
}
|
public void | buildStarted(org.apache.tools.ant.BuildEvent event)Signals that a build has started.
// no-op
|
public void | configure()Configures this Selector.
Does this work only once per Selector object.
Because some problems while configuring from Selector
the configuration is done in the following order:
- collect the configuration data
- wait for the first isSelected() call
- set the default values
- set values for name pattern '*': update, cache, algorithm, comparator
- set values for name pattern '*.*: cache.cachefile, ...
This configuration algorithm is needed because you don't know
the order of arriving config-data. E.g. if you first set the
cache.cachefilename and after that the cache itself,
the default value for cachefilename is used, because setting the
cache implies creating a new Cache instance - with its defaults.
//
// ----- The "Singleton" -----
//
if (isConfigured) {
return;
}
isConfigured = true;
//
// ----- Set default values -----
//
Project p = getProject();
String filename = "cache.properties";
File cachefile = null;
if (p != null) {
// normal use inside Ant
cachefile = new File(p.getBaseDir(), filename);
// set self as a BuildListener to delay cachefile saves
getProject().addBuildListener(this);
} else {
// no reference to project - e.g. during normal JUnit tests
cachefile = new File(filename);
setDelayUpdate(false);
}
Cache defaultCache = new PropertiesfileCache(cachefile);
Algorithm defaultAlgorithm = new DigestAlgorithm();
Comparator defaultComparator = new EqualComparator();
update = true;
selectDirectories = true;
//
// ----- Set the main attributes, pattern '*' -----
//
for (Iterator itConfig = configParameter.iterator(); itConfig.hasNext();) {
Parameter par = (Parameter) itConfig.next();
if (par.getName().indexOf(".") > 0) {
// this is a *.* parameter for later use
specialParameter.add(par);
} else {
useParameter(par);
}
}
configParameter = new Vector();
// specify the algorithm classname
if (algoName != null) {
// use Algorithm defined via name
if ("hashvalue".equals(algoName.getValue())) {
algorithm = new HashvalueAlgorithm();
} else if ("digest".equals(algoName.getValue())) {
algorithm = new DigestAlgorithm();
} else if ("checksum".equals(algoName.getValue())) {
algorithm = new ChecksumAlgorithm();
}
} else {
if (algorithmClass != null) {
// use Algorithm specified by classname
algorithm = (Algorithm) loadClass(
algorithmClass,
"is not an Algorithm.",
Algorithm.class);
} else {
// nothing specified - use default
algorithm = defaultAlgorithm;
}
}
// specify the cache classname
if (cacheName != null) {
// use Cache defined via name
if ("propertyfile".equals(cacheName.getValue())) {
cache = new PropertiesfileCache();
}
} else {
if (cacheClass != null) {
// use Cache specified by classname
cache = (Cache) loadClass(cacheClass, "is not a Cache.", Cache.class);
} else {
// nothing specified - use default
cache = defaultCache;
}
}
// specify the comparator classname
if (compName != null) {
// use Algorithm defined via name
if ("equal".equals(compName.getValue())) {
comparator = new EqualComparator();
} else if ("rule".equals(compName.getValue())) {
// TODO there is a problem with the constructor for the RBC.
// you have to provide the rules in the constructors - no setters
// available.
throw new BuildException("RuleBasedCollator not yet supported.");
// Have to think about lazy initialization here... JHM
// comparator = new java.text.RuleBasedCollator();
}
} else {
if (comparatorClass != null) {
// use Algorithm specified by classname
comparator = (Comparator) loadClass(
comparatorClass,
"is not a Comparator.",
Comparator.class);
} else {
// nothing specified - use default
comparator = defaultComparator;
}
}
//
// ----- Set the special attributes, pattern '*.*' -----
//
for (Iterator itSpecial = specialParameter.iterator(); itSpecial.hasNext();) {
Parameter par = (Parameter) itSpecial.next();
useParameter(par);
}
specialParameter = new Vector();
|
public Algorithm | getAlgorithm()Get the algorithm type to use. return algorithm;
|
public Cache | getCache()Get the cache type to use. return cache;
|
public java.lang.ClassLoader | getClassLoader()Returns and initializes the classloader for this class.
if (myClassLoader == null) {
myClassLoader = (classpath == null)
// the usual classloader
? getClass().getClassLoader()
// additional use the provided classpath
: getProject().createClassLoader(classpath);
}
return myClassLoader;
|
public java.util.Comparator | getComparator()Get the comparator type to use. return comparator;
|
public boolean | getDelayUpdate()Getter for the delay update
return delayUpdate;
|
public int | getModified()Getter for the modified count
return modified;
|
public boolean | isSelected(org.apache.tools.ant.types.Resource resource)Implementation of ResourceSelector.isSelected().
if (resource.isFilesystemOnly()) {
// We have a 'resourced' file, so reconvert it and use
// the 'old' implementation.
FileResource fileResource = (FileResource) resource;
File file = fileResource.getFile();
String filename = fileResource.getName();
File basedir = fileResource.getBaseDir();
return isSelected(basedir, filename, file);
} else {
try {
// How to handle non-file-Resources? I copy temporarily the
// resource to a file and use the file-implementation.
FileUtils fu = FileUtils.getFileUtils();
File tmpFile = fu.createTempFile("modified-", ".tmp", null);
Resource tmpResource = new FileResource(tmpFile);
ResourceUtils.copyResource(resource, tmpResource);
boolean isSelected = isSelected(tmpFile.getParentFile(),
tmpFile.getName(),
resource.toLongString());
tmpFile.delete();
return isSelected;
} catch (UnsupportedOperationException uoe) {
log("The resource '"
+ resource.getName()
+ "' does not provide an InputStream, so it is not checked. "
+ "Akkording to 'selres' attribute value it is "
+ ((selectResourcesWithoutInputStream) ? "" : " not")
+ "selected.", Project.MSG_INFO);
return selectResourcesWithoutInputStream;
} catch (Exception e) {
throw new BuildException(e);
}
}
|
public boolean | isSelected(java.io.File basedir, java.lang.String filename, java.io.File file)Implementation of BaseExtendSelector.isSelected().
return isSelected(basedir, filename, file.getAbsolutePath());
|
private boolean | isSelected(java.io.File basedir, java.lang.String filename, java.lang.String cacheKey)The business logic of this selector for use as ResourceSelector of
FileSelector.
validate();
File f = new File(basedir, filename);
// You can not compute a value for a directory
if (f.isDirectory()) {
return selectDirectories;
}
// Get the values and do the comparison
String cachedValue = String.valueOf(cache.get(f.getAbsolutePath()));
String newValue = algorithm.getValue(f);
boolean rv = (comparator.compare(cachedValue, newValue) != 0);
// Maybe update the cache
if (update && rv) {
cache.put(f.getAbsolutePath(), newValue);
setModified(getModified() + 1);
if (!getDelayUpdate()) {
saveCache();
}
}
return rv;
|
protected java.lang.Object | loadClass(java.lang.String classname, java.lang.String msg, java.lang.Class type)Loads the specified class and initializes an object of that class.
Throws a BuildException using the given message if an error occurs during
loading/instantiation or if the object is not from the given type.
try {
// load the specified class
ClassLoader cl = getClassLoader();
Class clazz = null;
if (cl != null) {
clazz = cl.loadClass(classname);
} else {
clazz = Class.forName(classname);
}
Object rv = clazz.newInstance();
if (!type.isInstance(rv)) {
throw new BuildException("Specified class (" + classname + ") " + msg);
}
return rv;
} catch (ClassNotFoundException e) {
throw new BuildException("Specified class (" + classname + ") not found.");
} catch (Exception e) {
throw new BuildException(e);
}
|
public void | messageLogged(org.apache.tools.ant.BuildEvent event)Signals a message logging event.
// no-op
|
protected void | saveCache()save the cache file
if (getModified() > 1) {
cache.save();
setModified(0);
}
|
public void | setAlgorithm(org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector$AlgorithmName name)Set the algorithm type to use.
algoName = name;
|
public void | setAlgorithmClass(java.lang.String classname)Setter for algorithmClass.
algorithmClass = classname;
|
public void | setCache(org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector$CacheName name)Set the cache type to use.
cacheName = name;
|
public void | setCacheClass(java.lang.String classname)Setter for cacheClass.
cacheClass = classname;
|
public void | setClassLoader(java.lang.ClassLoader loader)Set the used ClassLoader.
If you invoke this selector by API (e.g. inside some testcases) the selector
will use a different classloader for loading the interface implementations than
the caller. Therefore you will get a ClassCastException if you get the
implementations from the selector and cast them.
myClassLoader = loader;
|
public void | setComparator(org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector$ComparatorName name)Set the comparator type to use.
compName = name;
|
public void | setComparatorClass(java.lang.String classname)Setter for comparatorClass.
comparatorClass = classname;
|
public void | setDelayUpdate(boolean delayUpdate)Setter for the delay update
this.delayUpdate = delayUpdate;
|
public void | setModified(int modified)Setter for the modified count
this.modified = modified;
|
public void | setParameters(org.apache.tools.ant.types.Parameter[] parameters)Defined in org.apache.tools.ant.types.Parameterizable.
Overwrite implementation in superclass because only special
parameters are valid.
if (parameters != null) {
for (int i = 0; i < parameters.length; i++) {
configParameter.add(parameters[i]);
}
}
|
public void | setSeldirs(boolean seldirs)Support for seldirs attribute.
selectDirectories = seldirs;
|
public void | setSelres(boolean newValue)Support for selres attribute.
this.selectResourcesWithoutInputStream = newValue;
|
public void | setUpdate(boolean update)Support for update attribute.
this.update = update;
|
public void | targetFinished(org.apache.tools.ant.BuildEvent event)Signals that a target has finished.
if (getDelayUpdate()) {
saveCache();
}
|
public void | targetStarted(org.apache.tools.ant.BuildEvent event)Signals that a target is starting.
// no-op
|
public void | taskFinished(org.apache.tools.ant.BuildEvent event)Signals that a task has finished.
if (getDelayUpdate()) {
saveCache();
}
|
public void | taskStarted(org.apache.tools.ant.BuildEvent event)Signals that a task is starting.
// no-op
|
public java.lang.String | toString()Override Object.toString().
StringBuffer buf = new StringBuffer("{modifiedselector");
buf.append(" update=").append(update);
buf.append(" seldirs=").append(selectDirectories);
buf.append(" cache=").append(cache);
buf.append(" algorithm=").append(algorithm);
buf.append(" comparator=").append(comparator);
buf.append("}");
return buf.toString();
|
protected void | tryToSetAParameter(java.lang.Object obj, java.lang.String name, java.lang.String value)Try to set a value on an object using reflection.
Helper method for easier access to IntrospectionHelper.setAttribute().
Project prj = (getProject() != null) ? getProject() : new Project();
IntrospectionHelper iHelper
= IntrospectionHelper.getHelper(prj, obj.getClass());
try {
iHelper.setAttribute(prj, obj, name, value);
} catch (org.apache.tools.ant.BuildException e) {
// no-op
}
|
public void | useParameter(org.apache.tools.ant.types.Parameter parameter)Support for nested tags.
Parameter named cache, algorithm,
comparator or update are mapped to
the respective set-Method.
Parameter which names starts with cache. or
algorithm. or comparator. are tried
to set on the appropriate object via its set-methods.
Other parameters are invalid and an BuildException will
be thrown.
String key = parameter.getName();
String value = parameter.getValue();
if ("cache".equals(key)) {
CacheName cn = new CacheName();
cn.setValue(value);
setCache(cn);
} else if ("algorithm".equals(key)) {
AlgorithmName an = new AlgorithmName();
an.setValue(value);
setAlgorithm(an);
} else if ("comparator".equals(key)) {
ComparatorName cn = new ComparatorName();
cn.setValue(value);
setComparator(cn);
} else if ("update".equals(key)) {
boolean updateValue =
("true".equalsIgnoreCase(value))
? true
: false;
setUpdate(updateValue);
} else if ("delayupdate".equals(key)) {
boolean updateValue =
("true".equalsIgnoreCase(value))
? true
: false;
setDelayUpdate(updateValue);
} else if ("seldirs".equals(key)) {
boolean sdValue =
("true".equalsIgnoreCase(value))
? true
: false;
setSeldirs(sdValue);
} else if (key.startsWith("cache.")) {
String name = key.substring(6);
tryToSetAParameter(cache, name, value);
} else if (key.startsWith("algorithm.")) {
String name = key.substring(10);
tryToSetAParameter(algorithm, name, value);
} else if (key.startsWith("comparator.")) {
String name = key.substring(11);
tryToSetAParameter(comparator, name, value);
} else {
setError("Invalid parameter " + key);
}
|
public void | verifySettings()Overrides BaseSelector.verifySettings().
configure();
if (cache == null) {
setError("Cache must be set.");
} else if (algorithm == null) {
setError("Algorithm must be set.");
} else if (!cache.isValid()) {
setError("Cache must be proper configured.");
} else if (!algorithm.isValid()) {
setError("Algorithm must be proper configured.");
}
|