com.panet.imeta.job.entries.xslt.JobEntryXSLT.java Source code

Java tutorial

Introduction

Here is the source code for com.panet.imeta.job.entries.xslt.JobEntryXSLT.java

Source

/* Copyright (c) 2007 Pentaho Corporation.  All rights reserved. 
* This software was developed by Pentaho Corporation and is provided under the terms 
* of the GNU Lesser General Public License, Version 2.1. You may not use 
* this file except in compliance with the license. If you need a copy of the license, 
* please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is Pentaho 
* Data Integration.  The Initial Developer is Pentaho Corporation.
*
* Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
* basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
* the license for the specific language governing your rights and limitations.*/

package com.panet.imeta.job.entries.xslt;

import static com.panet.imeta.job.entry.validator.AbstractFileValidator.putVariableSpace;
import static com.panet.imeta.job.entry.validator.AndValidator.putValidators;
import static com.panet.imeta.job.entry.validator.JobEntryValidatorUtils.andValidator;
import static com.panet.imeta.job.entry.validator.JobEntryValidatorUtils.fileExistsValidator;
import static com.panet.imeta.job.entry.validator.JobEntryValidatorUtils.notBlankValidator;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Source;
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;

import org.apache.commons.vfs.FileObject;
import org.w3c.dom.Node;

import com.panet.imeta.cluster.SlaveServer;
import com.panet.imeta.core.CheckResultInterface;
import com.panet.imeta.core.Const;
import com.panet.imeta.core.Result;
import com.panet.imeta.core.ResultFile;
import com.panet.imeta.core.database.DatabaseMeta;
import com.panet.imeta.core.exception.KettleDatabaseException;
import com.panet.imeta.core.exception.KettleException;
import com.panet.imeta.core.exception.KettleXMLException;
import com.panet.imeta.core.logging.LogWriter;
import com.panet.imeta.core.util.StringUtil;
import com.panet.imeta.core.vfs.KettleVFS;
import com.panet.imeta.core.xml.XMLHandler;
import com.panet.imeta.job.Job;
import com.panet.imeta.job.JobEntryType;
import com.panet.imeta.job.JobMeta;
import com.panet.imeta.job.entry.JobEntryBase;
import com.panet.imeta.job.entry.JobEntryInterface;
import com.panet.imeta.job.entry.validator.ValidatorContext;
import com.panet.imeta.repository.Repository;
import com.panet.imeta.resource.ResourceEntry;
import com.panet.imeta.resource.ResourceReference;
import com.panet.imeta.resource.ResourceEntry.ResourceType;
import com.panet.imeta.shared.SharedObjectInterface;

/**
 * This defines a 'xslt' job entry.
 *
 * @author Samatar Hassan
 * @since 02-03-2007
 *
 */
public class JobEntryXSLT extends JobEntryBase implements Cloneable, JobEntryInterface {
    public static final String ENTRY_ATTRIBUTE_XMLFILENAME = "xmlfilename";
    public static final String ENTRY_ATTRIBUTE_XSLFILENAME = "xslfilename";
    public static final String ENTRY_ATTRIBUTE_OUTPUTFILENAME = "outputfilename";
    public static final String ENTRY_ATTRIBUTE_IFFILEEXISTS = "iffileexists";
    public static final String ENTRY_ATTRIBUTE_ADDFILETORESULT = "addfiletoresult";
    public static final String ENTRY_ATTRIBUTE_XSLTFACTORY = "xsltfactory";

    public static String FACTORY_JAXP = "JAXP";
    public static String FACTORY_SAXON = "SAXON";

    private String xmlfilename;
    private String xslfilename;
    private String outputfilename;
    public int iffileexists;
    private boolean addfiletoresult;
    private String xsltfactory;

    public JobEntryXSLT(String n) {
        super(n, "");
        xmlfilename = null;
        xslfilename = null;
        outputfilename = null;
        iffileexists = 1;
        addfiletoresult = false;
        xsltfactory = FACTORY_JAXP;
        setID(-1L);
        setJobEntryType(JobEntryType.XSLT);
    }

    public JobEntryXSLT() {
        this("");
    }

    public JobEntryXSLT(JobEntryBase jeb) {
        super(jeb);
    }

    public Object clone() {
        JobEntryXSLT je = (JobEntryXSLT) super.clone();
        return je;
    }

