001package org.andromda.maven.plugin;
002
003import java.io.FileNotFoundException;
004import java.net.MalformedURLException;
005import java.net.URL;
006import java.util.ArrayList;
007import java.util.List;
008import org.andromda.core.common.AndroMDALogger;
009import org.andromda.core.common.ExceptionUtils;
010import org.andromda.core.common.ResourceUtils;
011import org.andromda.core.configuration.Configuration;
012import org.andromda.maven.plugin.configuration.AbstractConfigurationMojo;
013import org.apache.maven.artifact.Artifact;
014import org.apache.maven.artifact.factory.ArtifactFactory;
015import org.apache.maven.artifact.repository.ArtifactRepository;
016import org.apache.maven.model.Plugin;
017import org.apache.maven.plugin.MojoExecutionException;
018import org.apache.maven.plugin.MojoFailureException;
019import org.apache.maven.project.MavenProject;
020import org.apache.maven.settings.Settings;
021
022/**
023 * The abstract AndroMDA Mojo.  This should be extended
024 * by the Mojos that are used to run AndroMDA.
025 *
026 * @author Chad Brandon
027 */
028public abstract class AbstractAndroMDAMojo
029    extends AbstractConfigurationMojo
030{
031    /**
032     * This is the URI to the AndroMDA configuration file.
033     *
034     * @parameter expression="file:${project.basedir}/conf/andromda.xml"
035     * @required
036     */
037    protected String configurationUri;
038
039    /**
040     * Do we allow the code generation to run multiple times? Yes for AndroMDA server,
041     * no for all other cases unless overridden. This prevents multiple code generation
042     * runs while creating site documentation, generate-sources phase can run more than 8 times
043     * for each model when initiated by many of the reporting plugins.
044     *
045     * @parameter default-value="false"
046     * @required
047     */
048    protected boolean allowMultipleRuns;
049
050    /**
051     * @parameter expression="${project}"
052     * @required
053     * @readonly
054     */
055    protected MavenProject project;
056
057    /**
058     * @parameter expression="${project.build.filters}"
059     */
060    protected List<String> propertyFiles;
061
062    /**
063     * The current user system settings for use in Maven. (allows us to pass the user
064     * settings to the AndroMDA configuration).
065     *
066     * @parameter expression="${settings}"
067     * @required
068     * @readonly
069     */
070    protected Settings settings;
071
072    /**
073     * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
074     * @required
075     * @readonly
076     */
077    protected ArtifactFactory factory;
078
079    /**
080     * The registered plugin implementations.
081     *
082     * @parameter expression="${project.build.plugins}"
083     * @required
084     * @readonly
085     */
086    protected List<Plugin> plugins;
087
088    /**
089     * @parameter expression="${localRepository}"
090     * @required
091     * @readonly
092     */
093    protected ArtifactRepository localRepository;
094
095    private static List<String> configurations = new ArrayList<String>();
096
097    /**
098     * Initialize configuration and execute plugin
099     * @see org.apache.maven.plugin.Mojo#execute()
100     */
101    public void execute()
102        throws MojoExecutionException, MojoFailureException
103    {
104        if (this.allowMultipleRuns || !configurations.contains(this.configurationUri))
105        {
106            try
107            {
108                if (!this.allowMultipleRuns)
109                {
110                    configurations.add(this.configurationUri);
111                }
112                AndroMDALogger.initialize();
113                final URL configurationUri = ResourceUtils.toURL(this.configurationUri);
114                if (configurationUri == null)
115                {
116                    throw new MojoExecutionException("Configuration could not be loaded from '" + this.configurationUri +
117                            '\'');
118                }
119                // - setup the classpath
120                this.addPluginDependencies(
121                    Constants.ARTIFACT_ID,
122                    Artifact.SCOPE_RUNTIME);
123                // TODO Change from runtime to test scoped dependencies for mda generation, so they are not added to the dependent manifest files.
124                /*this.addPluginDependencies(
125                        Constants.ARTIFACT_ID,
126                        Artifact.SCOPE_TEST);*/
127                this.initializeClasspathFromClassPathElements(this.project.getRuntimeClasspathElements());
128                final Configuration configuration = this.getConfiguration(configurationUri);
129                this.execute(configuration);
130            }
131            catch (Throwable throwable)
132            {
133                String message = "Error running AndroMDA";
134                throwable = ExceptionUtils.getRootCause(throwable);
135                if (throwable instanceof MalformedURLException || throwable instanceof FileNotFoundException)
136                {
137                    message = "Configuration is not valid '" + this.configurationUri + '\'';
138                }
139                throw new MojoExecutionException(message, throwable);
140            }
141        }
142    }
143
144    /**
145     * Performs the execution of an AndroMDA service with the given
146     * <code>configuration</code>.
147     *
148     * @param configuration the configuration to use for AndroMDA service execution
149     * @throws Exception
150     */
151    protected abstract void execute(final Configuration configuration) throws Exception;
152
153    /**
154     * @param configurationUri The configurationUri to set.
155     */
156    public void setConfigurationUri(String configurationUri)
157    {
158        this.configurationUri = configurationUri;
159    }
160
161    /**
162     * @param project The project to set.
163     */
164    public void setProject(MavenProject project)
165    {
166        this.project = project;
167    }
168
169    /**
170     * Sets the current settings for this Mojo.
171     *
172     * @param settings The settings to set.
173     */
174    public void setSettings(Settings settings)
175    {
176        this.settings = settings;
177    }
178
179    /**
180     * Sets the property files for this project.
181     *
182     * @param propertyFiles
183     */
184    public void setPropertyFiles(List<String> propertyFiles)
185    {
186        this.propertyFiles = propertyFiles;
187    }
188
189    /**
190     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getProject()
191     */
192    protected MavenProject getProject()
193    {
194        return this.project;
195    }
196
197    /**
198     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getPropertyFiles()
199     */
200    protected List<String> getPropertyFiles()
201    {
202        return this.propertyFiles;
203    }
204
205    /**
206     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getSettings()
207     */
208    protected Settings getSettings()
209    {
210        return this.settings;
211    }
212
213    /**
214     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getFactory()
215     */
216    protected ArtifactFactory getFactory()
217    {
218        return this.factory;
219    }
220
221    /**
222     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getPlugins()
223     */
224    protected List<Plugin> getPlugins()
225    {
226        return this.plugins;
227    }
228
229    /**
230     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getLocalRepository()
231     */
232    protected ArtifactRepository getLocalRepository()
233    {
234        return this.localRepository;
235    }
236}