Coverage Report - org.apache.camel.maven.RunCamelMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
RunCamelMojo
0% 
0% 
4.211
 
 1  
 /**
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.camel.maven;
 18  
 
 19  
 import java.io.File;
 20  
 import java.lang.reflect.Method;
 21  
 import java.net.MalformedURLException;
 22  
 import java.net.URL;
 23  
 import java.net.URLClassLoader;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collection;
 26  
 import java.util.Collections;
 27  
 import java.util.HashSet;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Properties;
 31  
 import java.util.Set;
 32  
 
 33  
 import org.apache.maven.artifact.Artifact;
 34  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 35  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 36  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 37  
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
 38  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 39  
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 40  
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
 41  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 42  
 import org.apache.maven.artifact.versioning.VersionRange;
 43  
 import org.apache.maven.model.Dependency;
 44  
 import org.apache.maven.model.Exclusion;
 45  
 import org.apache.maven.plugin.MojoExecutionException;
 46  
 import org.apache.maven.plugin.MojoFailureException;
 47  
 import org.apache.maven.project.MavenProject;
 48  
 import org.apache.maven.project.MavenProjectBuilder;
 49  
 import org.apache.maven.project.artifact.MavenMetadataSource;
 50  
 
 51  
 import org.codehaus.mojo.exec.AbstractExecMojo;
 52  
 import org.codehaus.mojo.exec.ExecutableDependency;
 53  
 import org.codehaus.mojo.exec.Property;
 54  
 
 55  
 /**
 56  
  * Runs a CamelContext using any Spring XML configuration files found in
 57  
  * <code>META-INF/spring/*.xml</code> and starting up the context.
 58  
  * 
 59  
  * @goal run
 60  
  * @requiresDependencyResolution runtime
 61  
  * @execute phase="test-compile"
 62  
  */
 63  0
 public class RunCamelMojo extends AbstractExecMojo {
 64  
 
 65  
     // TODO
 66  
     // this code is based on a copy-and-paste of maven-exec-plugin
 67  
     //
 68  
     // If we could avoid the mega-cut-n-paste it would really really help!
 69  
     // ideally all I wanna do is auto-default 2 values!
 70  
     // namely the main and the command line arguments..
 71  
 
 72  
     /**
 73  
      * The maven project.
 74  
      * 
 75  
      * @parameter expression="${project}"
 76  
      * @required
 77  
      * @readonly
 78  
      */
 79  
     protected MavenProject project;
 80  
 
 81  
     /**
 82  
      * @component
 83  
      */
 84  
     private ArtifactResolver artifactResolver;
 85  
 
 86  
     /**
 87  
      * @component
 88  
      */
 89  
     private ArtifactFactory artifactFactory;
 90  
 
 91  
     /**
 92  
      * @component
 93  
      */
 94  
     private ArtifactMetadataSource metadataSource;
 95  
 
 96  
     /**
 97  
      * @parameter expression="${localRepository}"
 98  
      * @required
 99  
      * @readonly
 100  
      */
 101  
     private ArtifactRepository localRepository;
 102  
 
 103  
     /**
 104  
      * @parameter expression="${project.remoteArtifactRepositories}"
 105  
      */
 106  
     private List remoteRepositories;
 107  
 
 108  
     /**
 109  
      * @component
 110  
      */
 111  
     private MavenProjectBuilder projectBuilder;
 112  
 
 113  
     /**
 114  
      * @parameter expression="${plugin.artifacts}"
 115  
      * @readonly
 116  
      */
 117  
     private List pluginDependencies;
 118  
 
 119  
     /**
 120  
      * The main class to execute.
 121  
      * 
 122  
      * @parameter expression="${camel.mainClass}"
 123  
      *            default-value="org.apache.camel.spring.Main"
 124  
      * @required
 125  
      */
 126  
     private String mainClass;
 127  
 
 128  
     /**
 129  
      * The class arguments.
 130  
      * 
 131  
      * @parameter expression="${camel.applicationContext}"
 132  
      */
 133  
     private String[] arguments;
 134  
 
 135  
     /**
 136  
      * A list of system properties to be passed. Note: as the execution is not
 137  
      * forked, some system properties required by the JVM cannot be passed here.
 138  
      * Use MAVEN_OPTS or the exec:exec instead. See the user guide for more
 139  
      * information.
 140  
      * 
 141  
      * @parameter
 142  
      */
 143  
     private Property[] systemProperties;
 144  
 
 145  
     /**
 146  
      * Deprecated; this is not needed anymore. Indicates if mojo should be kept
 147  
      * running after the mainclass terminates. Usefull for serverlike apps with
 148  
      * deamonthreads.
 149  
      * 
 150  
      * @parameter expression="${camel.keepAlive}" default-value="false"
 151  
      */
 152  
     private boolean keepAlive;
 153  
 
 154  
     /**
 155  
      * Indicates if the project dependencies should be used when executing the
 156  
      * main class.
 157  
      * 
 158  
      * @parameter expression="${camel.includeProjectDependencies}"
 159  
      *            default-value="true"
 160  
      */
 161  
     private boolean includeProjectDependencies;
 162  
 
 163  
     /**
 164  
      * Indicates if this plugin's dependencies should be used when executing the
 165  
      * main class. <p/> This is useful when project dependencies are not
 166  
      * appropriate. Using only the plugin dependencies can be particularly
 167  
      * useful when the project is not a java project. For example a mvn project
 168  
      * using the csharp plugins only expects to see dotnet libraries as
 169  
      * dependencies.
 170  
      * 
 171  
      * @parameter expression="${camel.includePluginDependencies}"
 172  
      *            default-value="false"
 173  
      */
 174  
     private boolean includePluginDependencies;
 175  
 
 176  
     /**
 177  
      * If provided the ExecutableDependency identifies which of the plugin
 178  
      * dependencies contains the executable class. This will have the affect of
 179  
      * only including plugin dependencies required by the identified
 180  
      * ExecutableDependency. <p/> If includeProjectDependencies is set to
 181  
      * <code>true</code>, all of the project dependencies will be included on
 182  
      * the executable's classpath. Whether a particular project dependency is a
 183  
      * dependency of the identified ExecutableDependency will be irrelevant to
 184  
      * its inclusion in the classpath.
 185  
      * 
 186  
      * @parameter
 187  
      * @optional
 188  
      */
 189  
     private ExecutableDependency executableDependency;
 190  
 
 191  
     /**
 192  
      * Wether to interrupt/join and possibly stop the daemon threads upon
 193  
      * quitting. <br/> If this is <code>false</code>, maven does nothing
 194  
      * about the daemon threads. When maven has no more work to do, the VM will
 195  
      * normally terminate any remaining daemon threads.
 196  
      * <p>
 197  
      * In certain cases (in particular if maven is embedded), you might need to
 198  
      * keep this enabled to make sure threads are properly cleaned up to ensure
 199  
      * they don't interfere with subsequent activity. In that case, see
 200  
      * {@link #daemonThreadJoinTimeout} and
 201  
      * {@link #stopUnresponsiveDaemonThreads} for further tuning.
 202  
      * </p>
 203  
      * 
 204  
      * @parameter expression="${camel.cleanupDaemonThreads} default-value="true"
 205  
      */
 206  
     private boolean cleanupDaemonThreads;
 207  
 
 208  
     /**
 209  
      * This defines the number of milliseconds to wait for daemon threads to
 210  
      * quit following their interruption.<br/> This is only taken into account
 211  
      * if {@link #cleanupDaemonThreads} is <code>true</code>. A value &lt;=0
 212  
      * means to not timeout (i.e. wait indefinitely for threads to finish).
 213  
      * Following a timeout, a warning will be logged.
 214  
      * <p>
 215  
      * Note: properly coded threads <i>should</i> terminate upon interruption
 216  
      * but some threads may prove problematic: as the VM does interrupt daemon
 217  
      * threads, some code may not have been written to handle interruption
 218  
      * properly. For example java.util.Timer is known to not handle
 219  
      * interruptions in JDK &lt;= 1.6. So it is not possible for us to
 220  
      * infinitely wait by default otherwise maven could hang. A sensible default
 221  
      * value has been chosen, but this default value <i>may change</i> in the
 222  
      * future based on user feedback.
 223  
      * </p>
 224  
      * 
 225  
      * @parameter expression="${camel.daemonThreadJoinTimeout}"
 226  
      *            default-value="15000"
 227  
      */
 228  
     private long daemonThreadJoinTimeout;
 229  
 
 230  
     /**
 231  
      * Wether to call {@link Thread#stop()} following a timing out of waiting
 232  
      * for an interrupted thread to finish. This is only taken into account if
 233  
      * {@link #cleanupDaemonThreads} is <code>true</code> and the
 234  
      * {@link #daemonThreadJoinTimeout} threshold has been reached for an
 235  
      * uncooperative thread. If this is <code>false</code>, or if
 236  
      * {@link Thread#stop()} fails to get the thread to stop, then a warning is
 237  
      * logged and Maven will continue on while the affected threads (and related
 238  
      * objects in memory) linger on. Consider setting this to <code>true</code>
 239  
      * if you are invoking problematic code that you can't fix. An example is
 240  
      * {@link java.util.Timer} which doesn't respond to interruption. To have
 241  
      * <code>Timer</code> fixed, vote for <a
 242  
      * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6336543">this
 243  
      * bug</a>.
 244  
      * 
 245  
      * @parameter expression="${camel.stopUnresponsiveDaemonThreads}
 246  
      *            default-value="false"
 247  
      */
 248  
     private boolean stopUnresponsiveDaemonThreads;
 249  
 
 250  
     /**
 251  
      * Deprecated this is not needed anymore.
 252  
      * 
 253  
      * @parameter expression="${camel.killAfter}" default-value="-1"
 254  
      */
 255  
     private long killAfter;
 256  
 
 257  
     private Properties originalSystemProperties;
 258  
 
 259  
     /**
 260  
      * Execute goal.
 261  
      * 
 262  
      * @throws MojoExecutionException execution of the main class or one of the
 263  
      *                 threads it generated failed.
 264  
      * @throws MojoFailureException something bad happened...
 265  
      */
 266  
     public void execute() throws MojoExecutionException, MojoFailureException {
 267  0
         if (killAfter != -1) {
 268  0
             getLog().warn("Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.");
 269  
         }
 270  
 
 271  0
         if (null == arguments) {
 272  0
             arguments = new String[0];
 273  
         }
 274  
 
 275  0
         if (getLog().isDebugEnabled()) {
 276  0
             StringBuffer msg = new StringBuffer("Invoking : ");
 277  0
             msg.append(mainClass);
 278  0
             msg.append(".main(");
 279  0
             for (int i = 0; i < arguments.length; i++) {
 280  0
                 if (i > 0) {
 281  0
                     msg.append(", ");
 282  
                 }
 283  0
                 msg.append(arguments[i]);
 284  
             }
 285  0
             msg.append(")");
 286  0
             getLog().debug(msg);
 287  
         }
 288  
 
 289  0
         IsolatedThreadGroup threadGroup = new IsolatedThreadGroup(mainClass /* name */);
 290  0
         Thread bootstrapThread = new Thread(threadGroup, new Runnable() {
 291  0
             public void run() {
 292  
                 try {
 293  0
                     Method main = Thread.currentThread().getContextClassLoader().loadClass(mainClass).getMethod("main", new Class[] {String[].class});
 294  0
                     if (!main.isAccessible()) {
 295  0
                         getLog().debug("Setting accessibility to true in order to invoke main().");
 296  0
                         main.setAccessible(true);
 297  
                     }
 298  0
                     main.invoke(main, new Object[] {arguments});
 299  0
                 } catch (Exception e) { // just pass it on
 300  0
                     Thread.currentThread().getThreadGroup().uncaughtException(Thread.currentThread(), e);
 301  0
                 }
 302  0
             }
 303  
         }, mainClass + ".main()");
 304  0
         bootstrapThread.setContextClassLoader(getClassLoader());
 305  0
         setSystemProperties();
 306  
 
 307  0
         bootstrapThread.start();
 308  0
         joinNonDaemonThreads(threadGroup);
 309  
         // It's plausible that spontaneously a non-daemon thread might be
 310  
         // created as we try and shut down,
 311  
         // but it's too late since the termination condition (only daemon
 312  
         // threads) has been triggered.
 313  0
         if (keepAlive) {
 314  0
             getLog().warn("Warning: keepAlive is now deprecated and obsolete. Do you need it? Please comment on MEXEC-6.");
 315  0
             waitFor(0);
 316  
         }
 317  
 
 318  0
         if (cleanupDaemonThreads) {
 319  
 
 320  0
             terminateThreads(threadGroup);
 321  
 
 322  
             try {
 323  0
                 threadGroup.destroy();
 324  0
             } catch (IllegalThreadStateException e) {
 325  0
                 getLog().warn("Couldn't destroy threadgroup " + threadGroup, e);
 326  0
             }
 327  
         }
 328  
 
 329  0
         if (originalSystemProperties != null) {
 330  0
             System.setProperties(originalSystemProperties);
 331  
         }
 332  
 
 333  0
         synchronized (threadGroup) {
 334  0
             if (threadGroup.uncaughtException != null) {
 335  0
                 throw new MojoExecutionException(null, threadGroup.uncaughtException);
 336  
             }
 337  0
         }
 338  
 
 339  0
         registerSourceRoots();
 340  0
     }
 341  
 
 342  0
     class IsolatedThreadGroup extends ThreadGroup {
 343  
         Throwable uncaughtException; // synchronize access to this
 344  
 
 345  0
         public IsolatedThreadGroup(String name) {
 346  0
             super(name);
 347  0
         }
 348  
 
 349  
         public void uncaughtException(Thread thread, Throwable throwable) {
 350  0
             if (throwable instanceof ThreadDeath) {
 351  0
                 return; // harmless
 352  
             }
 353  0
             boolean doLog = false;
 354  0
             synchronized (this) {
 355  
                 // only remember the first one
 356  0
                 if (uncaughtException == null) {
 357  0
                     uncaughtException = throwable; // will be reported
 358  
                     // eventually
 359  0
                 } else {
 360  0
                     doLog = true;
 361  
                 }
 362  0
             }
 363  0
             if (doLog) {
 364  0
                 getLog().warn("an additional exception was thrown", throwable);
 365  
             }
 366  0
         }
 367  
     }
 368  
 
 369  
     private void joinNonDaemonThreads(ThreadGroup threadGroup) {
 370  
         boolean foundNonDaemon;
 371  
         do {
 372  0
             foundNonDaemon = false;
 373  0
             Collection threads = getActiveThreads(threadGroup);
 374  0
             for (Iterator iter = threads.iterator(); iter.hasNext();) {
 375  0
                 Thread thread = (Thread)iter.next();
 376  0
                 if (thread.isDaemon()) {
 377  0
                     continue;
 378  
                 }
 379  0
                 foundNonDaemon = true; // try again; maybe more threads were
 380  
                 // created while we were busy
 381  0
                 joinThread(thread, 0);
 382  0
             }
 383  0
         } while (foundNonDaemon);
 384  0
     }
 385  
 
 386  
     private void joinThread(Thread thread, long timeoutMsecs) {
 387  
         try {
 388  0
             getLog().debug("joining on thread " + thread);
 389  0
             thread.join(timeoutMsecs);
 390  0
         } catch (InterruptedException e) {
 391  0
             Thread.currentThread().interrupt(); // good practice if don't throw
 392  0
             getLog().warn("interrupted while joining against thread " + thread, e); // not
 393  
             // expected!
 394  0
         }
 395  
         // generally abnormal
 396  0
         if (thread.isAlive()) {
 397  0
             getLog().warn("thread " + thread + " was interrupted but is still alive after waiting at least " + timeoutMsecs + "msecs");
 398  
         }
 399  0
     }
 400  
 
 401  
     private void terminateThreads(ThreadGroup threadGroup) {
 402  0
         long startTime = System.currentTimeMillis();
 403  0
         Set uncooperativeThreads = new HashSet(); // these were not responsive
 404  
         // to interruption
 405  0
         for (Collection threads = getActiveThreads(threadGroup); !threads.isEmpty(); threads = getActiveThreads(threadGroup), threads.removeAll(uncooperativeThreads)) {
 406  
             // Interrupt all threads we know about as of this instant (harmless
 407  
             // if spuriously went dead (! isAlive())
 408  
             // or if something else interrupted it ( isInterrupted() ).
 409  0
             for (Iterator iter = threads.iterator(); iter.hasNext();) {
 410  0
                 Thread thread = (Thread)iter.next();
 411  0
                 getLog().debug("interrupting thread " + thread);
 412  0
                 thread.interrupt();
 413  0
             }
 414  
             // Now join with a timeout and call stop() (assuming flags are set
 415  
             // right)
 416  0
             for (Iterator iter = threads.iterator(); iter.hasNext();) {
 417  0
                 Thread thread = (Thread)iter.next();
 418  0
                 if (!thread.isAlive()) {
 419  0
                     continue; // and, presumably it won't show up in
 420  
                     // getActiveThreads() next iteration
 421  
                 }
 422  0
                 if (daemonThreadJoinTimeout <= 0) {
 423  0
                     joinThread(thread, 0); // waits until not alive; no timeout
 424  0
                     continue;
 425  
                 }
 426  0
                 long timeout = daemonThreadJoinTimeout - (System.currentTimeMillis() - startTime);
 427  0
                 if (timeout > 0) {
 428  0
                     joinThread(thread, timeout);
 429  
                 }
 430  0
                 if (!thread.isAlive()) {
 431  0
                     continue;
 432  
                 }
 433  0
                 uncooperativeThreads.add(thread); // ensure we don't process
 434  
                 // again
 435  0
                 if (stopUnresponsiveDaemonThreads) {
 436  0
                     getLog().warn("thread " + thread + " will be Thread.stop()'ed");
 437  0
                     thread.stop();
 438  0
                 } else {
 439  0
                     getLog().warn("thread " + thread + " will linger despite being asked to die via interruption");
 440  
                 }
 441  0
             }
 442  
         }
 443  0
         if (!uncooperativeThreads.isEmpty()) {
 444  0
             getLog().warn(
 445  
                           "NOTE: " + uncooperativeThreads.size() + " thread(s) did not finish despite being asked to "
 446  
                               + " via interruption. This is not a problem with exec:java, it is a problem with the running code." + " Although not serious, it should be remedied.");
 447  0
         } else {
 448  0
             int activeCount = threadGroup.activeCount();
 449  0
             if (activeCount != 0) {
 450  
                 // TODO this may be nothing; continue on anyway; perhaps don't
 451  
                 // even log in future
 452  0
                 Thread[] threadsArray = new Thread[1];
 453  0
                 threadGroup.enumerate(threadsArray);
 454  0
                 getLog().debug("strange; " + activeCount + " thread(s) still active in the group " + threadGroup + " such as " + threadsArray[0]);
 455  
             }
 456  
         }
 457  0
     }
 458  
 
 459  
     private Collection getActiveThreads(ThreadGroup threadGroup) {
 460  0
         Thread[] threads = new Thread[threadGroup.activeCount()];
 461  0
         int numThreads = threadGroup.enumerate(threads);
 462  0
         Collection result = new ArrayList(numThreads);
 463  0
         for (int i = 0; i < threads.length && threads[i] != null; i++) {
 464  0
             result.add(threads[i]);
 465  
         }
 466  
         // note: result should be modifiable
 467  0
         return result;
 468  
     }
 469  
 
 470  
     /**
 471  
      * Pass any given system properties to the java system properties.
 472  
      */
 473  
     private void setSystemProperties() {
 474  0
         if (systemProperties != null) {
 475  0
             originalSystemProperties = System.getProperties();
 476  0
             for (int i = 0; i < systemProperties.length; i++) {
 477  0
                 Property systemProperty = systemProperties[i];
 478  0
                 String value = systemProperty.getValue();
 479  0
                 System.setProperty(systemProperty.getKey(), value == null ? "" : value);
 480  
             }
 481  
         }
 482  0
     }
 483  
 
 484  
     /**
 485  
      * Set up a classloader for the execution of the main class.
 486  
      * 
 487  
      * @return the classloader
 488  
      * @throws MojoExecutionException
 489  
      */
 490  
     private ClassLoader getClassLoader() throws MojoExecutionException {
 491  0
         List classpathURLs = new ArrayList();
 492  0
         this.addRelevantPluginDependenciesToClasspath(classpathURLs);
 493  0
         this.addRelevantProjectDependenciesToClasspath(classpathURLs);
 494  0
         return new URLClassLoader((URL[])classpathURLs.toArray(new URL[classpathURLs.size()]));
 495  
     }
 496  
 
 497  
     /**
 498  
      * Add any relevant project dependencies to the classpath. Indirectly takes
 499  
      * includePluginDependencies and ExecutableDependency into consideration.
 500  
      * 
 501  
      * @param path classpath of {@link java.net.URL} objects
 502  
      * @throws MojoExecutionException
 503  
      */
 504  
     private void addRelevantPluginDependenciesToClasspath(List path) throws MojoExecutionException {
 505  0
         if (hasCommandlineArgs()) {
 506  0
             arguments = parseCommandlineArgs();
 507  
         }
 508  
 
 509  
         try {
 510  0
             Iterator iter = this.determineRelevantPluginDependencies().iterator();
 511  0
             while (iter.hasNext()) {
 512  0
                 Artifact classPathElement = (Artifact)iter.next();
 513  0
                 getLog().debug("Adding plugin dependency artifact: " + classPathElement.getArtifactId() + " to classpath");
 514  0
                 path.add(classPathElement.getFile().toURL());
 515  0
             }
 516  0
         } catch (MalformedURLException e) {
 517  0
             throw new MojoExecutionException("Error during setting up classpath", e);
 518  0
         }
 519  
 
 520  0
     }
 521  
 
 522  
     /**
 523  
      * Add any relevant project dependencies to the classpath. Takes
 524  
      * includeProjectDependencies into consideration.
 525  
      * 
 526  
      * @param path classpath of {@link java.net.URL} objects
 527  
      * @throws MojoExecutionException
 528  
      */
 529  
     private void addRelevantProjectDependenciesToClasspath(List path) throws MojoExecutionException {
 530  0
         if (this.includeProjectDependencies) {
 531  
             try {
 532  0
                 getLog().debug("Project Dependencies will be included.");
 533  
 
 534  0
                 URL mainClasses = new File(project.getBuild().getOutputDirectory()).toURL();
 535  0
                 getLog().debug("Adding to classpath : " + mainClasses);
 536  0
                 path.add(mainClasses);
 537  
 
 538  0
                 URL testClasses = new File(project.getBuild().getTestOutputDirectory()).toURL();
 539  0
                 getLog().debug("Adding to classpath : " + testClasses);
 540  0
                 path.add(testClasses);
 541  
 
 542  0
                 Set dependencies = project.getArtifacts();
 543  
 
 544  
                 // system scope dependencies are not returned by maven 2.0. See
 545  
                 // MEXEC-17
 546  0
                 dependencies.addAll(getSystemScopeDependencies());
 547  
 
 548  0
                 Iterator iter = dependencies.iterator();
 549  0
                 while (iter.hasNext()) {
 550  0
                     Artifact classPathElement = (Artifact)iter.next();
 551  0
                     getLog().debug("Adding project dependency artifact: " + classPathElement.getArtifactId() + " to classpath");
 552  0
                     path.add(classPathElement.getFile().toURL());
 553  0
                 }
 554  
 
 555  0
             } catch (MalformedURLException e) {
 556  0
                 throw new MojoExecutionException("Error during setting up classpath", e);
 557  0
             }
 558  
         } else {
 559  0
             getLog().debug("Project Dependencies will be excluded.");
 560  
         }
 561  
 
 562  0
     }
 563  
 
 564  
     private Collection getSystemScopeDependencies() throws MojoExecutionException {
 565  0
         List systemScopeArtifacts = new ArrayList();
 566  
 
 567  0
         for (Iterator artifacts = getAllDependencies().iterator(); artifacts.hasNext();) {
 568  0
             Artifact artifact = (Artifact)artifacts.next();
 569  
 
 570  0
             if (artifact.getScope().equals(Artifact.SCOPE_SYSTEM)) {
 571  0
                 systemScopeArtifacts.add(artifact);
 572  
             }
 573  0
         }
 574  0
         return systemScopeArtifacts;
 575  
     }
 576  
 
 577  
     // generic method to retrieve all the transitive dependencies
 578  
     private Collection getAllDependencies() throws MojoExecutionException {
 579  0
         List artifacts = new ArrayList();
 580  
 
 581  0
         for (Iterator dependencies = project.getDependencies().iterator(); dependencies.hasNext();) {
 582  0
             Dependency dependency = (Dependency)dependencies.next();
 583  
 
 584  0
             String groupId = dependency.getGroupId();
 585  0
             String artifactId = dependency.getArtifactId();
 586  
 
 587  
             VersionRange versionRange;
 588  
             try {
 589  0
                 versionRange = VersionRange.createFromVersionSpec(dependency.getVersion());
 590  0
             } catch (InvalidVersionSpecificationException e) {
 591  0
                 throw new MojoExecutionException("unable to parse version", e);
 592  0
             }
 593  
 
 594  0
             String type = dependency.getType();
 595  0
             if (type == null) {
 596  0
                 type = "jar"; //$NON-NLS-1$
 597  
             }
 598  0
             String classifier = dependency.getClassifier();
 599  0
             boolean optional = dependency.isOptional();
 600  0
             String scope = dependency.getScope();
 601  0
             if (scope == null) {
 602  0
                 scope = Artifact.SCOPE_COMPILE;
 603  
             }
 604  
 
 605  0
             Artifact art = this.artifactFactory.createDependencyArtifact(groupId, artifactId, versionRange, type, classifier, scope, optional);
 606  
 
 607  0
             if (scope.equalsIgnoreCase(Artifact.SCOPE_SYSTEM)) {
 608  0
                 art.setFile(new File(dependency.getSystemPath()));
 609  
             }
 610  
 
 611  0
             List exclusions = new ArrayList();
 612  0
             for (Iterator j = dependency.getExclusions().iterator(); j.hasNext();) {
 613  0
                 Exclusion e = (Exclusion)j.next();
 614  0
                 exclusions.add(e.getGroupId() + ":" + e.getArtifactId()); //$NON-NLS-1$
 615  0
             }
 616  
 
 617  0
             ArtifactFilter newFilter = new ExcludesArtifactFilter(exclusions);
 618  
 
 619  0
             art.setDependencyFilter(newFilter);
 620  
 
 621  0
             artifacts.add(art);
 622  0
         }
 623  
 
 624  0
         return artifacts;
 625  
     }
 626  
 
 627  
     /**
 628  
      * Determine all plugin dependencies relevant to the executable. Takes
 629  
      * includePlugins, and the executableDependency into consideration.
 630  
      * 
 631  
      * @return a set of Artifact objects. (Empty set is returned if there are no
 632  
      *         relevant plugin dependencies.)
 633  
      * @throws MojoExecutionException
 634  
      */
 635  
     private Set determineRelevantPluginDependencies() throws MojoExecutionException {
 636  
         Set relevantDependencies;
 637  0
         if (this.includePluginDependencies) {
 638  0
             if (this.executableDependency == null) {
 639  0
                 getLog().debug("All Plugin Dependencies will be included.");
 640  0
                 relevantDependencies = new HashSet(this.pluginDependencies);
 641  0
             } else {
 642  0
                 getLog().debug("Selected plugin Dependencies will be included.");
 643  0
                 Artifact executableArtifact = this.findExecutableArtifact();
 644  0
                 Artifact executablePomArtifact = this.getExecutablePomArtifact(executableArtifact);
 645  0
                 relevantDependencies = this.resolveExecutableDependencies(executablePomArtifact);
 646  
             }
 647  0
         } else {
 648  0
             relevantDependencies = Collections.EMPTY_SET;
 649  0
             getLog().debug("Plugin Dependencies will be excluded.");
 650  
         }
 651  0
         return relevantDependencies;
 652  
     }
 653  
 
 654  
     /**
 655  
      * Get the artifact which refers to the POM of the executable artifact.
 656  
      * 
 657  
      * @param executableArtifact this artifact refers to the actual assembly.
 658  
      * @return an artifact which refers to the POM of the executable artifact.
 659  
      */
 660  
     private Artifact getExecutablePomArtifact(Artifact executableArtifact) {
 661  0
         return this.artifactFactory.createBuildArtifact(executableArtifact.getGroupId(), executableArtifact.getArtifactId(), executableArtifact.getVersion(), "pom");
 662  
     }
 663  
 
 664  
     /**
 665  
      * Examine the plugin dependencies to find the executable artifact.
 666  
      * 
 667  
      * @return an artifact which refers to the actual executable tool (not a
 668  
      *         POM)
 669  
      * @throws MojoExecutionException
 670  
      */
 671  
     private Artifact findExecutableArtifact() throws MojoExecutionException {
 672  
         // ILimitedArtifactIdentifier execToolAssembly =
 673  
         // this.getExecutableToolAssembly();
 674  
 
 675  0
         Artifact executableTool = null;
 676  0
         for (Iterator iter = this.pluginDependencies.iterator(); iter.hasNext();) {
 677  0
             Artifact pluginDep = (Artifact)iter.next();
 678  0
             if (this.executableDependency.matches(pluginDep)) {
 679  0
                 executableTool = pluginDep;
 680  0
                 break;
 681  
             }
 682  0
         }
 683  
 
 684  0
         if (executableTool == null) {
 685  0
             throw new MojoExecutionException("No dependency of the plugin matches the specified executableDependency." + "  Specified executableToolAssembly is: " + executableDependency.toString());
 686  
         }
 687  
 
 688  0
         return executableTool;
 689  
     }
 690  
 
 691  
     private Set resolveExecutableDependencies(Artifact executablePomArtifact) throws MojoExecutionException {
 692  
 
 693  
         Set executableDependencies;
 694  
         try {
 695  0
             MavenProject executableProject = this.projectBuilder.buildFromRepository(executablePomArtifact, this.remoteRepositories, this.localRepository);
 696  
 
 697  
             // get all of the dependencies for the executable project
 698  0
             List dependencies = executableProject.getDependencies();
 699  
 
 700  
             // make Artifacts of all the dependencies
 701  0
             Set dependencyArtifacts = MavenMetadataSource.createArtifacts(this.artifactFactory, dependencies, null, null, null);
 702  
 
 703  
             // not forgetting the Artifact of the project itself
 704  0
             dependencyArtifacts.add(executableProject.getArtifact());
 705  
 
 706  
             // resolve all dependencies transitively to obtain a comprehensive
 707  
             // list of assemblies
 708  0
             ArtifactResolutionResult result = artifactResolver.resolveTransitively(dependencyArtifacts, executablePomArtifact, Collections.EMPTY_MAP, this.localRepository, this.remoteRepositories,
 709  
                                                                                    metadataSource, null, Collections.EMPTY_LIST);
 710  0
             executableDependencies = result.getArtifacts();
 711  
 
 712  0
         } catch (Exception ex) {
 713  0
             throw new MojoExecutionException("Encountered problems resolving dependencies of the executable " + "in preparation for its execution.", ex);
 714  0
         }
 715  
 
 716  0
         return executableDependencies;
 717  
     }
 718  
 
 719  
     /**
 720  
      * Stop program execution for nn millis.
 721  
      * 
 722  
      * @param millis the number of millis-seconds to wait for, <code>0</code>
 723  
      *                stops program forever.
 724  
      */
 725  
     private void waitFor(long millis) {
 726  0
         Object lock = new Object();
 727  0
         synchronized (lock) {
 728  
             try {
 729  0
                 lock.wait(millis);
 730  0
             } catch (InterruptedException e) {
 731  0
                 Thread.currentThread().interrupt(); // good practice if don't
 732  
                 // throw
 733  0
                 getLog().warn("Spuriously interrupted while waiting for " + millis + "ms", e);
 734  0
             }
 735  0
         }
 736  0
     }
 737  
 
 738  
 }