KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Replace


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.taskdefs;
20
21 import java.io.BufferedReader JavaDoc;
22 import java.io.BufferedWriter JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.FileOutputStream JavaDoc;
27 import java.io.FileReader JavaDoc;
28 import java.io.FileWriter JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStreamReader JavaDoc;
31 import java.io.OutputStreamWriter JavaDoc;
32 import java.io.Reader JavaDoc;
33 import java.io.Writer JavaDoc;
34 import java.util.Enumeration JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.Vector JavaDoc;
37 import org.apache.tools.ant.BuildException;
38 import org.apache.tools.ant.DirectoryScanner;
39 import org.apache.tools.ant.Project;
40 import org.apache.tools.ant.util.FileUtils;
41 import org.apache.tools.ant.util.StringUtils;
42
43 /**
44  * Replaces all occurrences of one or more string tokens with given
45  * values in the indicated files. Each value can be either a string
46  * or the value of a property available in a designated property file.
47  * If you want to replace a text that crosses line boundaries, you
48  * must use a nested <code>&lt;replacetoken&gt;</code> element.
49  *
50  * @since Ant 1.1
51  *
52  * @ant.task category="filesystem"
53  */

54 public class Replace extends MatchingTask {
55
56     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
57
58     private File JavaDoc src = null;
59     private NestedString token = null;
60     private NestedString value = new NestedString();
61
62     private File JavaDoc propertyFile = null;
63     private File JavaDoc replaceFilterFile = null;
64     private Properties JavaDoc properties = null;
65     private Vector JavaDoc replacefilters = new Vector JavaDoc();
66
67     private File JavaDoc dir = null;
68
69     private int fileCount;
70     private int replaceCount;
71     private boolean summary = false;
72
73     /** The encoding used to read and write files - if null, uses default */
74     private String JavaDoc encoding = null;
75
76     /**
77      * An inline string to use as the replacement text.
78      */

79     public class NestedString {
80
81         private StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
82
83         /**
84          * The text of the element.
85          *
86          * @param val the string to add
87          */

88         public void addText(String JavaDoc val) {
89             buf.append(val);
90         }
91
92         /**
93          * @return the text
94          */

95         public String JavaDoc getText() {
96             return buf.toString();
97         }
98     }
99
100     /**
101      * A filter to apply.
102      */

103     public class Replacefilter {
104         private String JavaDoc token;
105         private String JavaDoc value;
106         private String JavaDoc replaceValue;
107         private String JavaDoc property;
108
109         private StringBuffer JavaDoc inputBuffer;
110         private StringBuffer JavaDoc outputBuffer = new StringBuffer JavaDoc();
111
112         /**
113          * Validate the filter's configuration.
114          * @throws BuildException if any part is invalid.
115          */

116         public void validate() throws BuildException {
117             //Validate mandatory attributes
118
if (token == null) {
119                 String JavaDoc message = "token is a mandatory attribute "
120                     + "of replacefilter.";
121                 throw new BuildException(message);
122             }
123
124             if ("".equals(token)) {
125                 String JavaDoc message = "The token attribute must not be an empty "
126                     + "string.";
127                 throw new BuildException(message);
128             }
129
130             //value and property are mutually exclusive attributes
131
if ((value != null) && (property != null)) {
132                 String JavaDoc message = "Either value or property "
133                     + "can be specified, but a replacefilter "
134                     + "element cannot have both.";
135                 throw new BuildException(message);
136             }
137
138             if ((property != null)) {
139                 //the property attribute must have access to a property file
140
if (propertyFile == null) {
141                     String JavaDoc message = "The replacefilter's property attribute "
142                         + "can only be used with the replacetask's "
143                         + "propertyFile attribute.";
144                     throw new BuildException(message);
145                 }
146
147                 //Make sure property exists in property file
148
if (properties == null
149                     || properties.getProperty(property) == null) {
150                     String JavaDoc message = "property \"" + property
151                         + "\" was not found in " + propertyFile.getPath();
152                     throw new BuildException(message);
153                 }
154             }
155
156             replaceValue = getReplaceValue();
157         }
158
159         /**
160          * Get the replacement value for this filter token.
161          * @return the replacement value
162          */

163         public String JavaDoc getReplaceValue() {
164             if (property != null) {
165                 return properties.getProperty(property);
166             } else if (value != null) {
167                 return value;
168             } else if (Replace.this.value != null) {
169                 return Replace.this.value.getText();
170             } else {
171                 //Default is empty string
172
return "";
173             }
174         }
175
176         /**
177          * Set the token to replace.
178          * @param token <code>String</code> token.
179          */

180         public void setToken(String JavaDoc token) {
181             this.token = token;
182         }
183
184         /**
185          * Get the string to search for.
186          * @return current <code>String</code> token.
187          */

188         public String JavaDoc getToken() {
189             return token;
190         }
191
192         /**
193          * The replacement string; required if <code>property<code>
194          * is not set.
195          * @param value <code>String</code> value to replace.
196          */

197         public void setValue(String JavaDoc value) {
198             this.value = value;
199         }
200
201         /**
202          * Get replacement <code>String</code>.
203          * @return replacement or null.
204          */

205         public String JavaDoc getValue() {
206             return value;
207         }
208
209         /**
210          * Set the name of the property whose value is to serve as
211          * the replacement value; required if <code>value</code> is not set.
212          * @param property property name.
213          */

214         public void setProperty(String JavaDoc property) {
215             this.property = property;
216         }
217
218         /**
219          * Get the name of the property whose value is to serve as
220          * the replacement value.
221          * @return property or null.
222          */

223         public String JavaDoc getProperty() {
224             return property;
225         }
226
227         /**
228          * Retrieves the output buffer of this filter. The filter guarantees
229          * that data is only appended to the end of this StringBuffer.
230          * @return The StringBuffer containing the output of this filter.
231          */

232         StringBuffer JavaDoc getOutputBuffer() {
233             return outputBuffer;
234         }
235
236         /**
237          * Sets the input buffer for this filter.
238          * The filter expects from the component providing the input that data
239          * is only added by that component to the end of this StringBuffer.
240          * This StringBuffer will be modified by this filter, and expects that
241          * another component will only apped to this StringBuffer.
242          * @param input The input for this filter.
243          */

244         void setInputBuffer(StringBuffer JavaDoc input) {
245             inputBuffer = input;
246         }
247
248         /**
249          * Processes the buffer as far as possible. Takes into account that
250          * appended data may make it possible to replace the end of the already
251          * received data, when the token is split over the "old" and the "new"
252          * part.
253          * @return true if some data has been made available in the
254          * output buffer.
255          */

256         boolean process() {
257             if (inputBuffer.length() > token.length()) {
258                 int pos = replace();
259                 pos = Math.max((inputBuffer.length() - token.length()), pos);
260                 outputBuffer.append(inputBuffer.substring(0, pos));
261                 inputBuffer.delete(0, pos);
262                 return true;
263             }
264             return false;
265         }
266
267         /**
268          * Processes the buffer to the end. Does not take into account that
269          * appended data may make it possible to replace the end of the already
270          * received data.
271          */

272         void flush() {
273             replace();
274             // Avoid runtime problem on pre 1.4 when compiling post 1.4
275
outputBuffer.append(inputBuffer.toString());
276             inputBuffer.delete(0, inputBuffer.length());
277         }
278
279         /**
280          * Performs the replace operation.
281          * @return The position of the last character that was inserted as
282          * replacement.
283          */

284         private int replace() {
285             int found = inputBuffer.toString().indexOf(token);
286             int pos = -1;
287             while (found >= 0) {
288                 inputBuffer.replace(found, found + token.length(),
289                         replaceValue);
290                 pos = found + replaceValue.length();
291                 found = inputBuffer.toString().indexOf(token, pos);
292                 ++replaceCount;
293             }
294             return pos;
295         }
296     }
297
298     /**
299      * Class reading a file in small chunks, and presenting these chunks in
300      * a StringBuffer. Compatible with the Replacefilter.
301      * @since 1.7
302      */

303     private class FileInput {
304         private StringBuffer JavaDoc outputBuffer;
305         private Reader JavaDoc reader;
306         private char[] buffer;
307         private static final int BUFF_SIZE = 4096;
308
309         /**
310          * Constructs the input component. Opens the file for reading.
311          * @param source The file to read from.
312          * @throws IOException When the file cannot be read from.
313          */

314         FileInput(File JavaDoc source) throws IOException JavaDoc {
315             outputBuffer = new StringBuffer JavaDoc();
316             buffer = new char[BUFF_SIZE];
317             if (encoding == null) {
318                 reader = new BufferedReader JavaDoc(new FileReader JavaDoc(source));
319             } else {
320                 reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(
321                         new FileInputStream JavaDoc(source), encoding));
322             }
323         }
324
325         /**
326          * Retrieves the output buffer of this filter. The component guarantees
327          * that data is only appended to the end of this StringBuffer.
328          * @return The StringBuffer containing the output of this filter.
329          */

330         StringBuffer JavaDoc getOutputBuffer() {
331             return outputBuffer;
332         }
333
334         /**
335          * Reads some data from the file.
336          * @return true when the end of the file has not been reached.
337          * @throws IOException When the file cannot be read from.
338          */

339         boolean readChunk() throws IOException JavaDoc {
340             int bufferLength = 0;
341             bufferLength = reader.read(buffer);
342             if (bufferLength < 0) {
343                 return false;
344             }
345             outputBuffer.append(new String JavaDoc(buffer, 0, bufferLength));
346             return true;
347         }
348
349         /**
350          * Closes the file.
351          * @throws IOException When the file cannot be closed.
352          */

353         void close() throws IOException JavaDoc {
354             reader.close();
355         }
356
357         /**
358          * Closes file but doesn't throw exception
359          */

360         void closeQuietly() {
361             FileUtils.close(reader);
362         }
363
364     }
365
366     /**
367      * Component writing a file in chunks, taking the chunks from the
368      * Replacefilter.
369      * @since 1.7
370      */

371     private class FileOutput {
372         private StringBuffer JavaDoc inputBuffer;
373         private Writer JavaDoc writer;
374
375         /**
376          * Constructs the output component. Opens the file for writing.
377          * @param out The file to read to.
378          * @throws IOException When the file cannot be read from.
379          */

380         FileOutput(File JavaDoc out) throws IOException JavaDoc {
381                 if (encoding == null) {
382                     writer = new BufferedWriter JavaDoc(new FileWriter JavaDoc(out));
383                 } else {
384                     writer = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc
385                             (new FileOutputStream JavaDoc(out), encoding));
386                 }
387         }
388
389         /**
390          * Sets the input buffer for this component.
391          * The filter expects from the component providing the input that data
392          * is only added by that component to the end of this StringBuffer.
393          * This StringBuffer will be modified by this filter, and expects that
394          * another component will only append to this StringBuffer.
395          * @param input The input for this filter.
396          */

397         void setInputBuffer(StringBuffer JavaDoc input) {
398             inputBuffer = input;
399         }
400
401         /**
402          * Writes the buffer as far as possible.
403          * @return false to be inline with the Replacefilter.
404          * (Yes defining an interface crossed my mind, but would publish the
405          * internal behavior.)
406          * @throws IOException when the output cannot be written.
407          */