    public String getXML() {
        StringBuffer retval = new StringBuffer(50);

        retval.append(super.getXML());
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_XMLFILENAME, xmlfilename));
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_XSLFILENAME, xslfilename));
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_OUTPUTFILENAME, outputfilename));
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_IFFILEEXISTS, iffileexists));
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_ADDFILETORESULT, addfiletoresult));
        retval.append("      ").append(XMLHandler.addTagValue(ENTRY_ATTRIBUTE_XSLTFACTORY, xsltfactory));

        return retval.toString();
    }

    public void loadXML(Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers,
            Repository rep) throws KettleXMLException {
        try {
            super.loadXML(entrynode, databases, slaveServers);
            xmlfilename = XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_XMLFILENAME);
            xslfilename = XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_XSLFILENAME);
            outputfilename = XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_OUTPUTFILENAME);
            iffileexists = Const.toInt(XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_IFFILEEXISTS), -1);
            addfiletoresult = "Y"
                    .equalsIgnoreCase(XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_ADDFILETORESULT));
            xsltfactory = XMLHandler.getTagValue(entrynode, ENTRY_ATTRIBUTE_XSLTFACTORY);
            if (xsltfactory == null)
                xsltfactory = FACTORY_JAXP;

        } catch (KettleXMLException xe) {
            throw new KettleXMLException("Unable to load job entry of type 'xslt' from XML node", xe);
        }
    }

    public void setInfo(Map<String, String[]> p, String id, List<? extends SharedObjectInterface> databases) {
        xmlfilename = JobEntryBase.parameterToString(p.get(id + ".xmlfilename"));
        xslfilename = JobEntryBase.parameterToString(p.get(id + ".xslfilename"));
        outputfilename = JobEntryBase.parameterToString(p.get(id + ".outputfilename"));
        iffileexists = JobEntryBase.parameterToInt(p.get(id + ".iffileexists"));
        addfiletoresult = JobEntryBase.parameterToBoolean(p.get(id + ".addfiletoresult"));
        xsltfactory = JobEntryBase.parameterToString(p.get(id + ".xsltfactory"));
    }

    public void loadRep(Repository rep, long id_jobentry, List<DatabaseMeta> databases,
            List<SlaveServer> slaveServers) throws KettleException {
        try {
            super.loadRep(rep, id_jobentry, databases, slaveServers);
            xmlfilename = rep.getJobEntryAttributeString(id_jobentry, ENTRY_ATTRIBUTE_XMLFILENAME);
            xslfilename = rep.getJobEntryAttributeString(id_jobentry, ENTRY_ATTRIBUTE_XSLFILENAME);
            outputfilename = rep.getJobEntryAttributeString(id_jobentry, ENTRY_ATTRIBUTE_OUTPUTFILENAME);
            iffileexists = (int) rep.getJobEntryAttributeInteger(id_jobentry, ENTRY_ATTRIBUTE_IFFILEEXISTS);
            addfiletoresult = rep.getJobEntryAttributeBoolean(id_jobentry, ENTRY_ATTRIBUTE_ADDFILETORESULT);
            xsltfactory = rep.getJobEntryAttributeString(id_jobentry, ENTRY_ATTRIBUTE_XSLTFACTORY);
            if (xsltfactory == null)
                xsltfactory = FACTORY_JAXP;
        } catch (KettleException dbe) {
            throw new KettleException(
                    "Unable to load job entry of type 'xslt' from the repository for id_jobentry=" + id_jobentry,
                    dbe);
        }
    }

    public void saveRep(Repository rep, long id_job) throws KettleException {
        try {
            super.saveRep(rep, id_job);

            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_XMLFILENAME, xmlfilename);
            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_XSLFILENAME, xslfilename);
            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_OUTPUTFILENAME, outputfilename);
            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_IFFILEEXISTS, iffileexists);
            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_ADDFILETORESULT, addfiletoresult);
            rep.saveJobEntryAttribute(id_job, getID(), ENTRY_ATTRIBUTE_XSLTFACTORY, xsltfactory);

        } catch (KettleDatabaseException dbe) {
            throw new KettleException(
                    "Unable to save job entry of type 'xslt' to the repository for id_job=" + id_job, dbe);
        }
    }

    public String getXSLTFactory() {
        return xsltfactory;
    }

    public void setXSLTFactory(String xsltfactoryin) {
        xsltfactory = xsltfactoryin;
    }

    public String getRealxmlfilename() {
        return environmentSubstitute(getxmlFilename());
    }

    public String getRealoutputfilename() {
        return environmentSubstitute(getoutputFilename());
    }

    public String getRealxslfilename() {
        return environmentSubstitute(getxslFilename());
    }

    public Result execute(Result previousResult, int nr, Repository rep, Job parentJob) {
        LogWriter log = LogWriter.getInstance();
        Result result = previousResult;
        result.setResult(false);

        String realxmlfilename = getRealxmlfilename();
        String realxslfilename = getRealxslfilename();
        String realoutputfilename = getRealoutputfilename();

        FileObject xmlfile = null;
        FileObject xslfile = null;
        FileObject outputfile = null;

        try

        {

            if (xmlfilename != null && xslfilename != null && outputfilename != null) {
                xmlfile = KettleVFS.getFileObject(realxmlfilename);
                xslfile = KettleVFS.getFileObject(realxslfilename);
                outputfile = KettleVFS.getFileObject(realoutputfilename);

                if (xmlfile.exists() && xslfile.exists()) {
                    if (outputfile.exists() && iffileexists == 2) {
                        //Output file exists
                        // User want to fail
                        log.logError(toString(), Messages.getString("JobEntryXSLT.OuputFileExists1.Label")
                                + realoutputfilename + Messages.getString("JobEntryXSLT.OuputFileExists2.Label"));
                        result.setResult(false);
                        result.setNrErrors(1);
                    }

                    else if (outputfile.exists() && iffileexists == 1) {
                        // Do nothing
                        if (log.isDebug())
                            log.logDebug(toString(),
                                    Messages.getString("JobEntryXSLT.OuputFileExists1.Label") + realoutputfilename
                                            + Messages.getString("JobEntryXSLT.OuputFileExists2.Label"));
                        result.setResult(true);
                    } else {
                        if (outputfile.exists() && iffileexists == 0) {
                            // the output file exists and user want to create new one with unique name
                            //Format Date

                            // Try to clean filename (without wildcard)
                            String wildcard = realoutputfilename.substring(realoutputfilename.length() - 4,
                                    realoutputfilename.length());
                            if (wildcard.substring(0, 1).equals(".")) {
                                // Find wildcard
                                realoutputfilename = realoutputfilename.substring(0,
                                        realoutputfilename.length() - 4) + "_"
                                        + StringUtil.getFormattedDateTimeNow(true) + wildcard;
                            } else {
                                // did not find wildcard
                                realoutputfilename = realoutputfilename + "_"
                                        + StringUtil.getFormattedDateTimeNow(true);
                            }
                            if (log.isDebug())
                                log.logDebug(toString(),
                                        Messages.getString("JobEntryXSLT.OuputFileExists1.Label")
                                                + realoutputfilename
                                                + Messages.getString("JobEntryXSLT.OuputFileExists2.Label"));
                            log.logDebug(toString(),
                                    Messages.getString("JobEntryXSLT.OuputFileNameChange1.Label")
                                            + realoutputfilename
                                            + Messages.getString("JobEntryXSLT.OuputFileNameChange2.Label"));
                        }

                        // Create transformer factory
                        TransformerFactory factory = TransformerFactory.newInstance();

                        if (xsltfactory.equals(FACTORY_SAXON)) {
                            // Set the TransformerFactory to the SAXON implementation.
                            factory = new net.sf.saxon.TransformerFactoryImpl();
                        }

                        if (log.isDetailed())
                            log.logDetailed(Messages.getString("JobEntryXSL.Log.TransformerFactoryInfos"), Messages
                                    .getString("JobEntryXSL.Log.TransformerFactory", factory.getClass().getName()));

                        // Use the factory to create a template containing the xsl file
                        Templates template = factory
                                .newTemplates(new StreamSource(KettleVFS.getInputStream(xslfile)));

                        // Use the template to create a transformer
                        Transformer xformer = template.newTransformer();

                        if (log.isDetailed())
                            log.logDetailed(Messages.getString("JobEntryXSL.Log.TransformerClassInfos"), Messages
                                    .getString("JobEntryXSL.Log.TransformerClass", xformer.getClass().getName()));

                        // Prepare the input and output files
                        Source source = new StreamSource(KettleVFS.getInputStream(xmlfile));
                        StreamResult resultat = new StreamResult(KettleVFS.getOutputStream(outputfile, false));

                        // Apply the xsl file to the source file and write the result to the output file
                        xformer.transform(source, resultat);

                        if (isAddFileToResult()) {
                            // Add output filename to output files
                            ResultFile resultFile = new ResultFile(ResultFile.FILE_TYPE_GENERAL,
                                    KettleVFS.getFileObject(realoutputfilename), parentJob.getJobname(),
                                    toString());
                            result.getResultFiles().put(resultFile.getFile().toString(), resultFile);
                        }

                        // Everything is OK
                        result.setResult(true);
                    }
                } else {

                    if (!xmlfile.exists()) {
                        log.logError(toString(), Messages.getString("JobEntryXSLT.FileDoesNotExist1.Label")
                                + realxmlfilename + Messages.getString("JobEntryXSLT.FileDoesNotExist2.Label"));
                    }
                    if (!xslfile.exists()) {
                        log.logError(toString(), Messages.getString("JobEntryXSLT.FileDoesNotExist1.Label")
                                + realxslfilename + Messages.getString("JobEntryXSLT.FileDoesNotExist2.Label"));
                    }
                    result.setResult(false);
                    result.setNrErrors(1);
                }

            } else {
                log.logError(toString(), Messages.getString("JobEntryXSLT.AllFilesNotNull.Label"));
                result.setResult(false);
                result.setNrErrors(1);
            }
        } catch (Exception e) {
            log.logError(toString(),
                    Messages.getString("JobEntryXSLT.ErrorXLST.Label")
                            + Messages.getString("JobEntryXSLT.ErrorXLSTXML1.Label") + realxmlfilename
                            + Messages.getString("JobEntryXSLT.ErrorXLSTXML2.Label")
                            + Messages.getString("JobEntryXSLT.ErrorXLSTXSL1.Label") + realxslfilename
                            + Messages.getString("JobEntryXSLT.ErrorXLSTXSL2.Label") + e.getMessage());
            result.setResult(false);
            result.setNrErrors(1);
        } finally {
            try {
                if (xmlfile != null)
                    xmlfile.close();

                if (xslfile != null)
                    xslfile.close();
                if (outputfile != null)
                    outputfile.close();

                // file object is not properly garbaged collected and thus the file cannot
                // be deleted anymore. This is a known problem in the JVM.

                System.gc();
            } catch (IOException e) {
            }
        }

        return result;
    }

    public boolean evaluates() {
        return true;
    }

    public void setxmlFilename(String filename) {
        this.xmlfilename = filename;
    }

    public String getxmlFilename() {
        return xmlfilename;
    }

    public String getoutputFilename() {
        return outputfilename;
    }

    public void setoutputFilename(String outputfilename) {
        this.outputfilename = outputfilename;
    }

    public void setxslFilename(String filename) {
        this.xslfilename = filename;
    }

    public String getxslFilename() {
        return xslfilename;
    }

    public void setAddFileToResult(boolean addfiletoresultin) {
        this.addfiletoresult = addfiletoresultin;
    }

    public boolean isAddFileToResult() {
        return addfiletoresult;
    }

    public List<ResourceReference> getResourceDependencies(JobMeta jobMeta) {
        List<ResourceReference> references = super.getResourceDependencies(jobMeta);
        if ((!Const.isEmpty(xslfilename)) && (!Const.isEmpty(xmlfilename))) {
            String realXmlFileName = jobMeta.environmentSubstitute(xmlfilename);
            String realXslFileName = jobMeta.environmentSubstitute(xslfilename);
            ResourceReference reference = new ResourceReference(this);
            reference.getEntries().add(new ResourceEntry(realXmlFileName, ResourceType.FILE));
            reference.getEntries().add(new ResourceEntry(realXslFileName, ResourceType.FILE));
            references.add(reference);
        }
        return references;
    }

    @Override
    public void check(List<CheckResultInterface> remarks, JobMeta jobMeta) {
        ValidatorContext ctx = new ValidatorContext();
        putVariableSpace(ctx, getVariables());
        putValidators(ctx, notBlankValidator(), fileExistsValidator());
        andValidator().validate(this, "xmlFilename", remarks, ctx);//$NON-NLS-1$
        andValidator().validate(this, "xslFilename", remarks, ctx);//$NON-NLS-1$

        andValidator().validate(this, "outputFilename", remarks, putValidators(notBlankValidator()));//$NON-NLS-1$
    }

}