/** {@inheritDoc} */
  public void execute() throws MojoExecutionException, MojoFailureException {
    try {
      getLog().info("***Starting DependencyToXMLMojo");
      checkReactor(reactorProjects);

      if (getLog().isDebugEnabled()) getLog().debug("Create config-xml-Object");

      final FsmMavenPluginType config = bindXmlConfigToPojo(configXml);

      if (getLog().isDebugEnabled()) getLog().debug("Creating PrototypeXml-Object");

      PrototypeXml prototype = new PrototypeXml(getLog(), prototypeXml);

      if (getLog().isDebugEnabled()) {
        getLog().debug("Getting target-file: " + targetXml.getAbsoluteFile());
        getLog().debug("Enhance created Modules");
      }
      final IResolver resolver =
          new MavenGetArtifactsResolver(
              getLog(), reactorProjects, repoSystem, repoSession, projectBuilder, mavenProject);
      final Map<String, Module> modules = new HashMap<String, Module>();
      for (final ModuleType moduleType : config.getModules().getModule()) {
        if (modules.containsKey(moduleType.getDependencyTagValueInXml())) {
          throw new MojoFailureException(
              "Properties for Module: "
                  + moduleType.getDependencyTagValueInXml()
                  + "defined twice\tFix to prevent unpredictable behaviour!\tPlease contact Responsible Developer, XSD has to be fixed!");
        }
        modules.put(
            moduleType.getDependencyTagValueInXml(),
            resolver.resolve(moduleType, config.getScopes().getScope()));
      }

      if (getLog().isDebugEnabled()) getLog().debug("Enhance Prototype for TargetXml");

      prototype.fillPrototypeDom(modules);

      if (getLog().isDebugEnabled()) getLog().debug("Write TargetXml-File");

      writeDomToTarget(targetXml, prototype.getPrototypeDom());

      if (getLog().isDebugEnabled())
        getLog()
            .debug(
                "Dependencies written to Module-XML:\n\t" + prototype.getPrototypeDom().toString());

      getLog().info("***DependencyToXMLMojo finished");
    } catch (XmlPullParserException e) {
      throw new MojoExecutionException(e.getMessage(), e);
    } catch (IOException e) {
      throw new MojoExecutionException(e.getMessage(), e);
    }
  }
  public void copy(Repository sourceRepository, Repository targetRepository, String version)
      throws WagonException, IOException {
    String prefix = "staging-plugin";

    String fileName = prefix + "-" + version + ".zip";

    String tempdir = System.getProperty("java.io.tmpdir");

    logger.debug("Writing all output to " + tempdir);

    // Create the renameScript script

    String renameScriptName = prefix + "-" + version + "-rename.sh";

    File renameScript = new File(tempdir, renameScriptName);

    // Work directory

    File basedir = new File(tempdir, prefix + "-" + version);

    FileUtils.deleteDirectory(basedir);

    basedir.mkdirs();

    Wagon sourceWagon = wagonManager.getWagon(sourceRepository);
    AuthenticationInfo sourceAuth = wagonManager.getAuthenticationInfo(sourceRepository.getId());

    sourceWagon.connect(sourceRepository, sourceAuth);

    logger.info("Looking for files in the source repository.");

    List<String> files = new ArrayList<String>();

    scan(sourceWagon, "", files);

    logger.info("Downloading files from the source repository to: " + basedir);

    for (String s : files) {

      if (s.contains(".svn")) {
        continue;
      }

      File f = new File(basedir, s);

      FileUtils.mkdir(f.getParentFile().getAbsolutePath());

      logger.info("Downloading file from the source repository: " + s);

      sourceWagon.get(s, f);
    }

    // ----------------------------------------------------------------------------
    // Now all the files are present locally and now we are going to grab the
    // metadata files from the targetRepositoryUrl and pull those down locally
    // so that we can merge the metadata.
    // ----------------------------------------------------------------------------

    logger.info("Downloading metadata from the target repository.");

    Wagon targetWagon = wagonManager.getWagon(targetRepository);

    if (!(targetWagon instanceof CommandExecutor)) {
      throw new CommandExecutionException(
          "Wagon class '"
              + targetWagon.getClass().getName()
              + "' in use for target repository is not a CommandExecutor");
    }

    AuthenticationInfo targetAuth = wagonManager.getAuthenticationInfo(targetRepository.getId());

    targetWagon.connect(targetRepository, targetAuth);

    PrintWriter rw = new PrintWriter(new FileWriter(renameScript));

    File archive = new File(tempdir, fileName);

    for (String s : files) {

      if (s.startsWith("/")) {
        s = s.substring(1);
      }

      if (s.endsWith(MAVEN_METADATA)) {
        File emf = new File(basedir, s + IN_PROCESS_MARKER);

        try {
          targetWagon.get(s, emf);
        } catch (ResourceDoesNotExistException e) {
          // We don't have an equivalent on the targetRepositoryUrl side because we have something
          // new on the sourceRepositoryUrl side so just skip the metadata merging.

          continue;
        }

        try {
          mergeMetadata(emf);
        } catch (XmlPullParserException e) {
          throw new IOException("Metadata file is corrupt " + s + " Reason: " + e.getMessage());
        }
      }
    }

    Set moveCommands = new TreeSet();

    // ----------------------------------------------------------------------------
    // Create the Zip file that we will deploy to the targetRepositoryUrl stage
    // ----------------------------------------------------------------------------

    logger.info("Creating zip file.");

    OutputStream os = new FileOutputStream(archive);

    ZipOutputStream zos = new ZipOutputStream(os);

    scanDirectory(basedir, basedir, zos, version, moveCommands);

    // ----------------------------------------------------------------------------
    // Create the renameScript script. This is as atomic as we can
    // ----------------------------------------------------------------------------

    logger.info("Creating rename script.");

    for (Object moveCommand : moveCommands) {
      String s = (String) moveCommand;

      // We use an explicit unix '\n' line-ending here instead of using the println() method.
      // Using println() will cause files and folders to have a '\r' at the end if the plugin is run
      // on Windows.
      rw.print(s + "\n");
    }

    IOUtil.close(rw);

    ZipEntry e = new ZipEntry(renameScript.getName());

    zos.putNextEntry(e);

    InputStream is = new FileInputStream(renameScript);

    IOUtil.copy(is, zos);

    IOUtil.close(is);

    IOUtil.close(zos);

    sourceWagon.disconnect();

    // Push the Zip to the target system

    logger.info("Uploading zip file to the target repository.");

    targetWagon.put(archive, fileName);

    logger.info("Unpacking zip file on the target machine.");

    String targetRepoBaseDirectory = targetRepository.getBasedir();

    // We use the super quiet option here as all the noise seems to kill/stall the connection

    String command =
        "unzip -o -qq -d "
            + targetRepoBaseDirectory
            + " "
            + targetRepoBaseDirectory
            + "/"
            + fileName;

    ((CommandExecutor) targetWagon).executeCommand(command);

    logger.info("Deleting zip file from the target repository.");

    command = "rm -f " + targetRepoBaseDirectory + "/" + fileName;

    ((CommandExecutor) targetWagon).executeCommand(command);

    logger.info("Running rename script on the target machine.");

    command = "cd " + targetRepoBaseDirectory + "; sh " + renameScriptName;

    ((CommandExecutor) targetWagon).executeCommand(command);

    logger.info("Deleting rename script from the target repository.");

    command = "rm -f " + targetRepoBaseDirectory + "/" + renameScriptName;

    ((CommandExecutor) targetWagon).executeCommand(command);

    targetWagon.disconnect();
  }