alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.modules.xsl.scenario;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.StringTokenizer;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import org.netbeans.modules.xml.core.actions.InputOutputReporter;
import org.netbeans.modules.xml.core.lib.FileUtilities;
import org.netbeans.modules.xml.core.lib.GuiUtil;
import org.netbeans.modules.xsl.settings.TransformHistory;
import org.netbeans.modules.xsl.transform.TransformServlet;
import org.netbeans.modules.xsl.ui.TransformPanel;
import org.netbeans.modules.xsl.utils.TransformUtil;
import org.openide.ErrorManager;
import org.openide.awt.HtmlBrowser;
import org.openide.cookies.SaveCookie;
import org.openide.filesystems.FileAlreadyLockedException;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.nodes.Node;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.netbeans.modules.xml.api.scenario.Scenario;
import org.netbeans.modules.xsl.api.XSLScenario;

/**
 * File implementation of an XSLScenario.
 * This scenario implementation can be used to execute an XSL transformation
 * using a filebased XML source.  The results can be saved to file, or
 * transformed using transformation servlet.
 * After transforming, the results can be opened in a browser or by applying
 * the default action of the result file.
 *
 * @author  asgeir@dimonsoftware.com
 */
public class FileXSLScenario implements Serializable, XSLScenario, PropertyChangeListener {
    
    /** The data used by this scenario */
    protected Data data;
    
    /** The name of this scenario */
    protected String name = "";
    
    /** Parsed input document */
    private transient Document sourceDoc;
    
    /** Stores the last UI component returned by getUIComponent() */
    private transient TransformPanel transPanel;
    
    /** Stores the last DataObject passed to getUIComponent() */
    private transient DataObject lastDataObject;

    /** Support for notifying listeners about PropertyChange */
    private transient PropertyChangeSupport support;
    
    /** Creates a new instance of FileXSLScenario */
    public FileXSLScenario() {
        data = new Data();
    }
    
    /**
     * Executes the DataObject using this scenario.
     * @param dataObject the DataObject to execute.
     */
    public void execute(DataObject dataObject) {
        InputOutputReporter cookieObserver = new InputOutputReporter(Util.THIS.getString("PROP_transformation_io_name"));
        try {
            // Save the file
            SaveCookie saveCookie = (SaveCookie)dataObject.getCookie(SaveCookie.class);
            if (saveCookie != null) {
                try {
                    saveCookie.save();
                } catch(IOException e) {
                    cookieObserver.message("Could not save file: " + e.getMessage());
                }
            }

          
            FileObject baseFO = dataObject.getPrimaryFile();
            URL baseURL = preferFileURL(baseFO);
            
            Source xmlSource = TransformUtil.createSource(baseURL, data.getSourceXML()); // throws IOException, MalformedURLException, FileStateInvalidException, ParserConfigurationException, SAXException
            if ( Util.THIS.isLoggable() )  Util.THIS.debug("    xmlSource = " + xmlSource.getSystemId());
            
            String xslName = TransformUtil.getURLName(baseFO);
            Source xslSource = TransformUtil.createSource(baseURL, xslName); // throws IOException, MalformedURLException, FileStateInvalidException, ParserConfigurationException, SAXException
            if ( Util.THIS.isLoggable() )  Util.THIS.debug("    xslSource = " + xslSource.getSystemId());
            
            if ( data.getOutput() == null ) { // Preview
                TransformServlet.prepare(null, xmlSource, xslSource);
                showURL(TransformServlet.getServletURL());
            } else {
                String fileName = data.getOutput().replace('\\', '/');
                FileObject resultFO = FileUtilities.createFileObject(baseFO.getParent(), fileName, data.isOverwrite()); // throws IOException
                
                if ( Util.THIS.isLoggable() )  Util.THIS.debug("    resultFO = " + resultFO);
                
                OutputStream outputStream = null;
                FileLock fileLock = null;
                try {
                    fileLock = resultFO.lock();
                    outputStream = resultFO.getOutputStream(fileLock);
                    
                    Result outputResult = new StreamResult(outputStream); // throws IOException, FileStateInvalidException
                    
                    if ( Util.THIS.isLoggable() )  {
                        Util.THIS.debug("    resultFO = " + resultFO);
                        Util.THIS.debug("    outputResult = " + outputResult);
                    }
                    
                    String xmlName = data.getSourceXML();
                    cookieObserver.message(Util.THIS.getString("MSG_transformation_1", xmlName, xslName));
                    TransformUtil.transform(xmlSource, null, xslSource, outputResult, null); // throws TransformerException
                    
                    if ( data.getProcess() == TransformHistory.APPLY_DEFAULT_ACTION ) {
                        GuiUtil.performDefaultAction(resultFO);
                        GuiUtil.performDefaultAction(resultFO);
                    } else if ( data.getProcess() == TransformHistory.OPEN_IN_BROWSER ) {
                        showURL(resultFO.getURL());
                    }
                    
                    GuiUtil.setStatusText(Util.THIS.getString("MSG_opening_browser"));
                    
                } catch (FileAlreadyLockedException exc) {
                    throw (FileAlreadyLockedException) ErrorManager.getDefault().annotate(exc, Util.THIS.getString("ERR_FileAlreadyLockedException_output"));
                } finally {
                    if ( outputStream != null ) {
                        outputStream.close();
                    }
                    if ( fileLock != null ) {
                        fileLock.releaseLock();
                    }
                }
            }
        } catch (TransformerException exc) { // during fileOutput();
            // ignore it -> it should be displayed by CookieObserver!
        } catch(Exception e) {
            ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
        }
        
        cookieObserver.message(Util.THIS.getString("MSG_transformation_2"));
        cookieObserver.moveToFront(true);
        
        sourceDoc = null;
    }
    
