001package org.andromda.ant.task;
002
003import java.io.FileNotFoundException;
004import java.net.URL;
005import org.andromda.core.AndroMDAServer;
006import org.andromda.core.configuration.Configuration;
007import org.apache.commons.lang.exception.ExceptionUtils;
008import org.apache.tools.ant.BuildException;
009import org.apache.tools.ant.taskdefs.MatchingTask;
010
011/**
012 * <p>
013 * This class wraps the AndroMDA model processor so that AndroMDA Server can be
014 * used as an Ant task. Represents the <code>&lt;andromda&gt;</code> custom
015 * task which can be called from an Ant build script.
016 * </p>
017 *
018 * @author Lofi Dewanto
019 */
020public class AndroMDAServerStopTask
021    extends MatchingTask
022{
023    /**
024     * Initialize the context class loader.
025     */
026    static
027    {
028        initializeContextClassLoader();
029    }
030
031    /**
032     * Stores the configuration URI.
033     */
034    private URL configurationUri;
035
036    /**
037     * Sets the URI to the configuration file.
038     *
039     * @param configurationUri
040     */
041    public void setConfigurationUri(final URL configurationUri)
042    {
043        this.configurationUri = configurationUri;
044    }
045
046    /**
047     * <p>
048     * Stops the AndroMDA server.
049     * </p>
050     * <p>
051     * This is the main entry point of the application when running Ant. It is
052     * called by ant whenever the surrounding task is executed (which could be
053     * multiple times).
054     * </p>
055     *
056     * @throws BuildException if something goes wrong
057     */
058    public void execute()
059        throws BuildException
060    {
061        // initialize before the execute as well in case we
062        // want to execute more than once
063        initializeContextClassLoader();
064        try
065        {
066            if (this.configurationUri == null)
067            {
068                throw new BuildException("Configuration is not a valid URI --> '" + this.configurationUri + '\'');
069            }
070
071            // Create the configuration file
072            final Configuration configuration = Configuration.getInstance(this.configurationUri);
073
074            final AndroMDAServer andromdaServer = AndroMDAServer.newInstance();
075            if (andromdaServer != null)
076            {
077                andromdaServer.stop(configuration);
078            }
079        }
080        catch (Throwable throwable)
081        {
082            final Throwable cause = ExceptionUtils.getCause(throwable);
083            if (cause != null)
084            {
085                throwable = cause;
086            }
087            if (throwable instanceof FileNotFoundException)
088            {
089                throw new BuildException("No configuration could be loaded from --> '" + configurationUri + '\'');
090            }
091            throw new BuildException(throwable);
092        }
093        finally
094        {
095            // Set the context class loader back ot its system class loaders
096            // so that any processes running after won't be trying to use
097            // the ContextClassLoader for this class.
098            Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
099        }
100    }
101
102    /**
103     * Set the context class loader so that any classes using it (the
104     * contextContextClassLoader) have access to the correct loader.
105     */
106    private static void initializeContextClassLoader()
107    {
108        Thread.currentThread().setContextClassLoader(AndroMDAServerStopTask.class.getClassLoader());
109    }
110}