Package org.apache.tools.ant.gui.core

Source Code of org.apache.tools.ant.gui.core.ProjectManager$BuildRunner

/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 - 2004 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution, if
*    any, must include the following acknowlegement:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowlegement may appear in the software itself,
*    if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
*    Foundation" must not be used to endorse or promote products derived
*    from this software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
*    nor may "Apache" appear in their names without prior written
*    permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui.core;

import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.BuildEvent;

import org.apache.tools.ant.gui.acs.ACSFactory;
import org.apache.tools.ant.gui.acs.ACSProjectElement;
import org.apache.tools.ant.gui.acs.ACSTargetElement;

import org.apache.tools.ant.gui.command.SaveCmd;

import org.apache.tools.ant.gui.event.BuildEventType;
import org.apache.tools.ant.gui.event.ProjectSavedEvent;

import org.apache.tools.ant.gui.xml.DOMDocument;

import java.io.IOException;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.Writer;

import java.net.URL;
import java.net.URLConnection;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import javax.swing.JOptionPane;

/**
* This class is responsible for managing the currently open projects,
* and the loading of new projects.
*
* XXX need to add property change listeners support.
*
* @version $Revision: 1.8 $
* @author Simeon Fitch, Christoph Wilhelms
*/
public class ProjectManager {

    /** Set of open projects. */
    private List _projects = new ArrayList(1);
    /** List of build listeners to register when build starts. */
    private List _buildListeners = new LinkedList();
    /** The current thread executing a build. */
    private Thread _buildThread = null;
    /** The application context */
    private AppContext _context = null;

    /**
     * Standard Constructor
     *
     * @param context the application context
     */
    public ProjectManager(AppContext context) {
        _context = context;
    }

    /**
     * Get all the open projects.
     *
     * @return an array of all open projects.
     */
    public ACSProjectElement[] getOpen() {
        ACSProjectElement[] retval = new ACSProjectElement[_projects.size()];
        _projects.toArray(retval);
        return retval;
    }

    /**
     * Save the given project.
     *
     * @param project Project to save.
     */
    public void save(ACSProjectElement project) throws IOException {
        saveAs(project, null);
    }


    /**
     * Save the given project to the given location.
     *
     * @param project Project to save.
     * @param location Location to save to.
     */
    public void saveAs(ACSProjectElement project, URL location)
        throws IOException {

        if(location == null) {
            location = project.getLocation();
        }
        if(location == null) {
            // This shouldn't happen.
            throw new IOException("Logic error: Save location mising.");
        }

        Writer out = null;
        try {
            // XXX for some reason the URLConnection for protocol type "file"
            // doesn't support output (at least that is what the exception
            // says. I don't know if I'm doing something wrong or not, but
            // since we need to handle files differently (which is fine
            // right now since files are all we really support anyway.
            if(location.getProtocol().equals("file")) {
                out = new FileWriter(location.getFile());
            }
            else {
                // XXX This is here for future support of FTP/HTTP and
                // the like. JDBC will have to be dealt with differently.
                URLConnection connection = location.openConnection();
                connection.setDoInput(false);
                connection.setDoOutput(true);
                out = new OutputStreamWriter(connection.getOutputStream());
            }

            // Persist the project.
            // Call the write method of the parent node (document) do persist document related tags
            // and not only the project!
            project.getParentNode().write(out);
            out.flush();
            project.setLocation(location);
            project.setModified(false);
           
            _context.getEventBus().postEvent(
                new ProjectSavedEvent(_context));
           
        } catch (org.xml.sax.SAXException e) {
           
            e.printStackTrace();
            throw new IOException(e.getMessage());
           
        } finally {
            try { out.close(); } catch(Exception ex) {}
        }
    }

    /**
     * Open the project persisted at the given location
     *
     * @param location Location of project file.
     * @return Successfully loaded project.
     * @throws IOException thrown if there is a problem opening the project.
     */
    public ACSProjectElement open(File location) throws IOException {
        return open(new URL("file", null, location.getPath()));
    }

    /**
     * Open the project persisted at the given location
     *
     * @param location Location of project file.
     * @return Successfully loaded project.
     * @throws IOException thrown if there is a problem opening the project.
     */
    public ACSProjectElement open(URL location) throws IOException {
        ACSProjectElement retval = null;
        retval = ACSFactory.getInstance().load(location);
        retval.setLocation(location);
        _projects.add(retval);
        return retval;
    }

    /**
     * Create a new, unpopulated project.
     *
     * @return Unpopulated project.
     */
    public ACSProjectElement createNew() {
        ACSProjectElement retval = ACSFactory.getInstance().createProject();
        _projects.add(retval);
        return retval;
    }

    /**
     * Remove the given project from the set of active projects.
     *
     * @param project Project to close.
     */
    public boolean close(ACSProjectElement project) throws IOException {
        DOMDocument doc = project.getOwnerDocument();

        // Check to see is the project has been modified and
        // ask the user if they would like to save it before
        // closing.
        int select = JOptionPane.NO_OPTION;
        if (doc.isModified()) {
            select = JOptionPane.showConfirmDialog(null,
                    project.getDisplayName() +
                    " has been modified.\n\nWould you like to save it?\n\n",
                    "Save Modified Project",
                    JOptionPane.YES_NO_CANCEL_OPTION);
        }
       
        if (select == JOptionPane.YES_OPTION) {
           
            // Try to save the project
            SaveCmd cmd = new SaveCmd(_context);
            cmd.run();
           
            // If it is still modified, then the save was canceled.
            if (doc.isModified()) {
                select = JOptionPane.CANCEL_OPTION;
            }
        }
       
        if (select != JOptionPane.CANCEL_OPTION) {
            _projects.remove(project);
        }
       
        return (select != JOptionPane.CANCEL_OPTION);
    }

