KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > types > selectors > modifiedselector > ModifiedSelector


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.types.selectors.modifiedselector;
20
21
22 // Java
23
import java.util.Comparator JavaDoc;
24 import java.util.Vector JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.io.File JavaDoc;
27
28 // Ant
29
import org.apache.tools.ant.Project;
30 import org.apache.tools.ant.IntrospectionHelper;
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.BuildListener;
33 import org.apache.tools.ant.BuildEvent;
34 import org.apache.tools.ant.types.EnumeratedAttribute;
35 import org.apache.tools.ant.types.Parameter;
36 import org.apache.tools.ant.types.Path;
37 import org.apache.tools.ant.types.Resource;
38 import org.apache.tools.ant.types.resources.FileResource;
39 import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
40 import org.apache.tools.ant.types.selectors.BaseExtendSelector;
41 import org.apache.tools.ant.util.FileUtils;
42 import org.apache.tools.ant.util.ResourceUtils;
43
44
45 /**
46  * <p>Selector class that uses <i>Algorithm</i>, <i>Cache</i> and <i>Comparator</i>
47  * for its work.
48  * The <i>Algorithm</i> is used for computing a hashvalue for a file.
49  * The <i>Comparator</i> decides whether to select or not.
50  * The <i>Cache</i> stores the other value for comparison by the <i>Comparator</i>
51  * in a persistent manner.</p>
52  *
53  * <p>The ModifiedSelector is implemented as a <b>CoreSelector</b> and uses default
54  * values for all its attributes therefore the simpliest example is <pre>
55  * &lt;copy todir="dest"&gt;
56  * &lt;filelist dir="src"&gt;
57  * &lt;modified/&gt;
58  * &lt;/filelist&gt;
59  * &lt;/copy&gt;
60  * </pre></p>
61  *
62  * <p>The same example rewritten as CoreSelector with setting the all values
63  * (same as defaults are) would be <pre>
64  * &lt;copy todir="dest"&gt;
65  * &lt;filelist dir="src"&gt;
66  * &lt;modified update="true"
67  * cache="propertyfile"
68  * algorithm="digest"
69  * comparator="equal"&gt;
70  * &lt;param name="cache.cachefile" value="cache.properties"/&gt;
71  * &lt;param name="algorithm.algorithm" value="MD5"/&gt;
72  * &lt;/modified&gt;
73  * &lt;/filelist&gt;
74  * &lt;/copy&gt;
75  * </pre></p>
76  *
77  * <p>And the same rewritten as CustomSelector would be<pre>
78  * &lt;copy todir="dest"&gt;
79  * &lt;filelist dir="src"&gt;
80  * &lt;custom class="org.apache.tools.ant.type.selectors.ModifiedSelector"&gt;
81  * &lt;param name="update" value="true"/&gt;
82  * &lt;param name="cache" value="propertyfile"/&gt;
83  * &lt;param name="algorithm" value="digest"/&gt;
84  * &lt;param name="comparator" value="equal"/&gt;
85  * &lt;param name="cache.cachefile" value="cache.properties"/&gt;
86  * &lt;param name="algorithm.algorithm" value="MD5"/&gt;
87  * &lt;/custom&gt;
88  * &lt;/filelist&gt;
89  * &lt;/copy&gt;
90  * </pre></p>
91  *
92  * <p>If you want to provide your own interface implementation you can do
93  * that via the *classname attributes. If the classes are not on Ant's core
94  * classpath, you will have to provide the path via nested &lt;classpath&gt;
95  * element, so that the selector can find the classes. <pre>
96  * &lt;modified cacheclassname="com.mycompany.MyCache"&gt;
97  * &lt;classpath&gt;
98  * &lt;pathelement location="lib/mycompony-antutil.jar"/&gt;
99  * &lt;/classpath&gt;
100  * &lt;/modified&gt;
101  * </pre></p>
102  *
103  * <p>All these three examples copy the files from <i>src</i> to <i>dest</i>
104  * using the ModifiedSelector. The ModifiedSelector uses the <i>PropertyfileCache
105  * </i>, the <i>DigestAlgorithm</i> and the <i>EqualComparator</i> for its
106  * work. The PropertyfileCache stores key-value-pairs in a simple java
107  * properties file. The filename is <i>cache.properties</i>. The <i>update</i>
108  * flag lets the selector update the values in the cache (and on first call
109  * creates the cache). The <i>DigestAlgorithm</i> computes a hashvalue using the
110  * java.security.MessageDigest class with its MD5-Algorithm and its standard
111  * provider. The new computed hashvalue and the stored one are compared by
112  * the <i>EqualComparator</i> which returns 'true' (more correct a value not
113  * equals zero (1)) if the values are not the same using simple String
114  * comparison.</p>
115  *
116  * <p>A useful scenario for this selector is inside a build environment
117  * for homepage generation (e.g. with <a HREF="http://forrest.apache.org/">
118  * Apache Forrest</a>). <pre>
119  * &lt;target name="generate-and-upload-site"&gt;
120  * &lt;echo&gt; generate the site using forrest &lt;/echo&gt;
121  * &lt;antcall target="site"/&gt;
122  *
123  * &lt;echo&gt; upload the changed files &lt;/echo&gt;
124  * &lt;ftp server="${ftp.server}" userid="${ftp.user}" password="${ftp.pwd}"&gt;
125  * &lt;fileset dir="htdocs/manual"&gt;
126  * &lt;modified/&gt;
127  * &lt;/fileset&gt;
128  * &lt;/ftp&gt;
129  * &lt;/target&gt;
130  * </pre> Here all <b>changed</b> files are uploaded to the server. The
131  * ModifiedSelector saves therefore much upload time.</p>
132  *
133  *
134  * <p>This selector uses reflection for setting the values of its three interfaces
135  * (using org.apache.tools.ant.IntrospectionHelper) therefore no special
136  * 'configuration interfaces' has to be implemented by new caches, algorithms or
137  * comparators. All present <i>set</i>XX methods can be used. E.g. the DigestAlgorithm
138  * can use a specified provider for computing its value. For selecting this
139  * there is a <i>setProvider(String providername)</i> method. So you can use
140  * a nested <i>&lt;param name="algorithm.provider" value="MyProvider"/&gt;</i>.
141  *
142  *
143  * @since Ant 1.6
144  */

