org.apache.fop.tools.EventProducerCollectorTask Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* 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.
*/
/* $Id: EventProducerCollectorTask.java 1761021 2016-09-16 11:40:57Z ssteiner $ */
package org.apache.fop.tools;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Node;
import org.apache.commons.io.IOUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.selectors.FilenameSelector;
import org.apache.fop.events.model.EventModel;
import org.apache.fop.events.model.EventProducerModel;
/**
* Ant task which inspects a file set for Java interfaces which extend the
* {@link org.apache.fop.events.EventProducer} interface. For all such interfaces an event model
* file and a translation file for the human-readable messages generated by the events is
* created and/or updated.
*/
public class EventProducerCollectorTask extends Task {
private List filesets = new java.util.ArrayList();
private File destDir;
private File translationFile;
/** {@inheritDoc} */
public void execute() throws BuildException {
try {
EventProducerCollector collector = new EventProducerCollector();
long lastModified = processFileSets(collector);
for (EventModel model : collector.getModels()) {
File parentDir = getParentDir(model);
if (!parentDir.exists() && !parentDir.mkdirs()) {
throw new BuildException(
"Could not create target directory for event model file: " + parentDir);
}
File modelFile = new File(parentDir, "event-model.xml");
if (!modelFile.exists() || lastModified > modelFile.lastModified()) {
model.saveToXML(modelFile);
log("Event model written to " + modelFile);
}
if (getTranslationFile() != null) {
// TODO Remove translation file creation facility?
if (!getTranslationFile().exists()
|| lastModified > getTranslationFile().lastModified()) {
updateTranslationFile(modelFile);
}
}
}
} catch (ClassNotFoundException e) {
throw new BuildException(e);
} catch (EventConventionException ece) {
throw new BuildException(ece);
} catch (IOException ioe) {
throw new BuildException(ioe);
}
}
private static final String MODEL2TRANSLATION = "model2translation.xsl";
private static final String MERGETRANSLATION = "merge-translation.xsl";
private File getParentDir(EventModel model) {
Iterator iter = model.getProducers();
assert iter.hasNext();
EventProducerModel producer = (EventProducerModel) iter.next();
assert !iter.hasNext();
String interfaceName = producer.getInterfaceName();
int startLocalName = interfaceName.lastIndexOf(".");
if (startLocalName < 0) {
return destDir;
} else {
String dirname = interfaceName.substring(0, startLocalName);
dirname = dirname.replace('.', File.separatorChar);
return new File(destDir, dirname);
}
}
/**
* Updates the translation file with new entries for newly found event producer methods.
* @param modelFile the model file to use
* @throws IOException if an I/O error occurs
*/
protected void updateTranslationFile(File modelFile) throws IOException {
try {
boolean resultExists = getTranslationFile().exists();
SAXTransformerFactory tFactory
= (SAXTransformerFactory)SAXTransformerFactory.newInstance();
//Generate fresh generated translation file as template
Source src = new StreamSource(modelFile.toURI().toURL().toExternalForm());
StreamSource xslt1 = new StreamSource(
getClass().getResourceAsStream(MODEL2TRANSLATION));
if (xslt1.getInputStream() == null) {
throw new FileNotFoundException(MODEL2TRANSLATION + " not found");
}
DOMResult domres = new DOMResult();
Transformer transformer = tFactory.newTransformer(xslt1);
transformer.transform(src, domres);
final Node generated = domres.getNode();
Node sourceDocument;
if (resultExists) {
//Load existing translation file into memory (because we overwrite it later)
src = new StreamSource(getTranslationFile().toURI().toURL().toExternalForm());
domres = new DOMResult();
transformer = tFactory.newTransformer();
transformer.transform(src, domres);
sourceDocument = domres.getNode();
} else {
//Simply use generated as source document
sourceDocument = generated;
}
//Generate translation file (with potentially new translations)
src = new DOMSource(sourceDocument);
//The following triggers a bug in older Xalan versions
//Result res = new StreamResult(getTranslationFile());
OutputStream out = new java.io.FileOutputStream(getTranslationFile());
out = new java.io.BufferedOutputStream(out);
Result res = new StreamResult(out);
try {
StreamSource xslt2 = new StreamSource(
getClass().getResourceAsStream(MERGETRANSLATION));
if (xslt2.getInputStream() == null) {
throw new FileNotFoundException(MERGETRANSLATION + " not found");
}
transformer = tFactory.newTransformer(xslt2);
transformer.setURIResolver(new URIResolver() {
public Source resolve(String href, String base) throws TransformerException {
if ("my:dom".equals(href)) {
return new DOMSource(generated);
}
return null;
}
});
if (resultExists) {
transformer.setParameter("generated-url", "my:dom");
}
transformer.transform(src, res);
if (resultExists) {
log("Translation file updated: " + getTranslationFile());
} else {
log("Translation file generated: " + getTranslationFile());
}
} finally {
IOUtils.closeQuietly(out);
}
} catch (TransformerException te) {
throw new IOException(te.getMessage());
}
}
/**
* Processes the file sets defined for the task.
* @param collector the collector to use for collecting the event producers
* @return the time of the latest modification of any of the files inspected
* @throws IOException if an I/O error occurs
* @throws EventConventionException if the EventProducer conventions are violated
* @throws ClassNotFoundException if a required class cannot be found
*/
protected long processFileSets(EventProducerCollector collector)
throws IOException, EventConventionException, ClassNotFoundException {
long lastModified = 0;
for (FileSet fs : filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
String[] srcFiles = ds.getIncludedFiles();
File directory = fs.getDir(getProject());
for (String filename : srcFiles) {
File src = new File(directory, filename);
boolean eventProducerFound = collector.scanFile(src);
if (eventProducerFound) {
lastModified = Math.max(lastModified, src.lastModified());
}
}
}
return lastModified;
}
/**
* Adds a file set.
* @param set the file set
*/
public void addFileset(FileSet set) {
filesets.add(set);
}
/**
* Sets the destination directory for the event models.
*
* @param destDir the destination directory
*/
public void setDestDir(File destDir) {
if (!destDir.isDirectory()) {
throw new IllegalArgumentException("destDir must be a directory");
}
this.destDir = destDir;
}
/**
* Sets the translation file for the event producer methods.
* @param f the translation file
*/
public void setTranslationFile(File f) {
this.translationFile = f;
}
/**
* Returns the translation file for the event producer methods.
* @return the translation file
*/
public File getTranslationFile() {
return this.translationFile;
}
/**
* Command-line interface for testing purposes.
* @param args the command-line arguments
*/
public static void main(String[] args) {
try {
Project project = new Project();
EventProducerCollectorTask generator = new EventProducerCollectorTask();
generator.setProject(project);
project.setName("Test");
FileSet fileset = new FileSet();
fileset.setDir(new File("test/java"));
FilenameSelector selector = new FilenameSelector();
selector.setName("**/*.java");
fileset.add(selector);
generator.addFileset(fileset);
File targetDir = new File("build/codegen1");
targetDir.mkdirs();
generator.setTranslationFile(new File("out1.xml"));
generator.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy