/**
 * Copyright (C) 2002
 */

package org.objectweb.util.ant;

import org.apache.tools.ant.taskdefs.XSLTLiaison;
import org.apache.xalan.processor.TransformerFactoryImpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 * This class permits to use the Xalan 2.
 *
 * @author Sebastien Chassande-Barrioz
 */
public class Xalan2Liaison implements XSLTLiaison {

	/** The trax TransformerFactory */
	private TransformerFactory tfactory = null;

	/** stylesheet stream, close it asap */
	private FileInputStream xslStream = null;

	/** Stylesheet template */
	private Templates templates = null;

	/** transformer */
	private Transformer transformer = null;

	public Xalan2Liaison() throws Exception {
		tfactory = new TransformerFactoryImpl();
	}

	public void setStylesheet(File stylesheet) throws Exception {
		xslStream = new FileInputStream(stylesheet);
		StreamSource src = new StreamSource(xslStream);
		src.setSystemId(getSystemId(stylesheet));
		templates = tfactory.newTemplates(src);
		transformer = templates.newTransformer();
	}

	public void transform(File infile, File outfile) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(infile);
			fos = new FileOutputStream(outfile);
			StreamSource src = new StreamSource(fis);
			src.setSystemId(getSystemId(infile));
			StreamResult res = new StreamResult(fos);
			// not sure what could be the need of this...
			res.setSystemId(getSystemId(outfile));

			transformer.transform(src, res);
		}
		finally {
			// make sure to close all handles, otherwise the garbage
			// collector will close them...whenever possible and
			// Windows may complain about not being able to delete files.
			try {
				if (xslStream != null) {
					xslStream.close();
				}
			}
			catch (IOException ignored) {
			}
			try {
				if (fis != null) {
					fis.close();
				}
			}
			catch (IOException ignored) {
			}
			try {
				if (fos != null) {
					fos.close();
				}
			}
			catch (IOException ignored) {
			}
		}
	}

	// make sure that the systemid is made of '/' and not '\' otherwise
	// crimson will complain that it cannot resolve relative entities
	// because it grabs the base uri via lastIndexOf('/') without
	// making sure it is really a /'ed path
	protected String getSystemId(File file) {
		String path = file.getAbsolutePath();
		path = path.replace('\\', '/');
		return FILE_PROTOCOL_PREFIX + path;
	}

	public void addParam(String name, String value) {
		transformer.setParameter(name, value);
	}
}