408         boolean process() throws IOException JavaDoc {
409             writer.write(inputBuffer.toString());
410             inputBuffer.delete(0, inputBuffer.length());
411             return false;
412         }
413
414         /**
415          * Processes the buffer to the end.
416          * @throws IOException when the output cannot be flushed.
417          */

418         void flush() throws IOException JavaDoc {
419             process();
420             writer.flush();
421         }
422
423         /**
424          * Closes the file.
425          * @throws IOException When the file cannot be closed.
426          */

427         void close() throws IOException JavaDoc {
428             writer.close();
429         }
430
431         /**
432          * Closes file but doesn't throw exception
433          */

434         void closeQuietly() {
435             FileUtils.close(writer);
436         }
437     }
438
439     /**
440      * Do the execution.
441      * @throws BuildException if we cant build
442      */

443     public void execute() throws BuildException {
444
445         Vector JavaDoc savedFilters = (Vector JavaDoc) replacefilters.clone();
446         Properties JavaDoc savedProperties =
447             properties == null ? null : (Properties JavaDoc) properties.clone();
448
449         if (token != null) {
450             // line separators in values and tokens are "\n"
451
// in order to compare with the file contents, replace them
452
// as needed
453
StringBuffer JavaDoc val = new StringBuffer JavaDoc(value.getText());
454             stringReplace(val, "\r\n", "\n");
455             stringReplace(val, "\n", StringUtils.LINE_SEP);
456             StringBuffer JavaDoc tok = new StringBuffer JavaDoc(token.getText());
457             stringReplace(tok, "\r\n", "\n");
458             stringReplace(tok, "\n", StringUtils.LINE_SEP);
459             Replacefilter firstFilter = createPrimaryfilter();
460             firstFilter.setToken(tok.toString());
461             firstFilter.setValue(val.toString());
462         }
463
464         try {
465             if (replaceFilterFile != null) {
466                 Properties JavaDoc props = getProperties(replaceFilterFile);
467                 Enumeration JavaDoc e = props.keys();
468                 while (e.hasMoreElements()) {
469                     String JavaDoc tok = e.nextElement().toString();
470                     Replacefilter replaceFilter = createReplacefilter();
471                     replaceFilter.setToken(tok);
472                     replaceFilter.setValue(props.getProperty(tok));
473                 }
474             }
475
476             validateAttributes();
477
478             if (propertyFile != null) {
479                 properties = getProperties(propertyFile);
480             }
481
482             validateReplacefilters();
483             fileCount = 0;
484             replaceCount = 0;
485
486             if (src != null) {
487                 processFile(src);
488             }
489
490             if (dir != null) {
491                 DirectoryScanner ds = super.getDirectoryScanner(dir);
492                 String JavaDoc[] srcs = ds.getIncludedFiles();
493
494                 for (int i = 0; i < srcs.length; i++) {
495                     File JavaDoc file = new File JavaDoc(dir, srcs[i]);
496                     processFile(file);
497                 }
498             }
499
500             if (summary) {
501                 log("Replaced " + replaceCount + " occurrences in "
502                     + fileCount + " files.", Project.MSG_INFO);
503             }
504         } finally {
505             replacefilters = savedFilters;
506             properties = savedProperties;
507         } // end of finally
508

509     }
510
511     /**
512      * Validate attributes provided for this task in .xml build file.
513      *
514      * @exception BuildException if any supplied attribute is invalid or any
515      * mandatory attribute is missing.
516      */

