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 AndroMDAServerStartTask
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     * Starts 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
057     *             if something goes wrong
058     */
059    public void execute()
060        throws BuildException
061    {
062        // Initialize before the execute as well in case we
063        // want to execute more than once
064        initializeContextClassLoader();
065        try
066        {
067            if (this.configurationUri == null)
068            {
069                throw new BuildException("Configuration is not a valid URI --> '" + this.configurationUri + '\'');
070            }
071
072            // Create the configuration file from URI
073            final Configuration configuration = Configuration.getInstance(this.configurationUri);
074
075            // Create and start the server
076            final AndroMDAServer andromdaServer = AndroMDAServer.newInstance();
077            if (andromdaServer != null)
078            {
079                andromdaServer.start(configuration);
080            }
081        }
082        catch (Throwable throwable)
083        {
084            final Throwable cause = ExceptionUtils.getCause(throwable);
085            if (cause != null)
086            {
087                throwable = cause;
088            }
089            if (throwable instanceof FileNotFoundException)
090            {
091                throw new BuildException("No configuration could be loaded from --> '" + configurationUri + '\'');
092            }
093            throw new BuildException(throwable);
094        }
095        finally
096        {
097            // Set the context class loader back ot its system class loaders
098            // so that any processes running after won't be trying to use
099            // the ContextClassLoader for this class.
100            Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
101        }
102    }
103
104    /**
105     * Set the context class loader so that any classes using it (the
106     * contextContextClassLoader) have access to the correct loader.
107     */
108    private static void initializeContextClassLoader()
109    {
110        Thread.currentThread().setContextClassLoader(AndroMDAServerStartTask.class.getClassLoader());
111    }
112}