  /**
   * Build the project with the given target (or the default target
     * if none is selected.  Build occurs on a separate thread, so method
     * returns immediately.
   *
     * @param project Project to build.
     * @param targets Targets to build in project.
   */
    public void build(ACSProjectElement project, ACSTargetElement[] targets)
        throws BuildException {
        _buildThread = new Thread(new BuildRunner(project, targets));
        _buildThread.start();
    }

  /**
   * Add a build listener.
   *
   * @param l Listener to add.
   */
    public void addBuildListener(BuildListener l) {
        synchronized(_buildListeners) {
            _buildListeners.add(l);
        }
    }

  /**
   * Remove a build listener.
   *
   * @param l Listener to remove.
   */
    public void removeBuildListener(BuildListener l) {
        synchronized(_buildListeners) {
            _buildListeners.remove(l);
        }
    }

  /**
   * Determine if the given BuildListener is registered.
   *
   * @param l Listener to test for.
   * @return True if listener has been added, false if unknown.
   */
    public boolean isRegisteredBuildListener(BuildListener l) {
        synchronized(_buildListeners) {
            return _buildListeners.contains(l);
        }
    }

  /**
   * Get the set of current build listeners.
   *
     * @return Set of current build listeners.
   */
    public BuildListener[] getBuildListeners() {
        synchronized(_buildListeners) {
            BuildListener[] retval = new BuildListener[_buildListeners.size()];
            _buildListeners.toArray(retval);
            return retval;
        }
    }

    /** Class for executing the build in a separate thread. */
    private class BuildRunner implements Runnable {
        /** The project to execute build on. */
        private ACSProjectElement _project = null;
        /** Targets to build. */
        private ACSTargetElement[] _targets = null;
        /** The Ant core representation of a project. */
        private Project _antProject = null;

        /**
         * Standard ctor.
         *
         * @param project Project to execute build on.
         * @param targets Targets to build.
         */
        public BuildRunner(ACSProjectElement project,
                           ACSTargetElement[] targets) throws BuildException {
            _project = project;
            _targets = targets;

            URL location = _project.getLocation();
            if(location == null) {
                // XXX this needs to be changed so that if the project is
                // not saved, or the persistence mechanism is remote
                // then a temporary version is saved first.
                throw new BuildException("Project must be saved first");
            }

            // XXX hopefully we will eventually be able to save
            // project files to any type of URL. Right now the Ant core
            // only supports Files.
            if(!location.getProtocol().equals("file")) {
                throw new IllegalArgumentException(
                    "The Ant core only supports building from locally " +
                    "stored build files.");
            }

            File f = new File(location.getFile());

            _antProject = new Project();
            _antProject.init();
            // XXX there is a bunch of stuff in the class
            // org.apache.tools.ant.Main that needs to be
            // refactored out so that it doesn't have to be
            // replicated here.
           
            // XXX need to provide a way to pass in externally
            // defined properties.  Perhaps define an external
            // Antidote properties file. JAVA_HOME may have to be set,
            // as well as checking the .ant.properties
            _antProject.setUserProperty(
                "ant.file" , f.getAbsolutePath());
            ProjectHelper helper = ProjectHelper.getProjectHelper();
            _antProject.addReference("ant.projectHelper", helper);
            helper.parse(_antProject, f);
        }

        /**
         * Convenience method for causeing the project to fire a build event.
         * Implemented because the corresponding method in the Project class
         * is not publically accessible.
         *
         * @param event Event to fire.
         */
        private void fireBuildEvent(BuildEvent event, BuildEventType type) {
            Enumeration en = _antProject.getBuildListeners().elements();
            while(en.hasMoreElements()) {
                BuildListener l = (BuildListener) en.nextElement();
                type.fireEvent(event, l);
            }
        }

        /**
         * Run the build.
         *
         */
        public void run() {
            synchronized(_antProject) {
                // Add the build listeners
                BuildListener[] listeners = getBuildListeners();
                for(int i = 0; i < listeners.length; i++) {
                    _antProject.addBuildListener(listeners[i]);
                }
               
                try {
                   
                    fireBuildEvent(new BuildEvent(
                        _antProject), BuildEventType.BUILD_STARTED);
                   
                   
                    Vector targetNames = new Vector();
                    if(_targets == null || _targets.length == 0) {
                        targetNames.add(_antProject.getDefaultTarget());
                    }
                    else {
                        for(int i = 0; i < _targets.length; i++) {
                            targetNames.add(_targets[i].getName());
                        }
                    }
                   
                    // Execute build on selected targets. XXX It would be
                    // nice if the Project API supported passing in target
                    // objects rather than String names.
                    _antProject.executeTargets(targetNames);
                }
                catch(BuildException ex) {
                    BuildEvent errorEvent = new BuildEvent(_antProject);
                    errorEvent.setException(ex);
                    errorEvent.setMessage(ex.getMessage(), Project.MSG_ERR);
                    fireBuildEvent(errorEvent, BuildEventType.MESSAGE_LOGGED);
                }
                finally {
                    fireBuildEvent(new BuildEvent(
                        _antProject), BuildEventType.BUILD_FINISHED);
                   
                    // Remove the build listeners.
                    for(int i = 0; i < listeners.length; i++) {
                        _antProject.removeBuildListener(listeners[i]);
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.tools.ant.gui.core.ProjectManager$BuildRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.