001package org.andromda.maven.plugin.bootstrap;
002
003import java.io.File;
004import java.io.FileNotFoundException;
005import java.net.MalformedURLException;
006import java.net.URL;
007import java.util.List;
008import org.andromda.core.AndroMDA;
009import org.andromda.core.common.ExceptionUtils;
010import org.andromda.core.common.ResourceUtils;
011import org.andromda.core.configuration.Configuration;
012import org.andromda.core.configuration.Model;
013import org.andromda.core.configuration.Repository;
014import org.andromda.maven.plugin.configuration.AbstractConfigurationMojo;
015import org.apache.maven.artifact.factory.ArtifactFactory;
016import org.apache.maven.artifact.repository.ArtifactRepository;
017import org.apache.maven.model.Plugin;
018import org.apache.maven.plugin.MojoExecutionException;
019import org.apache.maven.project.MavenProject;
020import org.apache.maven.settings.Settings;
021
022
023/**
024 * This is exactly the same as the regular AndroMDAMojo in the
025 * andromda-maven-plugin, however this is the <em>bootstrap</em> plugin which
026 * is used to run AndroMDA in bootstrap mode (with the bootstrap artifacts).
027 *
028 * @author Chad Brandon
029 * @goal run
030 * @phase generate-sources
031 * @requiresDependencyResolution runtime
032 */
033public class AndroMDAMojo
034    extends AbstractConfigurationMojo
035{
036    /**
037     * This is the URI to the AndroMDA configuration file.
038     *
039     * @parameter expression="file:${basedir}/conf/andromda.xml"
040     * @required
041     */
042    private String configurationUri;
043
044    /**
045     * @parameter expression="${project}"
046     * @required
047     * @readonly
048     */
049    private MavenProject project;
050
051    /**
052     * @parameter expression="${project.build.filters}"
053     */
054    private List<String> propertyFiles;
055
056    /**
057     * Whether or not a last modified check should be performed before running
058     * AndroMDA again.
059     *
060     * @parameter expression="false"
061     * @required
062     */
063    private boolean lastModifiedCheck;
064
065    /**
066     * The directory to which the build source is located (any generated
067     * source).
068     *
069     * @parameter expression="${project.build.directory}/src/main/java"
070     */
071    private File buildSourceDirectory;
072
073    /**
074     * The directory where the model generation output history is located
075     * (Modelname file containing a list of files generated by that model).
076     *
077     * @parameter expression="${project.build.directory}/history"
078     */
079    private File modelOutputHistory;
080
081    /**
082     * The current user system settings for use in Maven. (allows us to pass the
083     * user settings to the AndroMDA configuration).
084     *
085     * @parameter expression="${settings}"
086     * @required
087     * @readonly
088     */
089    private Settings settings;
090
091    /**
092     * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
093     * @required
094     * @readonly
095     */
096    private ArtifactFactory factory;
097
098    /**
099     * The registered plugin implementations.
100     *
101     * @parameter expression="${project.build.plugins}"
102     * @required
103     * @readonly
104     */
105    protected List<Plugin> plugins;
106
107    /**
108     * @parameter expression="${localRepository}"
109     * @required
110     * @readonly
111     */
112    protected ArtifactRepository localRepository;
113
114    /**
115     * @see org.apache.maven.plugin.Mojo#execute()
116     */
117    public void execute()
118        throws MojoExecutionException
119    {
120        try
121        {
122            final URL configurationUri = ResourceUtils.toURL(this.configurationUri);
123            if (configurationUri == null)
124            {
125                throw new MojoExecutionException("Configuration could not be loaded from '" + this.configurationUri +
126                        '\'');
127            }
128            final Configuration configuration = this.getConfiguration(configurationUri);
129            boolean execute = true;
130            if (this.lastModifiedCheck)
131            {
132                execute = ResourceUtils.modifiedAfter(
133                        ResourceUtils.getLastModifiedTime(configurationUri),
134                        this.buildSourceDirectory);
135                if (!execute)
136                {
137                    //TODO This duplicates functionality in ModelProcessor. It also doesn't work if files are generated to multiple different project locations.
138                    final Repository[] repositories = configuration.getRepositories();
139                    int repositoryCount = repositories.length;
140                    for (int ctr = 0; ctr < repositoryCount; ctr++)
141                    {
142                        final Repository repository = repositories[ctr];
143                        if (repository != null)
144                        {
145                            final Model[] models = repository.getModels();
146                            final int modelCount = models.length;
147                            for (int ctr2 = 0; ctr2 < modelCount; ctr2++)
148                            {
149                                final Model model = models[ctr2];
150                                execute = ResourceUtils.modifiedAfter(
151                                        model.getLastModified(),
152                                        this.buildSourceDirectory);
153                                if (execute)
154                                {
155                                    break;
156                                }
157                            }
158                        }
159                    }
160                }
161            }
162            if (execute)
163            {
164                this.initializeClasspathFromClassPathElements(this.project.getRuntimeClasspathElements());
165                final AndroMDA andromda = AndroMDA.newInstance();
166                andromda.run(configuration, lastModifiedCheck, this.modelOutputHistory.getAbsolutePath());
167                andromda.shutdown();
168            }
169            else
170            {
171                this.getLog().info("Files are up-to-date, skipping AndroMDA execution");
172            }
173            if (this.buildSourceDirectory != null)
174            {
175                this.getProject().addCompileSourceRoot(this.buildSourceDirectory.toString());
176            }
177        }
178        catch (Throwable throwable)
179        {
180            String message = "Error running AndroMDA";
181            throwable = ExceptionUtils.getRootCause(throwable);
182            if (throwable instanceof MalformedURLException || throwable instanceof FileNotFoundException)
183            {
184                message = "Configuration is not valid '" + this.configurationUri + '\'';
185            }
186            throw new MojoExecutionException(message, throwable);
187        }
188    }
189
190    /**
191     * @param configurationUri The configurationUri to set.
192     */
193    public void setConfigurationUri(String configurationUri)
194    {
195        this.configurationUri = configurationUri;
196    }
197
198    /**
199     * @param project The project to set.
200     */
201    public void setProject(MavenProject project)
202    {
203        this.project = project;
204    }
205
206    /**
207     * Sets the current settings for this Mojo.
208     *
209     * @param settings The settings to set.
210     */
211    public void setSettings(Settings settings)
212    {
213        this.settings = settings;
214    }
215
216    /**
217     * Sets the property files for this project.
218     *
219     * @param propertyFiles
220     */
221    public void setPropertyFiles(List<String> propertyFiles)
222    {
223        this.propertyFiles = propertyFiles;
224    }
225
226    /**
227     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getProject()
228     */
229    protected MavenProject getProject()
230    {
231        return this.project;
232    }
233
234    /**
235     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getPropertyFiles()
236     */
237    protected List<String> getPropertyFiles()
238    {
239        return this.propertyFiles;
240    }
241
242    /**
243     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getSettings()
244     */
245    protected Settings getSettings()
246    {
247        return this.settings;
248    }
249
250    /**
251     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getFactory()
252     */
253    protected ArtifactFactory getFactory()
254    {
255        return this.factory;
256    }
257
258    /**
259     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getPlugins()
260     */
261    protected List<Plugin> getPlugins()
262    {
263        return this.plugins;
264    }
265
266    /**
267     * @see org.andromda.maven.plugin.configuration.AbstractConfigurationMojo#getLocalRepository()
268     */
269    protected ArtifactRepository getLocalRepository()
270    {
271        return this.localRepository;
272    }
273}