001: package org.andromda.maven.plugin.andromdapp;
002:
003: import java.io.File;
004: import java.net.MalformedURLException;
005: import java.net.URL;
006: import java.net.URLClassLoader;
007: import java.util.ArrayList;
008: import java.util.Iterator;
009: import java.util.LinkedHashSet;
010: import java.util.List;
011: import java.util.Set;
012:
013: import org.andromda.core.common.ClassUtils;
014: import org.andromda.maven.plugin.andromdapp.script.ScriptClassGenerator;
015: import org.apache.maven.artifact.Artifact;
016: import org.apache.maven.artifact.DependencyResolutionRequiredException;
017: import org.apache.maven.artifact.factory.ArtifactFactory;
018: import org.apache.maven.artifact.repository.ArtifactRepository;
019: import org.apache.maven.model.Dependency;
020: import org.apache.maven.plugin.AbstractMojo;
021: import org.apache.maven.plugin.MojoExecutionException;
022: import org.apache.maven.plugin.MojoFailureException;
023: import org.apache.maven.project.MavenProject;
024:
025: /**
026: * Allows for the {@link ScriptClassGenerator} mojo to be invoked.
027: * on one or more given classes.
028: *
029: * @author Chad Brandon
030: * @goal instrument-scripts
031: * @phase compile
032: * @requiresDependencyResolution
033: */
034: public class ScriptClassGeneratorMojo extends AbstractMojo {
035: /**
036: * Defines the java files who's classes will be instrumented.
037: *
038: * @required
039: * @parameter
040: */
041: private Location[] locations;
042:
043: /**
044: * Defines the fully qualified class name of the script wrapper implementation.
045: *
046: * @parameter
047: * @required
048: */
049: private String scriptWrapper;
050:
051: /**
052: * @parameter expression="${project}"
053: * @required
054: * @readonly
055: */
056: private MavenProject project;
057:
058: /**
059: * @parameter expression="${component.org.apache.maven.artifact.factory.ArtifactFactory}"
060: * @required
061: * @readonly
062: */
063: protected ArtifactFactory factory;
064:
065: /**
066: * @parameter expression="${localRepository}"
067: * @required
068: * @readonly
069: */
070: protected ArtifactRepository localRepository;
071:
072: /**
073: * The java file extension
074: */
075: private static final String JAVA_EXTENSION = ".java";
076:
077: /**
078: * @see org.apache.maven.plugin.Mojo#execute()
079: */
080: public void execute() throws MojoExecutionException,
081: MojoFailureException {
082: try {
083: final ScriptClassGenerator generator = ScriptClassGenerator
084: .getInstance(this .scriptWrapper);
085: if (this .locations != null) {
086: final List classpathElements = new ArrayList(this
087: .getProvidedClasspathElements());
088: classpathElements.addAll(this .project
089: .getRuntimeClasspathElements());
090: this .initializeClassLoader(classpathElements);
091: for (int ctr = 0; ctr < locations.length; ctr++) {
092: final Location location = locations[ctr];
093: String rootPath = location.getRootPath();
094: for (final Iterator iterator = location.getPaths()
095: .iterator(); iterator.hasNext();) {
096: final String path = (String) iterator.next();
097: final int extensionIndex = path
098: .lastIndexOf(JAVA_EXTENSION);
099: if (extensionIndex != -1) {
100: final String className = path.substring(0,
101: extensionIndex).replaceAll(
102: "\\\\|/", "\\.");
103: this .getLog().info(
104: "injecting script wrapper: "
105: + className);
106: generator.modifyClass(rootPath, ClassUtils
107: .loadClass(className));
108: }
109: }
110: }
111: }
112: } catch (final Throwable throwable) {
113: throw new MojoExecutionException(
114: "Failed to inject script wrappers", throwable);
115: }
116: }
117:
118: /**
119: * Adds any dependencies to the current project from the plugin
120: * having the given <code>pluginArtifactId</code>.
121: *
122: * @param pluginArtifactId the artifactId of the plugin of which to add its dependencies.
123: * @param scope the artifact scope in which to add them (runtime, compile, etc).
124: */
125: protected List getProvidedClasspathElements() {
126: final List classpathElements = new ArrayList();
127: for (final Iterator iterator = this .project.getDependencies()
128: .iterator(); iterator.hasNext();) {
129: final Artifact artifact = this .getArtifact(
130: (Dependency) iterator.next(),
131: Artifact.SCOPE_PROVIDED);
132: if (artifact != null) {
133: classpathElements.add(artifact.getFile()
134: .getAbsolutePath());
135: }
136: }
137: return classpathElements;
138: }
139:
140: /**
141: * Adds a dependency to the current project's dependencies.
142: *
143: * @param dependency
144: * @param scope the scope of the artifact
145: */
146: private Artifact getArtifact(final Dependency dependency,
147: final String scope) {
148: Artifact artifact = null;
149: final ArtifactRepository localRepository = this .localRepository;
150: final MavenProject project = this .project;
151: if (project != null && localRepository != null) {
152: if (dependency != null) {
153: artifact = this .factory.createArtifact(dependency
154: .getGroupId(), dependency.getArtifactId(),
155: dependency.getVersion(), scope, dependency
156: .getType());
157: final File file = new File(
158: localRepository.getBasedir(), localRepository
159: .pathOf(artifact));
160: artifact.setFile(file);
161: }
162: }
163: return artifact;
164: }
165:
166: /**
167: * Sets the current context class loader from the given runtime classpath elements.
168: *
169: * @throws DependencyResolutionRequiredException
170: * @throws MalformedURLException
171: */
172: protected void initializeClassLoader(final List classpathFiles)
173: throws MalformedURLException {
174: final Set classpathUrls = new LinkedHashSet();
175: classpathUrls.add(new File(this .project.getBuild()
176: .getOutputDirectory()).toURL());
177: if (classpathFiles != null && classpathFiles.size() > 0) {
178: for (int ctr = 0; ctr < classpathFiles.size(); ++ctr) {
179: final File file = new File((String) classpathFiles
180: .get(ctr));
181: if (this .getLog().isDebugEnabled()) {
182: getLog()
183: .debug("adding to classpath '" + file + "'");
184: }
185: classpathUrls.add(file.toURL());
186: }
187: }
188: final URLClassLoader loader = new URLClassLoader(
189: (URL[]) classpathUrls.toArray(new URL[0]), Thread
190: .currentThread().getContextClassLoader());
191: Thread.currentThread().setContextClassLoader(loader);
192: }
193: }
|