145 public class ModifiedSelector extends BaseExtendSelector
146                               implements BuildListener, ResourceSelector {
147
148
149     // ----- attributes -----
150

151
152     /** Cache name for later instantiation. */
153     private CacheName cacheName = null;
154
155     /** User specified classname for Cache. */
156     private String JavaDoc cacheClass;
157
158     /** Algorithm name for later instantiation. */
159     private AlgorithmName algoName = null;
160
161     /** User specified classname for Algorithm. */
162     private String JavaDoc algorithmClass;
163
164     /** Comparator name for later instantiation. */
165     private ComparatorName compName = null;
166
167     /** User specified classname for Comparator. */
168     private String JavaDoc comparatorClass;
169
170     /** Should the cache be updated? */
171     private boolean update = true;
172
173     /** Are directories selected? */
174     private boolean selectDirectories = true;
175
176     /**
177      * Should Resources whithout an InputStream, and
178      * therefore without checking, be selected?
179      */

180     private boolean selectResourcesWithoutInputStream = true;
181
182     /** Delay the writing of the cache file */
183     private boolean delayUpdate = true;
184
185
186     // ----- internal member variables -----
187

188
189     /** How should the cached value and the new one compared? */
190     private Comparator JavaDoc comparator = null;
191
192     /** Algorithm for computing new values and updating the cache. */
193     private Algorithm algorithm = null;
194
195     /** The Cache containing the old values. */
196     private Cache cache = null;
197
198     /** Count of modified properties */
199     private int modified = 0;
200
201     /** Flag whether this object is configured. Configuration is only done once. */
202     private boolean isConfigured = false;
203
204     /**
205      * Parameter vector with parameters for later initialization.
206      * @see #configure
207      */

208     private Vector JavaDoc configParameter = new Vector JavaDoc();
209
210     /**
211      * Parameter vector with special parameters for later initialization.
212      * The names have the pattern '*.*', e.g. 'cache.cachefile'.
213      * These parameters are used <b>after</b> the parameters with the pattern '*'.
214      * @see #configure
215      */

216     private Vector JavaDoc specialParameter = new Vector JavaDoc();
217
218     /** The classloader of this class. */
219     private ClassLoader JavaDoc myClassLoader = null;
220
221     /** provided classpath for the classloader */
222     private Path classpath = null;
223
224
225     // ----- constructors -----
226

227
228     /** Bean-Constructor. */
229     public ModifiedSelector() {
230     }
231
232
233     // ----- configuration -----
234

235
236     /** Overrides BaseSelector.verifySettings(). */
237     public void verifySettings() {
238         configure();
239         if (cache == null) {
240             setError("Cache must be set.");
241         } else if (algorithm == null) {
242             setError("Algorithm must be set.");
243         } else if (!cache.isValid()) {
244             setError("Cache must be proper configured.");
245         } else if (!algorithm.isValid()) {
246             setError("Algorithm must be proper configured.");
247         }
248     }
249
250
251     /**
252      * Configures this Selector.
253      * Does this work only once per Selector object.
254      * <p>Because some problems while configuring from <custom>Selector
255      * the configuration is done in the following order:<ol>
256      * <li> collect the configuration data </li>
257      * <li> wait for the first isSelected() call </li>
258      * <li> set the default values </li>
259      * <li> set values for name pattern '*': update, cache, algorithm, comparator </li>
260      * <li> set values for name pattern '*.*: cache.cachefile, ... </li>
261      * </ol></p>
262      * <p>This configuration algorithm is needed because you don't know
263      * the order of arriving config-data. E.g. if you first set the
264      * <i>cache.cachefilename</i> and after that the <i>cache</i> itself,
265      * the default value for cachefilename is used, because setting the
266      * cache implies creating a new Cache instance - with its defaults.</p>
267      */

268     public void configure() {
269         //
270
// ----- The "Singleton" -----
271
//
272
if (isConfigured) {
273             return;
274         }
275         isConfigured = true;
276
277         //
278
// ----- Set default values -----
279
//
280
Project p = getProject();
281         String JavaDoc filename = "cache.properties";
282         File JavaDoc cachefile = null;
283         if (p != null) {
284             // normal use inside Ant
285
cachefile = new File JavaDoc(p.getBaseDir(), filename);
286
287             // set self as a BuildListener to delay cachefile saves
288
getProject().addBuildListener(this);
289         } else {
290             // no reference to project - e.g. during normal JUnit tests
291
cachefile = new File JavaDoc(filename);
292             setDelayUpdate(false);
293         }
294         Cache defaultCache = new PropertiesfileCache(cachefile);
295         Algorithm defaultAlgorithm = new DigestAlgorithm();
296         Comparator JavaDoc defaultComparator = new EqualComparator();
297         update = true;
298         selectDirectories = true;
299
300         //
301
// ----- Set the main attributes, pattern '*' -----
302
//
303
for (Iterator JavaDoc itConfig = configParameter.iterator(); itConfig.hasNext();) {
304             Parameter par = (Parameter) itConfig.next();
305             if (par.getName().indexOf(".") > 0) {
306                 // this is a *.* parameter for later use
307
specialParameter.add(par);
308             } else {
309                 useParameter(par);
310             }
311         }
312         configParameter = new Vector JavaDoc();
313
314         // specify the algorithm classname
315
if (algoName != null) {
316             // use Algorithm defined via name
317
if ("hashvalue".equals(algoName.getValue())) {
318                 algorithm = new HashvalueAlgorithm();
319             } else if ("digest".equals(algoName.getValue())) {
320                 algorithm = new DigestAlgorithm();
321             } else if ("checksum".equals(algoName.getValue())) {
322                 algorithm = new ChecksumAlgorithm();
323             }
324         } else {
325             if (algorithmClass != null) {
326                 // use Algorithm specified by classname
327
algorithm = (Algorithm) loadClass(
328                     algorithmClass,
329                     "is not an Algorithm.",
330                     Algorithm.class);
331             } else {
332                 // nothing specified - use default
333
algorithm = defaultAlgorithm;
334             }
335         }
336
337         // specify the cache classname
338
if (cacheName != null) {
339             // use Cache defined via name
340
if ("propertyfile".equals(cacheName.getValue())) {
341                 cache = new PropertiesfileCache();
342             }
343         } else {
344             if (cacheClass != null) {
345                 // use Cache specified by classname
346
cache = (Cache) loadClass(cacheClass, "is not a Cache.", Cache.class);
347             } else {
348                 // nothing specified - use default
349
cache = defaultCache;
350             }
351         }
352
353         // specify the comparator classname
354
if (compName != null) {
355             // use Algorithm defined via name
356
if ("equal".equals(compName.getValue())) {
357                 comparator = new EqualComparator();
358              } else if ("rule".equals(compName.getValue())) {
359                 // TODO there is a problem with the constructor for the RBC.
360
// you have to provide the rules in the constructors - no setters
361
// available.
362
throw new BuildException("RuleBasedCollator not yet supported.");
363                 // Have to think about lazy initialization here... JHM
364
// comparator = new java.text.RuleBasedCollator();
365
}
366         } else {
367             if (comparatorClass != null) {
368                 // use Algorithm specified by classname
369
comparator = (Comparator JavaDoc) loadClass(
370                     comparatorClass,
371                     "is not a Comparator.",
372                     Comparator JavaDoc.class);
373             } else {
374                 // nothing specified - use default
375
comparator = defaultComparator;
376             }
377         }
378
379         //
380
// ----- Set the special attributes, pattern '*.*' -----
381
//
382
for (Iterator JavaDoc itSpecial = specialParameter.iterator(); itSpecial.hasNext();) {
383             Parameter par = (Parameter) itSpecial.next();
384             useParameter(par);
385         }
386         specialParameter = new Vector JavaDoc();
387     }
388
389
390     /**
391      * Loads the specified class and initializes an object of that class.
392      * Throws a BuildException using the given message if an error occurs during
393      * loading/instantiation or if the object is not from the given type.
394      * @param classname the classname
395      * @param msg the message-part for the BuildException
396      * @param type the type to check against
397      * @return a castable object
398      */

399     protected Object JavaDoc loadClass(String JavaDoc classname, String JavaDoc msg, Class JavaDoc type) {
400         try {
401             // load the specified class
402
ClassLoader JavaDoc cl = getClassLoader();
403             Class JavaDoc clazz = null;
404             if (cl != null) {
405                 clazz = cl.loadClass(classname);
406             } else {
407                 clazz = Class.forName(classname);
408             }
409
410             Object JavaDoc rv = clazz.newInstance();
411
412             if (!type.isInstance(rv)) {
413                 throw new BuildException("Specified class (" + classname + ") " + msg);
414             }
415             return rv;
416         } catch (ClassNotFoundException JavaDoc e) {
417             throw new BuildException("Specified class (" + classname + ") not found.");
418         } catch (Exception JavaDoc e) {
419             throw new BuildException(e);
420         }
421     }
422
423
424     // ----- the selection work -----
425

426
427     /**
428      * Implementation of ResourceSelector.isSelected().
429      *
430      * @param resource The resource to check
431      * @return whether the resource is selected
432      * @see ResourceSelector#isSelected(Resource)
433      */

434     public boolean isSelected(Resource resource) {
435         if (resource.isFilesystemOnly()) {
436             // We have a 'resourced' file, so reconvert it and use
437
// the 'old' implementation.
438
FileResource fileResource = (FileResource) resource;
439             File JavaDoc file = fileResource.getFile();
440             String JavaDoc filename = fileResource.getName();
441             File JavaDoc basedir = fileResource.getBaseDir();
442             return isSelected(basedir, filename, file);
443         } else {
444             try {
445                 // How to handle non-file-Resources? I copy temporarily the
446
// resource to a file and use the file-implementation.
447
FileUtils fu = FileUtils.getFileUtils();
448                 File JavaDoc tmpFile = fu.createTempFile("modified-", ".tmp", null);
449                 Resource tmpResource = new FileResource(tmpFile);
450                 ResourceUtils.copyResource(resource, tmpResource);
451                 boolean isSelected = isSelected(tmpFile.getParentFile(),
452                                                 tmpFile.getName(),
453                                                 resource.toLongString());
454                 tmpFile.delete();
455                 return isSelected;
456             } catch (UnsupportedOperationException JavaDoc uoe) {
457                 log("The resource '"
458                   + resource.getName()
459                   + "' does not provide an InputStream, so it is not checked. "
460                   + "Akkording to 'selres' attribute value it is "
461                   + ((selectResourcesWithoutInputStream) ? "" : " not")
462                   + "selected.", Project.MSG_INFO);
463                 return selectResourcesWithoutInputStream;
464             } catch (Exception JavaDoc e) {
465                 throw new BuildException(e);
466             }
467         }
468     }
469
470
471     /**
472      * Implementation of BaseExtendSelector.isSelected().
473      *
474      * @param basedir as described in BaseExtendSelector
475      * @param filename as described in BaseExtendSelector
476      * @param file as described in BaseExtendSelector
477      * @return as described in BaseExtendSelector
478      */

479     public boolean isSelected(File JavaDoc basedir, String JavaDoc filename, File JavaDoc file) {
480         return isSelected(basedir, filename, file.getAbsolutePath());
481     }
482
483
484     /**
485      * The business logic of this selector for use as ResourceSelector of
486      * FileSelector.
487      *
488      * @param basedir as described in BaseExtendSelector
489      * @param filename as described in BaseExtendSelector
490      * @param cacheKey the name for the key for storing the hashvalue
491      * @return
492      */

493     private boolean isSelected(File JavaDoc basedir, String JavaDoc filename, String JavaDoc cacheKey) {
494         validate();
495         File JavaDoc f = new File JavaDoc(basedir, filename);
496
497         // You can not compute a value for a directory
498
if (f.isDirectory()) {
499             return selectDirectories;
500         }
501
502         // Get the values and do the comparison
503
String JavaDoc cachedValue = String.valueOf(cache.get(f.getAbsolutePath()));
504         String JavaDoc newValue = algorithm.getValue(f);
505
506         boolean rv = (comparator.compare(cachedValue, newValue) != 0);
507
508         // Maybe update the cache
509
if (update && rv) {
510             cache.put(f.getAbsolutePath(), newValue);
511             setModified(getModified() + 1);
512             if (!getDelayUpdate()) {
513                 saveCache();
514             }
515         }
516
517         return rv;
518     }
519
520
521    /**
522     * save the cache file
523     */

524     protected void saveCache() {
525         if (getModified() > 1) {
526             cache.save();
527             setModified(0);
528         }
529     }
530
531
532     // ----- attribute and nested element support -----
533

534
535     /**
536      * Setter for algorithmClass.
537      * @param classname new value
538      */

539     public void setAlgorithmClass(String JavaDoc classname) {
540         algorithmClass = classname;
541     }
542
543
544     /**
545      * Setter for comparatorClass.
546      * @param classname new value
547      */

548     public void setComparatorClass(String JavaDoc classname) {
549         comparatorClass = classname;
550     }
551
552
553     /**
554      * Setter for cacheClass.
555      * @param classname new value
556      */

557     public void setCacheClass(String JavaDoc classname) {
558         cacheClass = classname;
559     }
560
561
562     /**
563      * Support for <i>update</i> attribute.
564      * @param update new value
565      */

566     public void setUpdate(boolean update) {
567         this.update = update;
568     }
569
570
571     /**
572      * Support for <i>seldirs</i> attribute.
573      * @param seldirs new value
574      */

575     public void setSeldirs(boolean seldirs) {
576         selectDirectories = seldirs;
577     }
578
579
580     /**
581      * Support for <i>selres</i> attribute.
582      * @param newValue the new value
583      */

584     public void setSelres(boolean newValue) {
585         this.selectResourcesWithoutInputStream = newValue;
586     }
587
588
589     /**
590      * Getter for the modified count
591      * @return modified count
592      */

593     public int getModified() {
594         return modified;
595     }
596
597
598     /**
599      * Setter for the modified count
600      * @param modified count
601      */

602     public void setModified(int modified) {
603         this.modified = modified;
604     }
605
606
607     /**
608      * Getter for the delay update
609      * @return true if we should delay for performance
610      */

611     public boolean getDelayUpdate() {
612         return delayUpdate;
613     }
614
615
616     /**
617      * Setter for the delay update
618      * @param delayUpdate true if we should delay for performance
619      */

620     public void setDelayUpdate(boolean delayUpdate) {
621         this.delayUpdate = delayUpdate;
622     }
623
624
625     /**
626      * Add the classpath.
627      * @param path the classpath
628      */

629     public void addClasspath(Path path) {
630         if (classpath != null) {
631             throw new BuildException("<classpath> can be set only once.");
632         }
633         classpath = path;
634     }
635
636
637     /**
638      * Returns and initializes the classloader for this class.
639      * @return the classloader
640      */

641     public ClassLoader JavaDoc getClassLoader() {
642         if (myClassLoader == null) {
643             myClassLoader = (classpath == null)
644                 // the usual classloader
645
? getClass().getClassLoader()
646                 // additional use the provided classpath
647
: getProject().createClassLoader(classpath);
648         }
649         return myClassLoader;
650     }
651
652
653     /**
654      * Set the used ClassLoader.
655      * If you invoke this selector by API (e.g. inside some testcases) the selector
656      * will use a different classloader for loading the interface implementations than
657      * the caller. Therefore you will get a ClassCastException if you get the
658      * implementations from the selector and cast them.
659      * @param loader the ClassLoader to use
660      */

661     public void setClassLoader(ClassLoader JavaDoc loader) {
662         myClassLoader = loader;
663     }
664
665
666     /**
667      * Support for nested &lt;param&gt; tags.
668      * @param key the key of the parameter
669      * @param value the value of the parameter
670      */

671     public void addParam(String JavaDoc key, Object JavaDoc value) {
672         Parameter par = new Parameter();
673         par.setName(key);
674         par.setValue(String.valueOf(value));
675         configParameter.add(par);
676     }
677
678
679     /**
680      * Support for nested &lt;param&gt; tags.
681      * @param parameter the parameter object
682      */

683     public void addParam(Parameter parameter) {
684         configParameter.add(parameter);
685     }
686
687
688     /**
689      * Defined in org.apache.tools.ant.types.Parameterizable.
690      * Overwrite implementation in superclass because only special
691      * parameters are valid.
692      * @see #addParam(String,Object).
693      * @param parameters the parameters to set.
694      */

695     public void setParameters(Parameter[] parameters) {
696         if (parameters != null) {
697             for (int i = 0; i < parameters.length; i++) {
698                 configParameter.add(parameters[i]);
699             }
700         }
701     }
702
703
704     /**
705      * Support for nested <param name="" value=""/> tags.
706      * Parameter named <i>cache</i>, <i>algorithm</i>,
707      * <i>comparator</i> or <i>update</i> are mapped to
708      * the respective set-Method.
709      * Parameter which names starts with <i>cache.</i> or
710      * <i>algorithm.</i> or <i>comparator.</i> are tried
711      * to set on the appropriate object via its set-methods.
712      * Other parameters are invalid and an BuildException will
713      * be thrown.
714      *
715      * @param parameter Key and value as parameter object
716      */

717     public void useParameter(Parameter parameter) {
718         String JavaDoc key = parameter.getName();
719         String JavaDoc value = parameter.getValue();
720         if ("cache".equals(key)) {
721             CacheName cn = new CacheName();
722             cn.setValue(value);
723             setCache(cn);
724         } else if ("algorithm".equals(key)) {
725             AlgorithmName an = new AlgorithmName();
726             an.setValue(value);
727             setAlgorithm(an);
728         } else if ("comparator".equals(key)) {
729             ComparatorName cn = new ComparatorName();
730             cn.setValue(value);
731             setComparator(cn);
732         } else if ("update".equals(key)) {
733             boolean updateValue =
734                 ("true".equalsIgnoreCase(value))
735                 ? true
736                 : false;
737             setUpdate(updateValue);
738         } else if ("delayupdate".equals(key)) {
739             boolean updateValue =
740                 ("true".equalsIgnoreCase(value))
741                 ? true
742                 : false;
743             setDelayUpdate(updateValue);
744         } else if ("seldirs".equals(key)) {
745             boolean sdValue =
746                 ("true".equalsIgnoreCase(value))
747                 ? true
748                 : false;
749             setSeldirs(sdValue);
750         } else if (key.startsWith("cache.")) {
751             String JavaDoc name = key.substring(6);
752             tryToSetAParameter(cache, name, value);
753         } else if (key.startsWith("algorithm.")) {
754             String JavaDoc name = key.substring(10);
755             tryToSetAParameter(algorithm, name, value);
756         } else if (key.startsWith("comparator.")) {
757             String JavaDoc name = key.substring(11);
758             tryToSetAParameter(comparator, name, value);
759         } else {
760             setError("Invalid parameter " + key);
761         }
762     }
763
764
765     /**
766      * Try to set a value on an object using reflection.
767      * Helper method for easier access to IntrospectionHelper.setAttribute().
768      * @param obj the object on which the attribute should be set
769      * @param name the attributename
770      * @param value the new value
771      */

772     protected void tryToSetAParameter(Object JavaDoc obj, String JavaDoc name, String JavaDoc value) {
773         Project prj = (getProject() != null) ? getProject() : new Project();
774         IntrospectionHelper iHelper
775             = IntrospectionHelper.getHelper(prj, obj.getClass());
776         try {
777             iHelper.setAttribute(prj, obj, name, value);
778         } catch (org.apache.tools.ant.BuildException e) {
779             // no-op
780
}
781     }
782
783
784     // ----- 'beautiful' output -----
785

786
787     /**
788      * Override Object.toString().
789      * @return information about this selector
790      */

791     public String JavaDoc toString() {
792         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("{modifiedselector");
793         buf.append(" update=").append(update);
794         buf.append(" seldirs=").append(selectDirectories);
795         buf.append(" cache=").append(cache);
796         buf.append(" algorithm=").append(algorithm);
797         buf.append(" comparator=").append(comparator);
798         buf.append("}");
799         return buf.toString();
800     }
801
802
803     // ----- BuildListener interface methods -----
804

805
806     /**
807      * Signals that the last target has finished.
808      * @param event recieved BuildEvent
809     */

810     public void buildFinished(BuildEvent event) {
811         if (getDelayUpdate()) {
812             saveCache();
813         }
814     }
815
816
817     /**
818      * Signals that a target has finished.
819      * @param event recieved BuildEvent
820     */

821     public void targetFinished(BuildEvent event) {
822         if (getDelayUpdate()) {
823             saveCache();
824         }
825     }
826
827
828     /**
829      * Signals that a task has finished.
830      * @param event recieved BuildEvent
831     */

832     public void taskFinished(BuildEvent event) {
833         if (getDelayUpdate()) {
834             saveCache();
835         }
836     }
837
838
839     /**
840      * Signals that a build has started.
841      * @param event recieved BuildEvent
842     */

843     public void buildStarted(BuildEvent event) {
844         // no-op
845
}
846
847
848     /**
849      * Signals that a target is starting.
850      * @param event received BuildEvent
851     */

852     public void targetStarted(BuildEvent event) {
853         // no-op
854
}
855
856
857
858     /**
859      * Signals that a task is starting.
860      * @param event recieved BuildEvent
861     */

862     public void taskStarted(BuildEvent event) {
863         // no-op
864
}
865
866
867     /**
868      * Signals a message logging event.
869      * @param event recieved BuildEvent
870     */

871     public void messageLogged(BuildEvent event) {
872         // no-op
873
}
874
875
876     // The EnumeratedAttributes for the three interface implementations.
877
// Name-Classname mapping is done in the configure() method.
878

879
880     /**
881      * Get the cache type to use.
882      * @return the enumerated cache type
883      */

884     public Cache getCache() { return cache; }
885
886     /**
887      * Set the cache type to use.
888      * @param name an enumerated cache type.
889      */

890     public void setCache(CacheName name) {
891         cacheName = name;
892     }
893
894     /**
895      * The enumerated type for cache.
896      * The values are "propertyfile".
897      */

898     public static class CacheName extends EnumeratedAttribute {
899         /** @see EnumeratedAttribute#getValues() */
900         /** {@inheritDoc} */
901         public String JavaDoc[] getValues() {
902             return new String JavaDoc[] {"propertyfile" };
903         }
904     }
905
906     /**
907      * Get the algorithm type to use.
908      * @return the enumerated algorithm type
909      */

910     public Algorithm getAlgorithm() { return algorithm; }
911
912     /**
913      * Set the algorithm type to use.
914      * @param name an enumerated algorithm type.
915      */

916     public void setAlgorithm(AlgorithmName name) {
917         algoName = name;
918     }
919
920     /**
921      * The enumerated type for algorithm.
922      * The values are "hashValue", "digest" and "checksum".
923      */

924     public static class AlgorithmName extends EnumeratedAttribute {
925         /** @see EnumeratedAttribute#getValues() */
926         /** {@inheritDoc} */
927         public String JavaDoc[] getValues() {
928             return new String JavaDoc[] {"hashvalue", "digest", "checksum" };
929         }
930     }
931
932     /**
933      * Get the comparator type to use.
934      * @return the enumerated comparator type
935      */

936     public Comparator JavaDoc getComparator() { return comparator; }
937
938     /**
939      * Set the comparator type to use.
940      * @param name an enumerated comparator type.
941      */

942     public void setComparator(ComparatorName name) {
943         compName = name;
944     }
945
946     /**
947      * The enumerated type for algorithm.
948      * The values are "equal" and "rule".
949      */

950     public static class ComparatorName extends EnumeratedAttribute {
951         /** @see EnumeratedAttribute#getValues() */
952         /** {@inheritDoc} */
953         public String JavaDoc[] getValues() {
954             return new String JavaDoc[] {"equal", "rule" };
955         }
956     }
957
958 }
959
Popular Tags