517     public void validateAttributes() throws BuildException {
518         if (src == null && dir == null) {
519             String JavaDoc message = "Either the file or the dir attribute "
520                 + "must be specified";
521             throw new BuildException(message, getLocation());
522         }
523         if (propertyFile != null && !propertyFile.exists()) {
524             String JavaDoc message = "Property file " + propertyFile.getPath()
525                 + " does not exist.";
526             throw new BuildException(message, getLocation());
527         }
528         if (token == null && replacefilters.size() == 0) {
529             String JavaDoc message = "Either token or a nested replacefilter "
530                 + "must be specified";
531             throw new BuildException(message, getLocation());
532         }
533         if (token != null && "".equals(token.getText())) {
534             String JavaDoc message = "The token attribute must not be an empty string.";
535             throw new BuildException(message, getLocation());
536         }
537     }
538
539     /**
540      * Validate nested elements.
541      *
542      * @exception BuildException if any supplied attribute is invalid or any
543      * mandatory attribute is missing.
544      */

545     public void validateReplacefilters()
546             throws BuildException {
547         for (int i = 0; i < replacefilters.size(); i++) {
548             Replacefilter element =
549                 (Replacefilter) replacefilters.elementAt(i);
550             element.validate();
551         }
552     }
553
554     /**
555      * Load a properties file.
556      * @param propertyFile the file to load the properties from.
557      * @return loaded <code>Properties</code> object.
558      * @throws BuildException if the file could not be found or read.
559      */

