source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 31.5 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs;
19
20import java.io.File;
21import java.util.Enumeration;
22import java.util.Vector;
23import org.apache.tools.ant.AntClassLoader;
24import org.apache.tools.ant.BuildException;
25import org.apache.tools.ant.DirectoryScanner;
26import org.apache.tools.ant.DynamicConfigurator;
27import org.apache.tools.ant.Project;
28import org.apache.tools.ant.types.Mapper;
29import org.apache.tools.ant.types.Path;
30import org.apache.tools.ant.types.Reference;
31import org.apache.tools.ant.types.XMLCatalog;
32import org.apache.tools.ant.util.FileNameMapper;
33import org.apache.tools.ant.util.FileUtils;
34
35/**
36 * Processes a set of XML documents via XSLT. This is
37 * useful for building views of XML based documentation.
38 *
39 *
40 * @since Ant 1.1
41 *
42 * @ant.task name="xslt" category="xml"
43 */
44
45public class XSLTProcess extends MatchingTask implements XSLTLogger {
46 /** destination directory */
47 private File destDir = null;
48
49 /** where to find the source XML file, default is the project's basedir */
50 private File baseDir = null;
51
52 /** XSL stylesheet */
53 private String xslFile = null;
54
55 /** extension of the files produced by XSL processing */
56 private String targetExtension = ".html";
57
58 /** additional parameters to be passed to the stylesheets */
59 private Vector params = new Vector();
60
61 /** Input XML document to be used */
62 private File inFile = null;
63
64 /** Output file */
65 private File outFile = null;
66
67 /** The name of the XSL processor to use */
68 private String processor;
69
70 /** Classpath to use when trying to load the XSL processor */
71 private Path classpath = null;
72
73 /** The Liason implementation to use to communicate with the XSL
74 * processor */
75 private XSLTLiaison liaison;
76
77 /** Flag which indicates if the stylesheet has been loaded into
78 * the processor */
79 private boolean stylesheetLoaded = false;
80
81 /** force output of target files even if they already exist */
82 private boolean force = false;
83
84 /** Utilities used for file operations */
85 private FileUtils fileUtils;
86
87 /** XSL output properties to be used */
88 private Vector outputProperties = new Vector();
89
90 /** for resolving entities such as dtds */
91 private XMLCatalog xmlCatalog = new XMLCatalog();
92
93 /** Name of the TRAX Liaison class */
94 private static final String TRAX_LIAISON_CLASS =
95 "org.apache.tools.ant.taskdefs.optional.TraXLiaison";
96
97 /** Name of the now-deprecated XSLP Liaison class */
98 private static final String XSLP_LIAISON_CLASS =
99 "org.apache.tools.ant.taskdefs.optional.XslpLiaison";
100
101 /** Name of the now-deprecated Xalan liaison class */
102 private static final String XALAN_LIAISON_CLASS =
103 "org.apache.tools.ant.taskdefs.optional.XalanLiaison";
104
105 /**
106 * Whether to style all files in the included directories as well.
107 *
108 * @since Ant 1.5
109 */
110 private boolean performDirectoryScan = true;
111
112 /**
113 * factory element for TraX processors only
114 * @since Ant 1.6
115 */
116 private Factory factory = null;
117
118 /**
119 * whether to reuse Transformer if transforming multiple files.
120 * @since 1.5.2
121 */
122 private boolean reuseLoadedStylesheet = true;
123
124 /**
125 * AntClassLoader for the nested <classpath> - if set.
126 *
127 * <p>We keep this here in order to reset the context classloader
128 * in execute. We can't use liaison.getClass().getClassLoader()
129 * since the actual liaison class may have been loaded by a loader
130 * higher up (system classloader, for example).</p>
131 *
132 * @since Ant 1.6.2
133 */
134 private AntClassLoader loader = null;
135
136 /**
137 * Mapper to use when a set of files gets processed.
138 *
139 * @since Ant 1.6.2
140 */
141 private Mapper mapperElement = null;
142
143 /**
144 * Creates a new XSLTProcess Task.
145 */
146 public XSLTProcess() {
147 fileUtils = FileUtils.newFileUtils();
148 } //-- XSLTProcess
149
150 /**
151 * Whether to style all files in the included directories as well;
152 * optional, default is true.
153 *
154 * @param b true if files in included directories are processed.
155 * @since Ant 1.5
156 */
157 public void setScanIncludedDirectories(boolean b) {
158 performDirectoryScan = b;
159 }
160
161 /**
162 * Controls whether the stylesheet is reloaded for every transform.
163 *
164 * <p>Setting this to true may get around a bug in certain
165 * Xalan-J versions, default is false.</p>
166 *
167 * @since Ant 1.5.2
168 */
169 public void setReloadStylesheet(boolean b) {
170 reuseLoadedStylesheet = !b;
171 }
172
173 /**
174 * Defines the mapper to map source to destination files.
175 * @exception BuildException if more than one mapper is defined
176 * @since Ant 1.6.2
177 */
178 public void addMapper(Mapper mapper) {
179 if (mapperElement != null) {
180 throw new BuildException("Cannot define more than one mapper",
181 getLocation());
182 }
183 mapperElement = mapper;
184 }
185
186 /**
187 * Executes the task.
188 *
189 * @exception BuildException if there is an execution problem.
190 * @todo validate that if either in or our is defined, then both are
191 */
192 public void execute() throws BuildException {
193 File savedBaseDir = baseDir;
194
195 DirectoryScanner scanner;
196 String[] list;
197 String[] dirs;
198
199 if (xslFile == null) {
200 throw new BuildException("no stylesheet specified", getLocation());
201 }
202
203 if (inFile != null && !inFile.exists()) {
204 throw new BuildException("input file " + inFile.toString() + " does not exist", getLocation());
205 }
206
207 try {
208 if (baseDir == null) {
209 baseDir = getProject().resolveFile(".");
210 }
211
212 liaison = getLiaison();
213
214 // check if liaison wants to log errors using us as logger
215 if (liaison instanceof XSLTLoggerAware) {
216 ((XSLTLoggerAware) liaison).setLogger(this);
217 }
218
219 log("Using " + liaison.getClass().toString(), Project.MSG_VERBOSE);
220
221 File stylesheet = getProject().resolveFile(xslFile);
222 if (!stylesheet.exists()) {
223 stylesheet = fileUtils.resolveFile(baseDir, xslFile);
224 /*
225 * shouldn't throw out deprecation warnings before we know,
226 * the wrong version has been used.
227 */
228 if (stylesheet.exists()) {
229 log("DEPRECATED - the style attribute should be relative "
230 + "to the project\'s");
231 log(" basedir, not the tasks\'s basedir.");
232 }
233 }
234
235 // if we have an in file and out then process them
236 if (inFile != null && outFile != null) {
237 process(inFile, outFile, stylesheet);
238 return;
239 }
240
241 /*
242 * if we get here, in and out have not been specified, we are
243 * in batch processing mode.
244 */
245
246 //-- make sure Source directory exists...
247 if (destDir == null) {
248 String msg = "destdir attributes must be set!";
249 throw new BuildException(msg);
250 }
251 scanner = getDirectoryScanner(baseDir);
252 log("Transforming into " + destDir, Project.MSG_INFO);
253
254 // Process all the files marked for styling
255 list = scanner.getIncludedFiles();
256 for (int i = 0; i < list.length; ++i) {
257 process(baseDir, list[i], destDir, stylesheet);
258 }
259 if (performDirectoryScan) {
260 // Process all the directories marked for styling
261 dirs = scanner.getIncludedDirectories();
262 for (int j = 0; j < dirs.length; ++j) {
263 list = new File(baseDir, dirs[j]).list();
264 for (int i = 0; i < list.length; ++i) {
265 process(baseDir, dirs[j] + File.separator + list[i],
266 destDir, stylesheet);
267 }
268 }
269 }
270 } finally {
271 if (loader != null) {
272 loader.resetThreadContextLoader();
273 loader = null;
274 }
275 liaison = null;
276 stylesheetLoaded = false;
277 baseDir = savedBaseDir;
278 }
279 }
280
281 /**
282 * Set whether to check dependencies, or always generate;
283 * optional, default is false.
284 *
285 * @param force true if always generate.
286 */
287 public void setForce(boolean force) {
288 this.force = force;
289 }
290
291 /**
292 * Set the base directory;
293 * optional, default is the project's basedir.
294 *
295 * @param dir the base directory
296 **/
297 public void setBasedir(File dir) {
298 baseDir = dir;
299 }
300
301 /**
302 * Set the destination directory into which the XSL result
303 * files should be copied to;
304 * required, unless <tt>in</tt> and <tt>out</tt> are
305 * specified.
306 * @param dir the name of the destination directory
307 **/
308 public void setDestdir(File dir) {
309 destDir = dir;
310 }
311
312 /**
313 * Set the desired file extension to be used for the target;
314 * optional, default is html.
315 * @param name the extension to use
316 **/
317 public void setExtension(String name) {
318 targetExtension = name;
319 }
320
321 /**
322 * Name of the stylesheet to use - given either relative
323 * to the project's basedir or as an absolute path; required.
324 *
325 * @param xslFile the stylesheet to use
326 */
327 public void setStyle(String xslFile) {
328 this.xslFile = xslFile;
329 }
330
331 /**
332 * Set the optional classpath to the XSL processor
333 *
334 * @param classpath the classpath to use when loading the XSL processor
335 */
336 public void setClasspath(Path classpath) {
337 createClasspath().append(classpath);
338 }
339
340 /**
341 * Set the optional classpath to the XSL processor
342 *
343 * @return a path instance to be configured by the Ant core.
344 */
345 public Path createClasspath() {
346 if (classpath == null) {
347 classpath = new Path(getProject());
348 }
349 return classpath.createPath();
350 }
351
352 /**
353 * Set the reference to an optional classpath to the XSL processor
354 *
355 * @param r the id of the Ant path instance to act as the classpath
356 * for loading the XSL processor
357 */
358 public void setClasspathRef(Reference r) {
359 createClasspath().setRefid(r);
360 }
361
362 /**
363 * Set the name of the XSL processor to use; optional, default trax.
364 * Other values are "xalan" for Xalan1 and "xslp" for XSL:P, though the
365 * later is strongly deprecated.
366 *
367 * @param processor the name of the XSL processor
368 */
369 public void setProcessor(String processor) {
370 this.processor = processor;
371 }
372
373 /**
374 * Add the catalog to our internal catalog
375 *
376 * @param xmlCatalog the XMLCatalog instance to use to look up DTDs
377 */
378 public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog) {
379 this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog);
380 }
381
382 /**
383 * Load processor here instead of in setProcessor - this will be
384 * called from within execute, so we have access to the latest
385 * classpath.
386 *
387 * @param proc the name of the processor to load.
388 * @exception Exception if the processor cannot be loaded.
389 */
390 private void resolveProcessor(String proc) throws Exception {
391 if (proc.equals("trax")) {
392 final Class clazz = loadClass(TRAX_LIAISON_CLASS);
393 liaison = (XSLTLiaison) clazz.newInstance();
394 } else if (proc.equals("xslp")) {
395 log("DEPRECATED - xslp processor is deprecated. Use trax "
396 + "instead.");
397 final Class clazz = loadClass(XSLP_LIAISON_CLASS);
398 liaison = (XSLTLiaison) clazz.newInstance();
399 } else if (proc.equals("xalan")) {
400 log("DEPRECATED - xalan processor is deprecated. Use trax "
401 + "instead.");
402 final Class clazz = loadClass(XALAN_LIAISON_CLASS);
403 liaison = (XSLTLiaison) clazz.newInstance();
404 } else {
405 liaison = (XSLTLiaison) loadClass(proc).newInstance();
406 }
407 }
408
409 /**
410 * Load named class either via the system classloader or a given
411 * custom classloader.
412 *
413 * @param classname the name of the class to load.
414 * @return the requested class.
415 * @exception Exception if the class could not be loaded.
416 */
417 private Class loadClass(String classname) throws Exception {
418 if (classpath == null) {
419 return Class.forName(classname);
420 } else {
421 loader = getProject().createClassLoader(classpath);
422 loader.setThreadContextLoader();
423 Class c = Class.forName(classname, true, loader);
424 return c;
425 }
426 }
427
428 /**
429 * Specifies the output name for the styled result from the
430 * <tt>in</tt> attribute; required if <tt>in</tt> is set
431 *
432 * @param outFile the output File instance.
433 */
434 public void setOut(File outFile) {
435 this.outFile = outFile;
436 }
437
438 /**
439 * specifies a single XML document to be styled. Should be used
440 * with the <tt>out</tt> attribute; ; required if <tt>out</tt> is set
441 *
442 * @param inFile the input file
443 */
444 public void setIn(File inFile) {
445 this.inFile = inFile;
446 }
447
448 /**
449 * Processes the given input XML file and stores the result
450 * in the given resultFile.
451 *
452 * @param baseDir the base directory for resolving files.
453 * @param xmlFile the input file
454 * @param destDir the destination directory
455 * @param stylesheet the stylesheet to use.
456 * @exception BuildException if the processing fails.
457 */
458 private void process(File baseDir, String xmlFile, File destDir,
459 File stylesheet)
460 throws BuildException {
461
462 File outFile = null;
463 File inFile = null;
464
465 try {
466 long styleSheetLastModified = stylesheet.lastModified();
467 inFile = new File(baseDir, xmlFile);
468
469 if (inFile.isDirectory()) {
470 log("Skipping " + inFile + " it is a directory.",
471 Project.MSG_VERBOSE);
472 return;
473 }
474
475 FileNameMapper mapper = null;
476 if (mapperElement != null) {
477 mapper = mapperElement.getImplementation();
478 } else {
479 mapper = new StyleMapper();
480 }
481
482 String[] outFileName = mapper.mapFileName(xmlFile);
483 if (outFileName == null || outFileName.length == 0) {
484 log("Skipping " + inFile + " it cannot get mapped to output.",
485 Project.MSG_VERBOSE);
486 return;
487 } else if (outFileName == null || outFileName.length > 1) {
488 log("Skipping " + inFile + " its mapping is ambiguos.",
489 Project.MSG_VERBOSE);
490 return;
491 }
492
493 outFile = new File(destDir, outFileName[0]);
494
495 if (force
496 || inFile.lastModified() > outFile.lastModified()
497 || styleSheetLastModified > outFile.lastModified()) {
498 ensureDirectoryFor(outFile);
499 log("Processing " + inFile + " to " + outFile);
500
501 configureLiaison(stylesheet);
502 liaison.transform(inFile, outFile);
503 }
504 } catch (Exception ex) {
505 // If failed to process document, must delete target document,
506 // or it will not attempt to process it the second time
507 log("Failed to process " + inFile, Project.MSG_INFO);
508 if (outFile != null) {
509 outFile.delete();
510 }
511
512 throw new BuildException(ex);
513 }
514
515 } //-- processXML
516
517 /**
518 * Process the input file to the output file with the given stylesheet.
519 *
520 * @param inFile the input file to process.
521 * @param outFile the destination file.
522 * @param stylesheet the stylesheet to use.
523 * @exception BuildException if the processing fails.
524 */
525 private void process(File inFile, File outFile, File stylesheet)
526 throws BuildException {
527 try {
528 long styleSheetLastModified = stylesheet.lastModified();
529 log("In file " + inFile + " time: " + inFile.lastModified(),
530 Project.MSG_DEBUG);
531 log("Out file " + outFile + " time: " + outFile.lastModified(),
532 Project.MSG_DEBUG);
533 log("Style file " + xslFile + " time: " + styleSheetLastModified,
534 Project.MSG_DEBUG);
535 if (force || inFile.lastModified() >= outFile.lastModified()
536 || styleSheetLastModified >= outFile.lastModified()) {
537 ensureDirectoryFor(outFile);
538 log("Processing " + inFile + " to " + outFile,
539 Project.MSG_INFO);
540 configureLiaison(stylesheet);
541 liaison.transform(inFile, outFile);
542 } else {
543 log("Skipping input file " + inFile
544 + " because it is older than output file " + outFile
545 + " and so is the stylesheet " + stylesheet, Project.MSG_DEBUG);
546 }
547 } catch (Exception ex) {
548 log("Failed to process " + inFile, Project.MSG_INFO);
549 if (outFile != null) {
550 outFile.delete();
551 }
552 throw new BuildException(ex);
553 }
554 }
555
556 /**
557 * Ensure the directory exists for a given file
558 *
559 * @param targetFile the file for which the directories are required.
560 * @exception BuildException if the directories cannot be created.
561 */
562 private void ensureDirectoryFor(File targetFile)
563 throws BuildException {
564 File directory = fileUtils.getParentFile(targetFile);
565 if (!directory.exists()) {
566 if (!directory.mkdirs()) {
567 throw new BuildException("Unable to create directory: "
568 + directory.getAbsolutePath());
569 }
570 }
571 }
572
573 /**
574 * Get the factory instance configured for this processor
575 *
576 * @return the factory instance in use
577 */
578 public Factory getFactory() {
579 return factory;
580 }
581
582 /**
583 * Get the XML catalog containing entity definitions
584 *
585 * @return the XML catalog for the task.
586 */
587 public XMLCatalog getXMLCatalog() {
588 return xmlCatalog;
589 }
590
591 public Enumeration getOutputProperties() {
592 return outputProperties.elements();
593 }
594
595
596 /**
597 * Get the Liason implementation to use in processing.
598 *
599 * @return an instance of the XSLTLiason interface.
600 */
601 protected XSLTLiaison getLiaison() {
602 // if processor wasn't specified, see if TraX is available. If not,
603 // default it to xslp or xalan, depending on which is in the classpath
604 if (liaison == null) {
605 if (processor != null) {
606 try {
607 resolveProcessor(processor);
608 } catch (Exception e) {
609 throw new BuildException(e);
610 }
611 } else {
612 try {
613 resolveProcessor("trax");
614 } catch (Throwable e1) {
615 try {
616 resolveProcessor("xalan");
617 } catch (Throwable e2) {
618 try {
619 resolveProcessor("xslp");
620 } catch (Throwable e3) {
621 e3.printStackTrace();
622 e2.printStackTrace();
623 throw new BuildException(e1);
624 }
625 }
626 }
627 }
628 }
629 return liaison;
630 }
631
632 /**
633 * Create an instance of an XSL parameter for configuration by Ant.
634 *
635 * @return an instance of the Param class to be configured.
636 */
637 public Param createParam() {
638 Param p = new Param();
639 params.addElement(p);
640 return p;
641 }
642
643 /**
644 * The Param inner class used to store XSL parameters
645 */
646 public static class Param {
647 /** The parameter name */
648 private String name = null;
649
650 /** The parameter's value */
651 private String expression = null;
652
653 private String ifProperty;
654 private String unlessProperty;
655 private Project project;
656
657 /**
658 * Set the current project
659 *
660 * @param project the current project
661 */
662 public void setProject(Project project) {
663 this.project = project;
664 }
665
666 /**
667 * Set the parameter name.
668 *
669 * @param name the name of the parameter.
670 */
671 public void setName(String name) {
672 this.name = name;
673 }
674
675 /**
676 * The parameter value
677 * NOTE : was intended to be an XSL expression.
678 * @param expression the parameter's value.
679 */
680 public void setExpression(String expression) {
681 this.expression = expression;
682 }
683
684 /**
685 * Get the parameter name
686 *
687 * @return the parameter name
688 * @exception BuildException if the name is not set.
689 */
690 public String getName() throws BuildException {
691 if (name == null) {
692 throw new BuildException("Name attribute is missing.");
693 }
694 return name;
695 }
696
697 /**
698 * Get the parameter's value
699 *
700 * @return the parameter value
701 * @exception BuildException if the value is not set.
702 */
703 public String getExpression() throws BuildException {
704 if (expression == null) {
705 throw new BuildException("Expression attribute is missing.");
706 }
707 return expression;
708 }
709
710 /**
711 * Set whether this param should be used. It will be
712 * used if the property has been set, otherwise it won't.
713 * @param ifProperty name of property
714 */
715 public void setIf(String ifProperty) {
716 this.ifProperty = ifProperty;
717 }
718
719 /**
720 * Set whether this param should NOT be used. It
721 * will not be used if the property has been set, otherwise it
722 * will be used.
723 * @param unlessProperty name of property
724 */
725 public void setUnless(String unlessProperty) {
726 this.unlessProperty = unlessProperty;
727 }
728 /**
729 * Ensures that the param passes the conditions placed
730 * on it with <code>if</code> and <code>unless</code> properties.
731 */
732 public boolean shouldUse() {
733 if (ifProperty != null && project.getProperty(ifProperty) == null) {
734 return false;
735 } else if (unlessProperty != null
736 && project.getProperty(unlessProperty) != null) {
737 return false;
738 }
739
740 return true;
741 }
742 } // Param
743
744
745 /**
746 * Create an instance of an output property to be configured.
747 * @return the newly created output property.
748 * @since Ant 1.5
749 */
750 public OutputProperty createOutputProperty() {
751 OutputProperty p = new OutputProperty();
752 outputProperties.addElement(p);
753 return p;
754 }
755
756
757 /**
758 * Specify how the result tree should be output as specified
759 * in the <a href="http://www.w3.org/TR/xslt#output">
760 * specification</a>.
761 * @since Ant 1.5
762 */
763 public static class OutputProperty {
764 /** output property name */
765 private String name;
766
767 /** output property value */
768 private String value;
769
770 /**
771 * @return the output property name.
772 */
773 public String getName() {
774 return name;
775 }
776
777 /**
778 * set the name for this property
779 * @param name A non-null String that specifies an
780 * output property name, which may be namespace qualified.
781 */
782 public void setName(String name) {
783 this.name = name;
784 }
785
786 /**
787 * @return the output property value.
788 */
789 public String getValue() {
790 return value;
791 }
792
793 /**
794 * set the value for this property
795 * @param value The non-null string value of the output property.
796 */
797 public void setValue(String value) {
798 this.value = value;
799 }
800 }
801
802 /**
803 * Initialize internal instance of XMLCatalog
804 */
805 public void init() throws BuildException {
806 super.init();
807 xmlCatalog.setProject(getProject());
808 }
809
810 /**
811 * Loads the stylesheet and set xsl:param parameters.
812 *
813 * @param stylesheet the file form which to load the stylesheet.
814 * @exception BuildException if the stylesheet cannot be loaded.
815 */
816 protected void configureLiaison(File stylesheet) throws BuildException {
817 if (stylesheetLoaded && reuseLoadedStylesheet) {
818 return;
819 }
820 stylesheetLoaded = true;
821
822 try {
823 log("Loading stylesheet " + stylesheet, Project.MSG_INFO);
824 liaison.setStylesheet(stylesheet);
825 for (Enumeration e = params.elements(); e.hasMoreElements();) {
826 Param p = (Param) e.nextElement();
827 if (p.shouldUse()) {
828 liaison.addParam(p.getName(), p.getExpression());
829 }
830 }
831 if (liaison instanceof XSLTLiaison2) {
832 ((XSLTLiaison2) liaison).configure(this);
833 }
834 } catch (Exception ex) {
835 log("Failed to transform using stylesheet " + stylesheet,
836 Project.MSG_INFO);
837 throw new BuildException(ex);
838 }
839 }
840
841 /**
842 * Create the factory element to configure a trax liaison.
843 * @return the newly created factory element.
844 * @throws BuildException if the element is created more than one time.
845 */
846 public Factory createFactory() throws BuildException {
847 if (factory != null) {
848 throw new BuildException("'factory' element must be unique");
849 }
850 factory = new Factory();
851 return factory;
852 }
853
854 /**
855 * The factory element to configure a transformer factory
856 * @since Ant 1.6
857 */
858 public static class Factory {
859
860 /** the factory class name to use for TraXLiaison */
861 private String name;
862
863 /**
864 * the list of factory attributes to use for TraXLiaison
865 */
866 private Vector attributes = new Vector();
867
868 /**
869 * @return the name of the factory.
870 */
871 public String getName() {
872 return name;
873 }
874
875 /**
876 * Set the name of the factory
877 * @param name the name of the factory.
878 */
879 public void setName(String name) {
880 this.name = name;
881 }
882
883 /**
884 * Create an instance of a factory attribute.
885 * the newly created factory attribute
886 */
887 public void addAttribute(Attribute attr) {
888 attributes.addElement(attr);
889 }
890
891 /**
892 * return the attribute elements.
893 * @return the enumeration of attributes
894 */
895 public Enumeration getAttributes() {
896 return attributes.elements();
897 }
898
899 /**
900 * A JAXP factory attribute. This is mostly processor specific, for
901 * example for Xalan 2.3+, the following attributes could be set:
902 * <ul>
903 * <li>http://xml.apache.org/xalan/features/optimize (true|false) </li>
904 * <li>http://xml.apache.org/xalan/features/incremental (true|false) </li>
905 * </ul>
906 */
907 public static class Attribute implements DynamicConfigurator {
908
909 /** attribute name, mostly processor specific */
910 private String name;
911
912 /** attribute value, often a boolean string */
913 private Object value;
914
915 /**
916 * @return the attribute name.
917 */
918 public String getName() {
919 return name;
920 }
921
922 /**
923 * @return the output property value.
924 */
925 public Object getValue() {
926 return value;
927 }
928
929 public Object createDynamicElement(String name) throws BuildException {
930 return null;
931 }
932
933 public void setDynamicAttribute(String name, String value)
934 throws BuildException {
935 // only 'name' and 'value' exist.
936 if ("name".equalsIgnoreCase(name)) {
937 this.name = value;
938 } else if ("value".equalsIgnoreCase(name)) {
939 // a value must be of a given type
940 // say boolean|integer|string that are mostly used.
941 if ("true".equalsIgnoreCase(value)
942 || "false".equalsIgnoreCase(value)) {
943 this.value = new Boolean(value);
944 } else {
945 try {
946 this.value = new Integer(value);
947 } catch (NumberFormatException e) {
948 this.value = value;
949 }
950 }
951 } else {
952 throw new BuildException("Unsupported attribute: " + name);
953 }
954 }
955 } // -- class Attribute
956
957 } // -- class Factory
958
959 /**
960 * Mapper implementation of the "traditional" way &lt;xslt&gt;
961 * mapped filenames.
962 *
963 * <p>If the file has an extension, chop it off. Append whatever
964 * the user has specified as extension or ".html".</p>
965 *
966 * @since Ant 1.6.2
967 */
968 private class StyleMapper implements FileNameMapper {
969 public void setFrom(String from) {}
970 public void setTo(String to) {}
971 public String[] mapFileName(String xmlFile) {
972 int dotPos = xmlFile.lastIndexOf('.');
973 if (dotPos > 0) {
974 xmlFile = xmlFile.substring(0, dotPos);
975 }
976 return new String[] {xmlFile + targetExtension};
977 }
978 }
979
980}
Note: See TracBrowser for help on using the repository browser.