/**
   * Generates the classpath to be used by the launcher to execute the requested Grails script.
   *
   * @return An array of {@code URL} objects representing the dependencies required on the classpath
   *     to execute the selected Grails script.
   * @throws MojoExecutionException if an error occurs while attempting to resolve the dependencies
   *     and generate the classpath array.
   */
  @SuppressWarnings("unchecked")
  private URL[] generateGrailsExecutionClasspath(Set<Artifact> resolvedArtifacts)
      throws MojoExecutionException {
    try {

      final List<URL> classpath = generateExecutionClasspath(resolvedArtifacts);

      // check to see if someone is adding build listeners on the classpath, and if so, bring in the
      // system classpath and add it to our urls
      // IDEA for example does this
      if (System.getProperty("grails.build.listeners") != null) {
        String cp = System.getProperty("java.class.path");
        for (String c : cp.split(":")) {
          File f = new File(c);
          if (f.exists()) classpath.add(f.toURI().toURL());
        }
      }

      if (System.getProperty("grails.debug.classpath") != null) {
        for (URL url : classpath) {
          getLog().info("classpath " + url.toString());
        }
      }

      /*
       * Add the "tools.jar" to the classpath so that the Grails scripts can run native2ascii.
       * First assume that "java.home" points to a JRE within a JDK.  NOTE that this will not
       * provide a valid path on Mac OSX.  This is not a big deal, as the JDK on Mac OSX already
       * adds the required JAR's to the classpath.  This logic is really only for Windows/*Unix.
       */
      final String javaHome = System.getProperty("java.home");
      File toolsJar = new File(javaHome, "../lib/tools.jar");
      if (!toolsJar.exists()) {
        // The "tools.jar" cannot be found with that path, so
        // now try with the assumption that "java.home" points
        // to a JDK.
        toolsJar = new File(javaHome, "tools.jar");
      }

      if (toolsJar.exists()) {
        java.net.URL url = toolsJar.toURI().toURL();
        if (url != null) {
          classpath.add(url);
        }
      }

      return classpath.toArray(new URL[classpath.size()]);
    } catch (final Exception e) {
      throw new MojoExecutionException("Failed to create classpath for Grails execution.", e);
    }
  }
  private File getPluginTargetDirOverride(Artifact plugin) {
    String pluginLocationOverride =
        System.getProperty(plugin.getGroupId() + ":" + plugin.getArtifactId());

    File targetDir = null;

    if (pluginLocationOverride != null && pluginLocationOverride.length() > 0) {
      targetDir = new File(pluginLocationOverride);
      if (!targetDir.exists()) {
        getLog()
            .error(
                String.format(
                    "Specified directory (%s) for plugin %s:%s:%s could not be found",
                    pluginLocationOverride,
                    plugin.getGroupId(),
                    plugin.getArtifactId(),
                    plugin.getVersion()));
        targetDir = null;
      }
    }
    return targetDir;
  }
  private File getPluginDirAndInstallIfNecessary(final Artifact plugin)
      throws MojoExecutionException {
    boolean targetDirOverridden = true;
    File targetDir = getPluginTargetDirOverride(plugin);
    if (targetDir == null) {
      targetDirOverridden = false;
      targetDir = getPluginTargetDirCentral(plugin);
    }

    String pluginName = getPluginName(plugin);
    final String pluginVersion = plugin.getVersion();
    boolean snapshot = pluginVersion.endsWith("-SNAPSHOT");

    if (snapshot
        && plugin
            .getFile()
            .getAbsolutePath()
            .endsWith("target" + File.separator + "classes")) { // multi module build

      targetDir = plugin.getFile().getParentFile().getParentFile();
      getLog()
          .info(
              String.format(
                  "Plugin %s:%s is coming from a multi-module dependency (%s)",
                  pluginName, pluginVersion, targetDir.getAbsolutePath()));

    } else if ((!snapshot && !targetDir.exists()) || (snapshot && !targetDirOverridden)) {
      // Unpack the plugin if it hasn't already been or if its a SNAPSHOT and not overridden by
      // -Dflag

      // Ideally we need to now do two things (a) see if we are running JDK7
      // and (b) determine if -Dplugin.groupId.artifactId has been set - if this is so, we want to
      // do a Files.createLink
      // to the directory specified by  the -D flag. We should probably also check if the targetDir
      // is a link and
      // the -Dflag hasn't been set, in which case we'd want to remove the link and install the
      // plugin (and let the user
      // know this has happened.
      // We wouldn't actually want this to be allowed when doing a release however.... So people
      // should make sure they don't
      // specify them, they they'll be installed.

      getLog()
          .info(
              String.format(
                  "Installing Plugin %s:%s into (%s)",
                  pluginName, pluginVersion, targetDir.getAbsolutePath()));
      targetDir.mkdirs();

      final ZipUnArchiver unzipper = new ZipUnArchiver();
      unzipper.enableLogging(new ConsoleLogger(Logger.LEVEL_ERROR, "zip-unarchiver"));
      unzipper.setSourceFile(plugin.getFile());
      unzipper.setDestDirectory(targetDir);
      unzipper.setOverwrite(true);
      try {
        unzipper.extract();
      } catch (ArchiverException e) {
        throw new MojoExecutionException("Unable to extract zip", e);
      }
      try {
        File inputPom =
            new File(plugin.getFile().getParentFile(), pluginName + "-" + pluginVersion + ".pom");
        File outputPom = new File(targetDir, "pom.xml");
        getLog()
            .info(
                String.format(
                    "copying %s to %s", inputPom.getAbsolutePath(), outputPom.getAbsolutePath()));
        FileReader fr = new FileReader(inputPom);
        FileWriter fw = new FileWriter(outputPom);
        IOUtils.copy(fr, fw);
        fw.flush();
        fw.close();
        fr.close();
      } catch (IOException e) {
        throw new MojoExecutionException("Unable to copy pom.xml file");
      }
    } else {
      getLog()
          .info(
              String.format(
                  "Plugin %s:%s already installed (%s)",
                  pluginName, pluginVersion, targetDir.getAbsolutePath()));
    }

    return targetDir;
  }