/**
   * Checks that any jarResources defined in the jnlpFile elements are not also defined in
   * commonJarResources.
   *
   * @throws MojoExecutionException if a duplicate is found.
   */
  private void checkForDuplicateJarResources() throws MojoExecutionException {

    if (this.commonJarResources == null || this.commonJarResources.isEmpty()) {
      return;
    }

    for (Iterator jnlpFileItr = this.jnlpFiles.iterator(); jnlpFileItr.hasNext(); ) {

      JnlpFile jnlpFile = (JnlpFile) jnlpFileItr.next();

      List jnlpJarResources = jnlpFile.getJarResources();

      for (Iterator jarResourceItr = jnlpJarResources.iterator(); jarResourceItr.hasNext(); ) {
        JarResource jarResource = (JarResource) jarResourceItr.next();

        if (this.commonJarResources.contains(jarResource)) {
          String message =
              "Configuration Error: The jar resource element for artifact "
                  + jarResource
                  + " defined in common jar resources is duplicated in the jar "
                  + "resources configuration of the jnlp file identified by the template file "
                  + jnlpFile.getTemplateFilename()
                  + ".";

          throw new MojoExecutionException(message);
        }
      }
    }
  }
  /** {@inheritDoc} */
  public void execute() throws MojoExecutionException, MojoFailureException {

    checkConfiguration();

    try {
      copyResources(getResourcesDirectory(), getWorkDirectory());
    } catch (IOException e) {
      throw new MojoExecutionException(
          "An error occurred attempting to copy " + "resources to the working directory.", e);
    }

    if (this.commonJarResources != null) {
      retrieveJarResources(this.commonJarResources);
    }

    for (Iterator itr = this.jnlpFiles.iterator(); itr.hasNext(); ) {
      JnlpFile jnlpFile = (JnlpFile) itr.next();
      retrieveJarResources(jnlpFile.getJarResources());
    }

    signOrRenameJars();
    packJars();

    for (Iterator itr = this.jnlpFiles.iterator(); itr.hasNext(); ) {
      generateJnlpFile((JnlpFile) itr.next(), getLibPath());
    }

    generateVersionXml();
    copyWorkingDirToOutputDir();
  }
  /**
   * Confirms that each jnlpFile element is configured with a unique JNLP file name.
   *
   * @throws MojoExecutionException
   */
  private void checkForUniqueJnlpFilenames() throws MojoExecutionException {
    Set filenames = new HashSet(this.jnlpFiles.size());

    for (Iterator itr = this.jnlpFiles.iterator(); itr.hasNext(); ) {
      JnlpFile jnlpFile = (JnlpFile) itr.next();

      if (!filenames.add(jnlpFile.getOutputFilename())) {
        throw new MojoExecutionException(
            "Configuration error: Unique JNLP filenames must be provided. "
                + "The following file name appears more than once ["
                + jnlpFile.getOutputFilename()
                + "].");
      }
    }
  }
  /**
   * Generates a version.xml file for all the jarResources configured either in jnlpFile elements or
   * in the commonJarResources element.
   *
   * @throws MojoExecutionException
   */
  private void generateVersionXml() throws MojoExecutionException {

    Set /*JarResource*/ jarResources = new LinkedHashSet();

    // combine the jar resources from commonJarResources and each JnlpFile config

    for (Iterator itr = this.jnlpFiles.iterator(); itr.hasNext(); ) {
      JnlpFile jnlpFile = (JnlpFile) itr.next();
      jarResources.addAll(jnlpFile.getJarResources());
    }

    if (this.commonJarResources != null) {
      jarResources.addAll(this.commonJarResources);
    }

    VersionXmlGenerator generator = new VersionXmlGenerator();
    generator.generate(getLibDirectory(), jarResources);
  }
  /**
   * Checks the collection of jarResources configured for a given jnlpFile element.
   *
   * @param jnlpFile The configuration element whose jarResources are to be checked.
   * @throws MojoExecutionException if any config is invalid.
   */
  private void checkJnlpJarResources(JnlpFile jnlpFile) throws MojoExecutionException {

    List jnlpJarResources = jnlpFile.getJarResources();

    if (jnlpJarResources == null || jnlpJarResources.isEmpty()) {
      throw new MojoExecutionException(
          "Configuration error: A non-empty <jarResources> element must be specified in the plugin "
              + "configuration for the JNLP file named ["
              + jnlpFile.getOutputFilename()
              + "]");
    }

    Iterator itr = jnlpJarResources.iterator();
    List /*JarResource*/ jarsWithMainClass = new ArrayList();

    while (itr.hasNext()) {
      JarResource jarResource = (JarResource) itr.next();

      checkMandatoryJarResourceFields(jarResource);

      if (jarResource.getMainClass() != null) {
        jnlpFile.setMainClass(jarResource.getMainClass());
        jarsWithMainClass.add(jarResource);
      }
    }

    if (jarsWithMainClass.isEmpty()) {
      throw new MojoExecutionException(
          "Configuration error: Exactly one <jarResource> element must "
              + "be declared with a <mainClass> element in the configuration for JNLP file ["
              + jnlpFile.getOutputFilename()
              + "]");
    }

    if (jarsWithMainClass.size() > 1) {
      throw new MojoExecutionException(
          "Configuration error: More than one <jarResource> element has been declared "
              + "with a <mainClass> element in the configuration for JNLP file ["
              + jnlpFile.getOutputFilename()
              + "]");
    }
  }
  private void generateJnlpFile(JnlpFile jnlpFile, String libPath) throws MojoExecutionException {

    File jnlpOutputFile = new File(getWorkDirectory(), jnlpFile.getOutputFilename());

    Set jarResources = new LinkedHashSet();
    jarResources.addAll(jnlpFile.getJarResources());

    if (this.commonJarResources != null && !this.commonJarResources.isEmpty()) {

      for (Iterator itr = this.commonJarResources.iterator(); itr.hasNext(); ) {
        JarResource jarResource = (JarResource) itr.next();
        jarResources.add(jarResource);
      }

      jarResources.addAll(this.commonJarResources);
    }

    JarResourcesGenerator jnlpGenerator =
        new JarResourcesGenerator(
            getProject(),
            getTemplateDirectory(),
            "default-jnlp-servlet-template.vm",
            jnlpOutputFile,
            jnlpFile.getTemplateFilename(),
            jarResources,
            jnlpFile.getMainClass(),
            getWebstartJarURLForVelocity(),
            libPath);

    jnlpGenerator.setExtraConfig(getGeneratorExtraConfig());

    try {
      jnlpGenerator.generate();
    } catch (Exception e) {
      throw new MojoExecutionException(
          "The following error occurred attempting to generate "
              + "the JNLP deployment descriptor: "
              + e,
          e);
    }
  }
  /**
   * Checks the validity of a single jnlpFile configuration element.
   *
   * @param jnlpFile The configuration element to be checked.
   * @throws MojoExecutionException if the config element is invalid.
   */
  private void checkJnlpFileConfiguration(JnlpFile jnlpFile) throws MojoExecutionException {

    if (StringUtils.isEmpty(jnlpFile.getOutputFilename())) {
      throw new MojoExecutionException(
          "Configuration error: An outputFilename must be specified for each jnlpFile element");
    }

    if (jnlpFile.getTemplateFilename() == null) {
      getLog()
          .info(
              "No templateFilename found for "
                  + jnlpFile.getOutputFilename()
                  + ". Will use the default template.");
    } else {
      File templateFile = new File(getTemplateDirectory(), jnlpFile.getTemplateFilename());

      if (!templateFile.isFile()) {
        throw new MojoExecutionException(
            "The specified JNLP template does not exist: [" + templateFile + "]");
      }
    }

    checkJnlpJarResources(jnlpFile);
  }