560     public Properties JavaDoc getProperties(File JavaDoc propertyFile) throws BuildException {
561         Properties JavaDoc props = new Properties JavaDoc();
562
563         FileInputStream JavaDoc in = null;
564         try {
565             in = new FileInputStream JavaDoc(propertyFile);
566             props.load(in);
567         } catch (FileNotFoundException JavaDoc e) {
568             String JavaDoc message = "Property file (" + propertyFile.getPath()
569                 + ") not found.";
570             throw new BuildException(message);
571         } catch (IOException JavaDoc e) {
572             String JavaDoc message = "Property file (" + propertyFile.getPath()
573                 + ") cannot be loaded.";
574             throw new BuildException(message);
575         } finally {
576             FileUtils.close(in);
577         }
578
579         return props;
580     }
581
582     /**
583      * Perform the replacement on the given file.
584      *
585      * The replacement is performed on a temporary file which then
586      * replaces the original file.
587      *
588      * @param src the source <code>File</code>.
589      */

590     private void processFile(File JavaDoc src) throws BuildException {
591         if (!src.exists()) {
592             throw new BuildException("Replace: source file " + src.getPath()
593                                      + " doesn't exist", getLocation());
594         }
595
596         File JavaDoc temp = null;
597         FileInput in = null;
598         FileOutput out = null;
599         try {
600             in = new FileInput(src);
601
602             temp = FILE_UTILS.createTempFile("rep", ".tmp",
603                     src.getParentFile());
604             out = new FileOutput(temp);
605
606             int repCountStart = replaceCount;
607
608             logFilterChain(src.getPath());
609
610             out.setInputBuffer(buildFilterChain(in.getOutputBuffer()));
611
612             while (in.readChunk()) {
613                 if (processFilterChain()) {
614                     out.process();
615                 }
616             }
617
618             flushFilterChain();
619
620             out.flush();
621             in.close();
622             in = null;
623             out.close();
624             out = null;
625
626             boolean changes = (replaceCount != repCountStart);
627             if (changes) {
628                 FILE_UTILS.rename(temp, src);
629                 temp = null;
630             }
631         } catch (IOException JavaDoc ioe) {
632             throw new BuildException("IOException in " + src + " - "
633                     + ioe.getClass().getName() + ":"
634                     + ioe.getMessage(), ioe, getLocation());
635         } finally {
636             if (null != in) {
637                 in.closeQuietly();
638             }
639             if (null != out) {
640                 out.closeQuietly();
641             }
642             if (temp != null) {
643                 if (!temp.delete()) {
644                     temp.deleteOnExit();
645                 }
646             }
647         }
648     }
649
650     /**
651      * Flushes all filters.
652      */

653     private void flushFilterChain() {
654         for (int i = 0; i < replacefilters.size(); i++) {
655             Replacefilter filter = (Replacefilter) replacefilters.elementAt(i);
656             filter.flush();
657         }
658     }
659
660     /**
661      * Performs the normal processing of the filters.
662      * @return true if the filter chain produced new output.
663      */

664     private boolean processFilterChain() {
665         for (int i = 0; i < replacefilters.size(); i++) {
666             Replacefilter filter = (Replacefilter) replacefilters.elementAt(i);
667             if (!filter.process()) {
668                 return false;
669             }
670         }
671         return true;
672     }
673
674     /**
675      * Creates the chain of filters to operate.
676      * @param inputBuffer <code>StringBuffer</code> containing the input for the
677      * first filter.
678      * @return <code>StringBuffer</code> containing the output of the last filter.
679      */

680     private StringBuffer JavaDoc buildFilterChain(StringBuffer JavaDoc inputBuffer) {
681         StringBuffer JavaDoc buf = inputBuffer;
682         for (int i = 0; i < replacefilters.size(); i++) {
683             Replacefilter filter = (Replacefilter) replacefilters.elementAt(i);
684             filter.setInputBuffer(buf);
685             buf = filter.getOutputBuffer();
686         }
687         return buf;
688     }
689
690     /**
691      * Logs the chain of filters to operate on the file.
692      * @param filename <code>String</code>.
693      */

694     private void logFilterChain(String JavaDoc filename) {
695         for (int i = 0; i < replacefilters.size(); i++) {
696             Replacefilter filter = (Replacefilter) replacefilters.elementAt(i);
697             log("Replacing in " + filename + ": " + filter.getToken()
698                     + " --> " + filter.getReplaceValue(), Project.MSG_VERBOSE);
699         }
700     }
701     /**
702      * Set the source file; required unless <code>dir</code> is set.
703      * @param file source <code>File</code>.
704      */

