View Javadoc
1   package org.andromda.maven.plugin.andromdapp;
2   
3   import java.io.File;
4   import java.net.MalformedURLException;
5   import java.net.URL;
6   import java.net.URLClassLoader;
7   import java.util.ArrayList;
8   import java.util.Collection;
9   import java.util.LinkedHashSet;
10  import java.util.List;
11  import java.util.Set;
12  import org.andromda.core.common.ClassUtils;
13  import org.andromda.maven.plugin.andromdapp.script.ScriptClassGenerator;
14  import org.apache.maven.artifact.Artifact;
15  import org.apache.maven.artifact.factory.ArtifactFactory;
16  import org.apache.maven.artifact.repository.ArtifactRepository;
17  import org.apache.maven.model.Dependency;
18  import org.apache.maven.plugin.AbstractMojo;
19  import org.apache.maven.plugin.MojoExecutionException;
20  import org.apache.maven.plugin.MojoFailureException;
21  import org.apache.maven.project.MavenProject;
22  
23  /**
24   * Allows for the {@link ScriptClassGenerator} mojo to be invoked.
25   * on one or more given classes.
26   *
27   * @author Chad Brandon
28   * @goal instrument-scripts
29   * @phase compile
30   * @requiresDependencyResolution
31   */
32  public class ScriptClassGeneratorMojo
33      extends AbstractMojo
34  {
35      /**
36       * Defines the java files who's classes will be instrumented.
37       *
38       * @required
39       * @parameter
40       */
41      private Location[] locations;
42  
43      /**
44       * Defines the fully qualified class name of the script wrapper implementation.
45       *
46       * @parameter
47       * @required
48       */
49      private String scriptWrapper;
50  
51      /**
52       * @parameter expression="${project}"
53       * @required
54       * @readonly
55       */
56      private MavenProject project;
57  
58      /**
59       * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
60       * @required
61       * @readonly
62       */
63      protected ArtifactFactory factory;
64  
65      /**
66       * @parameter expression="${localRepository}"
67       * @required
68       * @readonly
69       */
70      protected ArtifactRepository localRepository;
71  
72      /**
73       * The java file extension
74       */
75      private static final String JAVA_EXTENSION = ".java";
76  
77      /**
78       * @see org.apache.maven.plugin.Mojo#execute()
79       */
80      public void execute()
81          throws MojoExecutionException, MojoFailureException
82      {
83          try
84          {
85              final ScriptClassGenerator generator = ScriptClassGenerator.getInstance(this.scriptWrapper);
86              if (this.locations != null)
87              {
88                  final List<String> classpathElements = new ArrayList<String>(this.getProvidedClasspathElements());
89                  classpathElements.addAll(this.project.getRuntimeClasspathElements());
90                  this.initializeClassLoader(classpathElements);
91                  for (int ctr = 0; ctr < locations.length; ctr++)
92                  {
93                      final Location location = locations[ctr];
94                      String rootPath = location.getRootPath();
95                      for (final String path : location.getPaths())
96                      {
97                          final int extensionIndex = path.lastIndexOf(JAVA_EXTENSION);
98                          if (extensionIndex != -1)
99                          {
100                             final String className = path.substring(
101                                     0,
102                                     extensionIndex).replaceAll(
103                                     "\\\\|/",
104                                     "\\.");
105                             this.getLog().info("injecting script wrapper: " + className);
106                             generator.modifyClass(
107                                 rootPath,
108                                 ClassUtils.loadClass(className));
109                         }
110                     }
111                 }
112             }
113         }
114         catch (final Throwable throwable)
115         {
116             throw new MojoExecutionException("Failed to inject script wrappers", throwable);
117         }
118     }
119 
120     /**
121      * Adds any dependencies to the current project from the plugin
122      * having the given <code>pluginArtifactId</code>.
123      * This project artifact dependencies are added.
124      * scope=PROVIDED the artifact scope in which to add them (runtime, compile, etc).
125      * @return classpathElements
126      */
127     protected List<String> getProvidedClasspathElements()
128     {
129         final List<String> classpathElements = new ArrayList<String>();
130         for (final Object dependency : this.project.getDependencies())
131         {
132             final Artifact artifact = this.getArtifact(
133                 (Dependency)dependency,
134                 Artifact.SCOPE_PROVIDED);
135             if (artifact != null)
136             {
137                 classpathElements.add(artifact.getFile().getAbsolutePath());
138             }
139         }
140         return classpathElements;
141     }
142 
143     /**
144      * Adds a dependency to the current project's dependencies.
145      *
146      * @param dependency
147      * @param scope the scope of the artifact
148      */
149     private Artifact getArtifact(
150         final Dependency dependency,
151         final String scope)
152     {
153         Artifact artifact = null;
154         final ArtifactRepository localRepository = this.localRepository;
155         final MavenProject project = this.project;
156         if (project != null && localRepository != null)
157         {
158             if (dependency != null)
159             {
160                 artifact =
161                     this.factory.createArtifact(
162                         dependency.getGroupId(),
163                         dependency.getArtifactId(),
164                         dependency.getVersion(),
165                         scope,
166                         dependency.getType());
167                 final File file = new File(
168                         localRepository.getBasedir(),
169                         localRepository.pathOf(artifact));
170                 artifact.setFile(file);
171             }
172         }
173         return artifact;
174     }
175 
176     /**
177      * Sets the current context class loader from the given runtime classpath elements.
178      * @param classpathFiles
179      * @throws MalformedURLException
180      */
181     protected void initializeClassLoader(final Collection<String> classpathFiles)
182         throws MalformedURLException
183     {
184         final Set<URL> classpathUrls = new LinkedHashSet<URL>();
185         classpathUrls.add(new File(this.project.getBuild().getOutputDirectory()).toURI().toURL());
186         if (classpathFiles != null)
187         {
188             for (String fileName : classpathFiles)
189             {
190                 final File file = new File(fileName);
191                 if (this.getLog().isDebugEnabled())
192                 {
193                     getLog().debug("adding to classpath '" + file + '\'');
194                 }
195                 classpathUrls.add(file.toURI().toURL());
196             }
197         }
198         final URLClassLoader loader =
199             new URLClassLoader(classpathUrls.toArray(new URL[classpathUrls.size()]),
200                 Thread.currentThread().getContextClassLoader());
201         Thread.currentThread().setContextClassLoader(loader);
202     }
203 }