    /**
     * This method returns the a UI component which can be used to
     * customize this scenario.  To update changes done in the UI panel,
     * the saveChanges() method can be called.
     * A new or initialized instance of Component should be returned every
     * time this method is called.
     * @param dataObject The DataObject which owns this scenario
     * @param activatePropertyChange a flag that determines if PropertyChangeEvents are fired
     * @return A Component which can be used to customize this scenario
     */
    public java.awt.Component getCustomizer(DataObject dataObject, boolean activatePropertyChange) {
        try {
            transPanel = new TransformPanel(null, null, dataObject);
            lastDataObject = dataObject;
            
            String sourceXML = data.getSourceXML();
            if (sourceXML.length() > 0) {
                FileObject baseFO = dataObject.getPrimaryFile();
                URL baseURL = preferFileURL(baseFO.getParent());
                URL sourceURL = new URL(baseURL, data.getSourceXML());
                sourceXML = sourceURL.toExternalForm();
            }
            
            TransformPanel.Data transData = new TransformPanel.Data(sourceXML,
            transPanel.getData().getXSL(), data.getOutput(), data.isOverwrite(), data.getProcess());
            transPanel.setData(transData);
            if(activatePropertyChange) {
                transPanel.addPropertyChangeListener(this);
            }
        } catch (Exception e) {
            // TBD: Notify user
            e.printStackTrace();
            transPanel = null;
        }
        
        return transPanel;
    }
    
    /**
     * Get the name of this scenario
     * @return The name of this scenario
     */
    public String getName() {
        return name;
    }
    
    /**
     * Set the name of this scenario
     * @param name The name of this scenario
     */
    public void setName(String name) {
        String oldName = this.name;
        this.name = name;
    }
    
    /**
     * Update this scenario with changes done by the last UI
     * component returned by the getUIComponent() method.
     */
    public void saveChanges() {
        if (transPanel != null) {
            TransformPanel.Data transData = transPanel.getData();
            
            String sourceXML = transData.getInput();
            FileObject baseFO = lastDataObject.getPrimaryFile();
            try {
                String baseURL = preferFileURL(baseFO.getParent()).toExternalForm();
                sourceXML = relativize(baseURL, sourceXML);
            } catch(Exception e) {}
            
            data.setSourceXML(sourceXML);
            String outputStr=null;
            if(transData.getOutput()!=null) {
                outputStr=transData.getOutput().toString();
            }
            data.setOutput(outputStr);
            data.setOverwrite(transData.isOverwriteOutput());
            data.setProcess(transData.getProcessOutput());
            sourceDoc = null;
        }
    }
    
    public Document getSourceDocument(DataObject dataObject, boolean reload) throws SAXException, IOException {
        if (sourceDoc == null || reload) {
            String sourceXML = data.getSourceXML();
            if (sourceXML == null || sourceXML.length() == 0) {
                return null;
            }
            
            FileObject baseFO = dataObject.getPrimaryFile();
            URL baseURL = preferFileURL(baseFO);
            URL url = new URL(baseURL, sourceXML);
            sourceDoc = XMLUtil.parse(new InputSource(url.toExternalForm()), false, true,
                null, TransformUtil.getEntityResolver());
        }
        
        return sourceDoc;
    }
    
    /**
     * Returns the name of this scenario
     */
    public String toString() {
        return getName();
    }
    
    
    /**
     * If possible it finds "file:" URL if fileObject is on LocalFileSystem.
     * @return URL of fileObject.
     */
    protected URL preferFileURL(FileObject fileObject) throws MalformedURLException, FileStateInvalidException {
        URL fileURL = null;
        File file = FileUtil.toFile(fileObject);
        
        if ( file != null ) {
            fileURL = file.toURL();
        } else {
            fileURL = fileObject.getURL();
        }
        return fileURL;
    }
    
