Hi! I plan to use ant & batik to build a project web page. For this I had a tree of SVG sources and an ant task to rasterize them. I was surprised to find that the tree structure was lost and instead all result images put directly into the target directory. Most other ant tasks keep directory structures, relative to the base directory of a fileset.
I decided to try to address this issue. In order to allow for even more flexibility, I plugged in a mapper as well. Now people can use mappers to control what source files will get transformed to what result files. The current state of the patch reflects behaviour as I would wish it to be. It is, however, an incompatible modification, as other builds might rely on the flattening. If you are concerned about backwards compatibility, I can think of two possibilities: 1. Use flattening whenever no mapper is present. 2. Provide a flatten attribute, defaulting to yes. I think I would prefer the latter, but would like your opinion whether we should aim for backwards compatibility at all in the first place. And of course I'd be grateful for any kind of useful comment you have about my modifications. The patch also modifies the build.xml file in order to help people to avoid build.sh resp. build.bat. There are classpath elements pointing at batik as well as inclusions for jar files from a lib directory where people could simply drop dependencies. Greetings, Martin von Gagern
Property changes on: contrib/rasterizertask
___________________________________________________________________
Added: svn:ignore
+ build
Index:
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverter.java
===================================================================
---
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverter.java
(revision 0)
+++
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverter.java
(revision 0)
@@ -0,0 +1,140 @@
+/*
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.apache.tools.ant.taskdefs.optional;
+
+
+// -- Batik classes ----------------------------------------------------------
+import org.apache.batik.apps.rasterizer.SVGConverter;
+import org.apache.batik.apps.rasterizer.SVGConverterException;
+import org.apache.batik.apps.rasterizer.SVGConverterFileSource;
+import org.apache.batik.apps.rasterizer.SVGConverterSource;
+
+// -- Ant classes ------------------------------------------------------------
+import org.apache.tools.ant.Task;
+
+// -- Java SDK classes -------------------------------------------------------
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * An <code>SVGConverter</code> with an explicit destination for each source.
+ *
+ * @author <a href="mailto:[email protected]">Martin von Gagern</a>
+ * @version $Id$
+ */
+class RasterizerTaskSVGConverter extends SVGConverter {
+
+ // -- Variables ----------------------------------------------------------
+
+ /**
+ * Ant task that is used to log messages.
+ */
+ private Task executingTask;
+
+ /**
+ * List of sources.
+ * Elements are expected to be {...@link File}s.
+ * It is not possible (yet) to reference parts of a file or an URL
+ * in this way.
+ */
+ private List sourceFiles;
+
+ /**
+ * List of destinations.
+ * Elements are expected to be {...@link File}s.
+ * If <code>appendFileNames</code> is <code>true</code>, the items of
+ * this list are interpreted as directories, and default file names
+ * derived from the names of the corresponding source files will be
+ * appended. Otherwise, the item will be interpreted as a file name
+ * in its own right.
+ */
+ private List destinations;
+
+ /**
+ * Determines whether to append file names to destination paths.
+ */
+ private boolean appendFileNames;
+
+
+ // -- Constructors -------------------------------------------------------
+
+ /**
+ * Sets the given Ant task to receive log messages.
+ * The value can be <code>null</code> when log messages won't be written.
+ *
+ * @param task Ant task to receive log messages or <code>null</code>
+ */
+ public RasterizerTaskSVGConverter(Task task) {
+ super(new RasterizerTaskSVGConverterController(task));
+ executingTask = task;
+ }
+
+ // -- Public interface ---------------------------------------------------
+
+ public void setSourceFiles(List sources) {
+ this.sourceFiles = sources;
+ }
+
+ public void setDestinationFiles(List destinations) {
+ this.destinations = destinations;
+ appendFileNames = false;
+ }
+
+ public void setDestinationDirectories(List destinations) {
+ this.destinations = destinations;
+ appendFileNames = true;
+ }
+
+
+ // -- Overrides to protected interface -----------------------------------
+
+ protected List computeSources() throws SVGConverterException {
+ List sources = new ArrayList(sourceFiles.size());
+ for (int i = 0; i < sourceFiles.size(); ++i) {
+ File file = (File)sourceFiles.get(i);
+ SVGConverterSource source;
+ source = new SVGConverterFileSource(file);
+ sources.add(source);
+ }
+ return sources;
+ }
+
+ protected List computeDstFiles(List sources)
+ throws SVGConverterException {
+ if (destinations.size() != sources.size())
+ throw new IllegalStateException("Length mismatch: " +
+ destinations.size() + " destinations for " +
+ sources.size() + " sources");
+ if (!appendFileNames)
+ return destinations;
+ List destFiles = new ArrayList(destinations.size());
+ for (int i = 0; i < destinations.size(); ++i) {
+ SVGConverterSource src = (SVGConverterSource)sources.get(i);
+ File dir = (File)destinations.get(i);
+ String name = getDestinationFile(src.getName());
+ File file = new File(dir, name);
+ destFiles.add(file);
+ }
+ return destFiles;
+ }
+
+}
Index:
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverterController.java
===================================================================
---
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverterController.java
(revision 745109)
+++
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTaskSVGConverterController.java
(working copy)
@@ -83,6 +83,11 @@
public boolean proceedWithSourceTranscoding(SVGConverterSource source,
File dest) {
+ if(executingTask != null) {
+ executingTask.log("Converting '"
+ + source.toString() + "' to '"
+ + dest.toString() + "'.");
+ }
return true;
}
Index:
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTask.java
===================================================================
---
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTask.java
(revision 745109)
+++
contrib/rasterizertask/sources/org/apache/tools/ant/taskdefs/optional/RasterizerTask.java
(working copy)
@@ -26,10 +26,11 @@
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.util.JAXPUtils;
+import org.apache.tools.ant.util.FileNameMapper;
// -- Batik classes ----------------------------------------------------------
-import org.apache.batik.apps.rasterizer.SVGConverter;
import org.apache.batik.apps.rasterizer.DestinationType;
import org.apache.batik.apps.rasterizer.SVGConverterException;
import org.apache.batik.transcoder.image.JPEGTranscoder;
@@ -47,6 +48,7 @@
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
+import java.util.Collections;
@@ -116,9 +118,11 @@
protected File destDir = null;
/** Contents of <code>fileset</code> elements. */
protected Vector filesets = new Vector();
+ /** Contents of <code>mapper</code> elements. */
+ protected Mapper mapperElement = null;
/** Converter object used to convert SVG images to raster images. */
- protected SVGConverter converter;
+ protected RasterizerTaskSVGConverter converter;
@@ -127,7 +131,6 @@
* Initializes a new rasterizer task.
*/
public RasterizerTask() {
- converter = new SVGConverter(new
RasterizerTaskSVGConverterController(this));
}
@@ -335,6 +338,31 @@
}
/**
+ * Creates <code>mapper</code> child element.
+ *
+ * <p>A <code>mapper</code> element can be used to specify
+ * the output file(s) for every input file in a flexible way.</p>
+ *
+ * @return the <code>mapper</code> element to be configured by Ant
+ */
+ public Mapper createMapper() throws BuildException {
+ if (mapperElement != null) {
+ throw new BuildException("Cannot define more than one mapper",
+ getLocation());
+ }
+ mapperElement = new Mapper(getProject());
+ return mapperElement;
+ }
+
+ /**
+ * Add a nested file name mapper.
+ * @param fileNameMapper the mapper to add.
+ */
+ public void add(FileNameMapper fileNameMapper) {
+ createMapper().add(fileNameMapper);
+ }
+
+ /**
* Validates and sets input values and files, then starts the conversion
* process.
*
@@ -345,8 +373,6 @@
*/
public void execute() throws BuildException {
- String[] sources; // Array of input files.
-
// Store default XML parser information and set user class.
String defaultParser = XMLResourceDescriptor.getXMLParserClassName();
// Throws BuildException.
@@ -367,26 +393,23 @@
}
}
+ // Actually create our converter
+ converter = new RasterizerTaskSVGConverter(this);
+
// Throws BuildException.
setRasterizingParameters();
- // Get and set source(s).
- sources = getSourceFiles();
- converter.setSources(sources);
+ // Get and set source(s) and destination(s).
+ setFileLists();
- // Set destination.
- if(this.srcFile != null) {
- converter.setDst(this.destFile);
- } else {
- converter.setDst(this.destDir);
- }
-
// Input filenames are stored in the converter and
// everything is ready for the conversion.
+ /*
log("Rasterizing " + sources.length +
(sources.length == 1 ? " image " : " images ") +
"from SVG to " + this.resultType.toString() + ".");
+ */
try {
converter.execute();
@@ -394,6 +417,8 @@
throw new BuildException(sce.getMessage());
}
} finally {
+ converter = null; // just to make sure it won't be reused
+
// Restore default XML parser for the next execute.
XMLResourceDescriptor.setXMLParserClassName(defaultParser);
}
@@ -487,51 +512,73 @@
*
* @return Array of source filename strings.
*/
- protected String[] getSourceFiles() {
+ protected void setFileLists() {
- List inputFiles = new ArrayList(); // Input files in temp list.
-
if(this.srcFile != null) {
// Only one source and destination file have been set.
- inputFiles.add(this.srcFile.getAbsolutePath());
+ List srcs = Collections.singletonList(srcFile);
+ List dests = Collections.singletonList(destFile);
+ converter.setSourceFiles(srcs);
+ converter.setDestinationFiles(dests);
} else {
// Unknown number of files have to be converted. destdir
// attribute and either srcdir attribute or fileset element
// have been set.
+ List srcs = new ArrayList(); // Input files
+ List dests = new ArrayList(); // Output dirs or files
+ List filesets = this.filesets; // local reference, modifyable
+ FileNameMapper mapper = null;
+ if (mapperElement != null)
+ mapper = mapperElement.getImplementation();
+
// Read source files from the child patterns.
// The value of srcdir attribute overrides the dir attribute in
// fileset element.
if(this.srcDir != null) {
// fileset is declared in the super class.
- // Scan to get all the files in srcdir directory that
- // should be in input files.
+ // Add to list of filesets in order to get all the files
+ // in srcdir directory that should be in input files.
fileset.setDir(this.srcDir);
- DirectoryScanner ds = fileset.getDirectoryScanner(project);
- String[] includedFiles = ds.getIncludedFiles();
- // Add file and its path to the input file vector.
- for (int j = 0 ; j < includedFiles.length ; j++) {
- File newFile = new File(srcDir.getPath(),
includedFiles[j]);
- inputFiles.add(newFile.getAbsolutePath());
- }
+ filesets = new ArrayList(filesets); // local copy, just in case
+ filesets.add(fileset);
}
- // Read source files from child filesets.
+
+ // Read source files from child filesets and child patterns.
for (int i = 0 ; i < filesets.size() ; i++) {
// Scan to get all the files in this fileset that
// should be in input files.
- FileSet fs = (FileSet) filesets.elementAt(i);
+ FileSet fs = (FileSet) filesets.get(i);
+ File fsDir = fs.getDir(project);
DirectoryScanner ds = fs.getDirectoryScanner(project);
String[] includedFiles = ds.getIncludedFiles();
// Add file and its path to the input file vector.
for (int j = 0 ; j < includedFiles.length ; j++) {
- File newFile = new File(fs.getDir(project).getPath(),
includedFiles[j]);
- inputFiles.add(newFile.getAbsolutePath());
+ File src = new File(fsDir, includedFiles[j]);
+ if (mapper == null) {
+ File dest = new File(destDir, includedFiles[j]);
+ srcs.add(src);
+ dests.add(dest.getParentFile()); // destination dir
+ }
+ else {
+ String[] mapped = mapper.mapFileName(includedFiles[j]);
+ if (mapped != null) {
+ for (int k = 0; k < mapped.length; ++k) {
+ File dest = new File(destDir, mapped[k]);
+ srcs.add(src);
+ dests.add(dest);
+ }
+ }
+ }
}
}
+
+ converter.setSourceFiles(srcs);
+ if (mapper == null)
+ converter.setDestinationDirectories(dests);
+ else
+ converter.setDestinationFiles(dests);
}
-
- // Convert List to array and return the array.
- return (String[])inputFiles.toArray(new String[0]);
}
/**
Index: contrib/rasterizertask/build.xml
===================================================================
--- contrib/rasterizertask/build.xml (revision 745109)
+++ contrib/rasterizertask/build.xml (working copy)
@@ -68,7 +68,12 @@
description="Compiles source files.">
<mkdir dir="${build.classes}" />
<!-- Compile code. -->
- <javac srcdir="${src}" destdir="${build.classes}" />
+ <javac srcdir="${src}" destdir="${build.classes}" debug="true">
+ <classpath>
+ <pathelement location="../../classes"/>
+ <fileset dir="." includes="lib/**/*.jar"/>
+ </classpath>
+ </javac>
</target>
<target name="jar" depends="prepare, compile"
signature.asc
Description: OpenPGP digital signature