705     public void setFile(File JavaDoc file) {
706         this.src = file;
707     }
708
709     /**
710      * Indicates whether a summary of the replace operation should be
711      * produced, detailing how many token occurrences and files were
712      * processed; optional, default=<code>false</code>.
713      *
714      * @param summary <code>boolean</code> whether a summary of the
715      * replace operation should be logged.
716      */

717     public void setSummary(boolean summary) {
718         this.summary = summary;
719     }
720
721
722     /**
723      * Sets the name of a property file containing filters; optional.
724      * Each property will be treated as a replacefilter where token is the name
725      * of the property and value is the value of the property.
726      * @param replaceFilterFile <code>File</code> to load.
727      */

728     public void setReplaceFilterFile(File JavaDoc replaceFilterFile) {
729         this.replaceFilterFile = replaceFilterFile;
730     }
731
732     /**
733      * The base directory to use when replacing a token in multiple files;
734      * required if <code>file</code> is not defined.
735      * @param dir <code>File</code> representing the base directory.
736      */

737     public void setDir(File JavaDoc dir) {
738         this.dir = dir;
739     }
740
741     /**
742      * Set the string token to replace; required unless a nested
743      * <code>replacetoken</code> element or the <code>replacefilterfile</code>
744      * attribute is used.
745      * @param token token <code>String</code>.
746      */

747     public void setToken(String JavaDoc token) {
748         createReplaceToken().addText(token);
749     }
750
751     /**
752      * Set the string value to use as token replacement;
753      * optional, default is the empty string "".
754      * @param value replacement value.
755      */

756     public void setValue(String JavaDoc value) {
757         createReplaceValue().addText(value);
758     }
759
760     /**
761      * Set the file encoding to use on the files read and written by the task;
762      * optional, defaults to default JVM encoding.
763      *
764      * @param encoding the encoding to use on the files.
765      */

766     public void setEncoding(String JavaDoc encoding) {
767         this.encoding = encoding;
768     }
769
770     /**
771      * Create a token to filter as the text of a nested element.
772      * @return nested token <code>NestedString</code> to configure.
773      */

774     public NestedString createReplaceToken() {
775         if (token == null) {
776             token = new NestedString();
777         }
778         return token;
779     }
780
781     /**
782      * Create a string to replace the token as the text of a nested element.
783      * @return replacement value <code>NestedString</code> to configure.
784      */

785     public NestedString createReplaceValue() {
786         return value;
787     }
788
789     /**
790      * The name of a property file from which properties specified using nested
791      * <code>&lt;replacefilter&gt;</code> elements are drawn; required only if
792      * the <i>property</i> attribute of <code>&lt;replacefilter&gt;</code> is used.
793      * @param propertyFile <code>File</code> to load.
794      */

795     public void setPropertyFile(File JavaDoc propertyFile) {
796         this.propertyFile = propertyFile;
797     }
798
799     /**
800      * Add a nested &lt;replacefilter&gt; element.
801      * @return a nested <code>Replacefilter</code> object to be configured.
802      */

803     public Replacefilter createReplacefilter() {
804         Replacefilter filter = new Replacefilter();
805         replacefilters.addElement(filter);
806         return filter;
807     }
808
809     /**
810      * Adds the token and value as first &lt;replacefilter&gt; element.
811      * The token and value are always processed first.
812      * @return a nested <code>Replacefilter</code> object to be configured.
813      */

814     private Replacefilter createPrimaryfilter() {
815         Replacefilter filter = new Replacefilter();
816         replacefilters.insertElementAt(filter, 0);
817         return filter;
818     }
819
820     /**
821      * Replace occurrences of str1 in StringBuffer str with str2.
822      */

823     private void stringReplace(StringBuffer JavaDoc str, String JavaDoc str1, String JavaDoc str2) {
824         int found = str.toString().indexOf(str1);
825         while (found >= 0) {
826             str.replace(found, found + str1.length(), str2);
827             found = str.toString().indexOf(str1, found + str2.length());
828         }
829     }
830
831 }
832
Popular Tags