    private void showURL(URL url) {
        HtmlBrowser.URLDisplayer.getDefault().showURL(url);
        GuiUtil.setStatusText(Util.THIS.getString("MSG_opening_browser"));
    }
    
    /**
     * Registers PropertyChangeListener to receive events.
     * @param listener The listener to register.
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        if(support==null) {
            support = new PropertyChangeSupport(this);
        }
        support.addPropertyChangeListener(listener);
    }
    
    /**
     * Removes PropertyChangeListener from the list of listeners.
     * @param listener The listener to remove.
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        if(support==null) {
            support = new PropertyChangeSupport(this);
        }
        support.removePropertyChangeListener(listener);
    }
    
    /**
     * This method gets called when a bound property is changed.
     * @param evt A PropertyChangeEvent object describing the event source
     *   	and the property that has changed.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        if(support==null) {
            support = new PropertyChangeSupport(this);
        }
        if(evt.getPropertyName().equals(TransformPanel.DATA_XML_MODIFIED) ||
        evt.getPropertyName().equals(TransformPanel.DATA_XSL_MODIFIED) ||
        evt.getPropertyName().equals(TransformPanel.DATA_OUTPUT_MODIFIED) ||
        evt.getPropertyName().equals(TransformPanel.DATA_OVERWRITE_MODIFIED) ||
        evt.getPropertyName().equals(TransformPanel.DATA_PROCESS_MODIFIED)) {
            support.firePropertyChange(Scenario.PROP_SCENARIO_MODIFIED,evt.getOldValue(), evt.getNewValue());
        }
    }
    
    private String relativize(String baseURI, String url) {
        StringTokenizer baseTok = new StringTokenizer(baseURI, "/");
        StringTokenizer urlTok = new StringTokenizer(url, "/");
        
        String curUrlTok = null;
        int parentTokens = baseTok.countTokens();
        int origParentTokens = parentTokens;
        while (baseTok.hasMoreTokens()) {
            if (!urlTok.hasMoreTokens()) {
                curUrlTok = null;
                break;
            }
            curUrlTok = urlTok.nextToken();
            if (!curUrlTok.equals(baseTok.nextToken())) {
                break;
            }
            parentTokens--;
        }
        
        if (parentTokens == origParentTokens) {
            // Difference in protocol
            return url;
        }
        
        String resUrl = "";
        for (int ind = 0; ind < parentTokens; ind++) {
            resUrl += "../";
        }
        
        if (curUrlTok != null) {
            if (parentTokens != 0) {
                resUrl += curUrlTok;
                if (urlTok.hasMoreTokens()) {
                    resUrl += "/";
                }
            }
         
            while (urlTok.hasMoreTokens()) {
                resUrl += urlTok.nextToken();
                if (urlTok.hasMoreTokens()) {
                    resUrl += "/";
                }
            }
        }
        
        return resUrl;
    }
    
    public class Data implements Serializable {
        
        /** Holds value of property sourceXML. */
        private String sourceXML = "";
        
        /** Holds value of property output. */
        private String output = null;
        
        /** Holds value of property overwrite. */
        private boolean overwrite = true;
        
        /** Holds value of property process. */
        private int process = -1;
        
        /** Getter for property sourceXML.
         * @return Value of property sourceXML.
         *
         */
        public String getSourceXML() {
            return this.sourceXML;
        }
        
        /** Setter for property sourceXML.
         * @param sourceXML New value of property sourceXML.
         *
         */
        public void setSourceXML(String sourceXML) {
            this.sourceXML = sourceXML;
        }
        
        /** Getter for property output.
         * @return Value of property output.
         *
         */
        public String getOutput() {
            return this.output;
        }
        
        /** Setter for property output.
         * @param output New value of property output.
         *
         */
        public void setOutput(String output) {
            this.output = output;
        }
        
        /** Getter for property overwrite.
         * @return Value of property overwrite.
         *
         */
        public boolean isOverwrite() {
            return this.overwrite;
        }
        
        /** Setter for property overwrite.
         * @param overwrite New value of property overwrite.
         *
         */
        public void setOverwrite(boolean overwrite) {
            this.overwrite = overwrite;
        }
        
        /** Getter for property process.
         * @return Value of property process.
         *
         */
        public int getProcess() {
            return this.process;
        }
        
        /** Setter for property process.
         * @param process New value of property process.
         *
         */
        public void setProcess(int process) {
            this.process = process;
        }
        
    }
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.