/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.myfaces.trinidadbuild.plugin.jdeveloper;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import java.net.URL;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;

import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import org.xml.sax.SAXException;

  /*
   * Important informational note:
   *
   * The following XML code is similar to what would be seen in a pom file
   * under the maven-jdev-plugin tag if Libraries (e.g. JSP Runtime
   * and JSF 1.2) and Distributed Tag Libraries wanted to be added to the .jpr
   * project.
   *
   * What you see below are the defaults that are put in a project's .jpr
   * automatically without specifying anything.  See replaceLibraries(),
   * replaceTagLibraries() and replaceDefaultTagLibraries().
   *
   * Also note that by setting the property "jdev.plugin.add.libraries" to
   * false in a project's pom.xml file, no libraries will be added, default
   * or otherwise.  In kind, setting the property "jdev.plugin.add.taglibs"
   * to false will result in no tag libraries of any kind being added.
   *
   * As you would expect, the default for both of these properties is "true".
   *
   *   <plugin>
        <groupId>org.apache.myfaces.trinidadbuild</groupId>
        <artifactId>maven-jdev-plugin</artifactId>
        <version>1.2.4-SNAPSHOT</version>
        <inherited>true</inherited>
        <configuration>
          <libraries>
            <library>JSP Runtime</library>
            <library>JSF 1.2</library>
          </libraries>
          <distributedTagLibraries>
            <distributedTagLibrary>
              <property>
                <name>name</name>
                <value>JSF HTML</value>
              </property>
              <property>
                <name>version</name>
                <value>1.2</value>
              </property>
              <property>
                <name>jspVersion</name>
                <value>2.1</value>
              </property>
              <property>
                <name>tld</name>
                <value>html_basic.tld</value>
              </property>
              <property>
                <name>URI</name>
                <value>http://java.sun.com/jsf/html</value>
              </property>
            </distributedTagLibrary>
            <distributedTagLibrary>
              <property>
                <name>name</name>
                <value>JSF Core</value>
              </property>
              <property>
                <name>version</name>
                <value>1.2</value>
              </property>
              <property>
                <name>jspVersion</name>
                <value>2.1</value>
              </property>
              <property>
                <name>tld</name>
                <value>jsf_core.tld</value>
              </property>
              <property>
                <name>URI</name>
                <value>http://java.sun.com/jsf/core</value>
              </property>
            </distributedTagLibrary>
          </distributedTagLibraries>
        </configuration>
      </plugin>
 */

/**
 * Generates the JDeveloper Workspace and Projects
 * from a maven development environment.
 * @version $Id$
 * @goal jdev
 * @execute phase=process-resources
 * @requiresDependencyResolution test
 * @description Goal which generates the JDeveloper Workspace and Projects
 *              from a maven development environment.
 */
public class JDeveloperMojo
  extends AbstractMojo
{
  /**
   * Append the version string to the workspace name if set
   * @parameter default-value=false
   *
   */
  private boolean appendVersion;

  /**
   * Compiler to be used by JDeveloper. "Ojc" is the default.  
   * If this parameter is absent or anything other than "Javac", "Ojc" will
   * be used.
   * @parameter expression="${jdev.compiler}" default-value="Ojc"
   */
  private String compiler;

  /**
   * Context root name.
   * @parameter expression="${j2ee.contextRoot}"
   */
  private String contextRoot;

  /**
   * Tag libraries and their properties.
   * @parameter
   */
  private Properties[] distributedTagLibraries;

  /**
   * Force the Mojo to use the default project.xml or
   * workspace.xml file to be used in creation of the
   * workspace file (.jws) or project file (.jpr). Otherwise,
   * if a .jws or .jpr exists, it will be used instead.
   * @parameter expression="${force}" default-value=false
   *
   */
  private boolean force;

  /**
   * JVM javaOptions found under 
   * Project Properties->Run/Debug/Profile->Launch Settings->Java Options
   * in JDeveloper. "-ea" is the default for "enableAssertions".  
   * @parameter expression="${jdev.jvm.java.options}" default-value="-ea"
   */
  private String javaOptions;

  /**
   * Libraries to include in Classpath.
   * @parameter
   */
  private String[] libraries;

  /**
   * Make the entire project before each run.  Running anything in the
   * project will automatically trigger a make of the entire project
   * followed by the run.
   * @parameter expression="${jdev.make.project}" default-value="false"
   */
  private boolean makeProject;

  /**
   * Name of the Maven Project
   * @parameter expression="${project}"
   * @required
   * @readonly
   */
  private MavenProject project;

  /**
   * Does project have tests? Used to determine if the
   * maven-jdev-plugin needs to create a <project name>-test.jpr
   * @parameter expression="${jdev.project.has.tests}" default-value="false"
   */
  private boolean projectHasTests;

  /**
   * To limit the sub-projects included in the generated workspace file,
   * list any projects to exclude here.
   *
   * e.g. To keep the trinidad-blank and trinidad-build projects from showing
   * up in the Trinidad workspace just list them:
   *  <projectsExcluded>
   *    <param>trinidad-blank</param>
   *    <param>trinidad-build</param>
   *  </projectsExcluded>
   * 
   * @parameter
   */
  private String[] projectsExcluded;
  
  /**
   * List of reactorProjects
   * @parameter expression="${reactorProjects}"
   * @required
   * @readonly
   */
  private List reactorProjects;

  /**
   * Create JDeveloper Workspace and Project Files that correspond to
   * the format used
   * @parameter expression="${jdev.release}" default-value="10.1.3.0.4"
   */
  private String release;

  /**
   * List of resource root directories
   * @parameter
   */
  private File[] resourceRoots;

  /**
   * Default file to be run when JDeveloper project is run.
   * @parameter expression="${jdev.run.target}"
   */
  private String runTarget;

  /**
   * List of source root directories
   * @parameter
   */
  private File[] sourceRoots;

  /**
   * Tag library directory used by each distributed jsf tag library
   *
   * @parameter expression="${jdev.tag.lib.dir}"
   */
  private String tagLibDirectory;

  /**
   * List of resource root directories for the test project
   * @parameter
   */
  private File[] testResourceRoots;

  /**
   * List of source root directories for the test project
   * @parameter
   */
  private File[] testSourceRoots;

  /**
   * Execute the Mojo.
   */
  public void execute()
    throws MojoExecutionException
  {
    _parseRelease();

    if (tagLibDirectory == null)
    {
      if (_releaseMajor >= 11)
      {
        tagLibDirectory = 
          "@oracle.home@/modules/oracle.jsf_1.2.9/glassfish.jsf_1.2.9.0.jar!/META-INF";
      }
      else
      {
        tagLibDirectory =
          "@oracle.home@lib/java/shared/oracle.jsf/1.2/jsf-ri.jar!/META-INF";
      }
    }

    try
    {
      generateWorkspace();
      generateProject();
      generateTestProject();
    }
    catch (IOException e)
    {
      throw new MojoExecutionException(e.getMessage());
    }
  }

  private void generateWorkspace()
    throws MojoExecutionException, IOException
  {
    if (!project.getCollectedProjects().isEmpty())
    {
      getLog().info("Generating JDeveloper " + release + " workspace: " +
                    project.getArtifactId());

      File workspaceFile = getJWorkspaceFile(project);

      try
      {
        Xpp3Dom workspaceDOM = readWorkspaceDOM(workspaceFile);
        replaceProjects(workspaceFile.getParentFile(), workspaceDOM);
        writeDOM(workspaceFile, workspaceDOM);
      }
      catch (XmlPullParserException e)
      {
        throw new MojoExecutionException("Error generating workspace", e);
      }
    }
  }

  private void generateProject()
    throws IOException, MojoExecutionException
  {
    if (!"pom".equals(project.getPackaging()))
    {
      File projectFile = getJProjectFile(project);

      // Get Project Properties to tell Mojo whether or not to add
      // library refs and taglibs to the project.
      Properties props = project.getProperties();
      String addLibs = (String)props.get(_PROPERTY_ADD_LIBRARY);
      String addTagLibs = (String)props.get(_PROPERTY_ADD_TAGLIBS);
      _addLibraries = (addLibs == null)
        ? true : (new Boolean(addLibs)).booleanValue();
      _addTagLibs   = (addTagLibs == null)
        ? true : (new Boolean(addTagLibs)).booleanValue();

      // TODO: read configuration for war:war goal
      File webappDir = new File(project.getBasedir(), "src/main/webapp");
      // TODO: read configuration for compiler:complie goal
      File outputDir =
        new File(project.getBuild().getDirectory(), "classes");

      MavenProject executionProject = project.getExecutionProject();
      List compileSourceRoots = executionProject.getCompileSourceRoots();
      if (sourceRoots != null)
      {
        for (int i = 0; i < sourceRoots.length; i++)
        {
          compileSourceRoots.add(sourceRoots[i].getAbsolutePath());
        }
      }

      List compileResourceRoots = executionProject.getResources();
      if (resourceRoots != null)
      {
        for (int i = 0; i < resourceRoots.length; i++)
        {
          Resource resource = new Resource();
          resource.setDirectory(resourceRoots[i].getAbsolutePath());
          compileResourceRoots.add(resource);
        }
      }

      getLog().info("Generating JDeveloper " + release + " Project " +
                    project.getArtifactId());

      Set pluginArtifacts = new LinkedHashSet();
      pluginArtifacts.addAll(project.getPluginArtifacts());

      // Note: include "compile", "provided", "system" and "runtime" scopes
      Set compileArtifacts = new LinkedHashSet();
      compileArtifacts.addAll(project.getCompileArtifacts());
      compileArtifacts.addAll(project.getRuntimeArtifacts());

      // Note: separate "runtime" vs. "compile" dependencies in JDeveloper?
      generateProject(projectFile, project.getArtifactId(),
                      project.getPackaging(), project.getDependencies(),
                      new ArrayList(compileArtifacts), compileSourceRoots,
                      compileResourceRoots,
                      Collections.singletonList(webappDir.getPath()),
                      outputDir);
    }
  }

  private void generateTestProject()
    throws IOException, MojoExecutionException
  {
    if (!"pom".equals(project.getPackaging()) && projectHasTests)
    {
      File projectFile = getJProjectTestFile(project);

      // Get Project Properties to tell Mojo whether or not to add
      // library refs and taglibs to the project.
      Properties props = project.getProperties();
      String addLibs = (String)props.get(_PROPERTY_ADD_LIBRARY);
      String addTagLibs = (String)props.get(_PROPERTY_ADD_TAGLIBS);
      _addLibraries = (addLibs == null)
        ? true : (new Boolean(addLibs)).booleanValue();
      _addTagLibs   = (addTagLibs == null)
        ? true : (new Boolean(addTagLibs)).booleanValue();
      File webappDir = new File(project.getBasedir(), "src/test/webapp");
      // TODO: read configuration for compiler:testCompile goal
      File outputDir =
        new File(project.getBuild().getDirectory(), "test-classes");

      // self dependency needed for test project
      List testDependencies = new ArrayList(project.getTestDependencies());
      Dependency selfDependency = new Dependency();
      selfDependency.setArtifactId(project.getArtifactId());
      selfDependency.setGroupId(project.getGroupId());
      selfDependency.setType(project.getPackaging());
      testDependencies.add(selfDependency);

      MavenProject executionProject = project.getExecutionProject();
      List compileSourceRoots =
        executionProject.getTestCompileSourceRoots();

      if (testResourceRoots != null)
      {
        for (int i = 0; i < testSourceRoots.length; i++)
        {
          compileSourceRoots.add(testSourceRoots[i].getAbsolutePath());
        }
      }

      List compileResourceRoots = executionProject.getTestResources();
      if (testResourceRoots != null)
      {
        for (int i = 0; i < testResourceRoots.length; i++)
        {
          Resource resource = new Resource();
          resource.setDirectory(testSourceRoots[i].getAbsolutePath());
          compileResourceRoots.add(resource);
        }
      }

      getLog().info("Generating JDeveloper " + release + " Project " +
                    project.getArtifactId() + "-test");

      // Note: all artifacts implicitly included in "test" scope
      generateProject(projectFile, project.getArtifactId() + "-test",
                      project.getPackaging(), testDependencies,
                      project.getTestArtifacts(), compileSourceRoots,
                      compileResourceRoots,
                      Collections.singletonList(webappDir.getPath()),
                      outputDir);
    }
  }

  private void generateProject(File projectFile, String projectName,
                               String packaging, List dependencies,
                               List artifacts, List sourceRoots,
                               List resourceRoots, List webSourceRoots,
                               File outputDir)
    throws IOException, MojoExecutionException
  {
    try
    {
      File projectDir = projectFile.getParentFile();
      Xpp3Dom projectDOM = readProjectDOM(projectFile);
      replaceWebappInfo(projectName, projectDOM);
      replaceSourcePaths(projectDir, sourceRoots, resourceRoots,
                         projectDOM);
      //replaceResourcePaths(projectDir, resourceRoots, projectDOM);
      replaceWebSourcePaths(projectDir, webSourceRoots, projectDOM);
      replaceDependencies(projectDir, dependencies, projectDOM);
      replaceLibraries(projectDir, artifacts, projectDOM);
      replaceTagLibraries(projectDOM);
      replaceOutputDirectory(projectDir, outputDir, projectDOM);
      replaceParameters(projectName, projectDOM);
      writeDOM(projectFile, projectDOM);

      /* Not needed in release 11 where .tld files are obtained
      ** From jar's META-INF dir, not in WEB-INF dir as in v10
      */
      if ( (_releaseMajor < 11) && ("war".equals(packaging)) )
        copyTagLibraries(projectDir, dependencies, artifacts);

    }
    catch (XmlPullParserException e)
    {
      throw new MojoExecutionException("Error generating project", e);
    }
  }

  private void replaceProjects(File workspaceDir, Xpp3Dom workspaceDOM)
    throws XmlPullParserException
  {
    // /jws:workspace
    //   /list[@n="listOfChildren"]
    Xpp3Dom sourceDOM = workspaceDOM.getChild("list");

    // <hash>
    //   <value n="nodeClass" v="oracle.jdeveloper.model.JProject"/>
    //   <url n="URL" path="[workspace-relative-path-to-project.jpr]"/>
    // </hash>
    Xpp3Dom targetDOM = new Xpp3Dom("list");

    for (Iterator i = project.getCollectedProjects().iterator(); i.hasNext(); )
    {
      MavenProject collectedProject = (MavenProject) i.next();
      File projectFile = getJProjectFile(collectedProject);

      boolean excluded = false;
      String projName = projectFile.getName();
        
      // Don't put any excluded projects into the hash
      if (projectsExcluded != null)
      {
        for (String excl: projectsExcluded)
        {
          if (projName.contains(excl))
          {
            getLog().info("Skipping excluded " + projName);
            excluded = true;
            break;
          }
        }
      }
      if (excluded)
        continue;

      boolean projHasTests = false;

      // Added in V11
      if (_releaseMajor >= 11)
      {
        Properties props = collectedProject.getProperties();
        String hasTests = (String)props.get(_PROPERTY_HAS_TESTS);
        projHasTests = "true".equalsIgnoreCase(hasTests);
      }

      getLog().info("projHasTests is " + Boolean.valueOf(projHasTests).toString());

      // if a child project is also a workspace, then don't 
      // put it in the .jws file.  It will have its own .jws
      // file.
      if (!"pom".equals(collectedProject.getPackaging()))
      {
        targetDOM.addChild(createProjectReferenceDOM(workspaceDir,
                                                     projectFile));
  
        File testProjectFile = getJProjectTestFile(collectedProject);

        /*
        ** In V11, we don't create a <projname>-test.jpr if 
        ** a project does not have any tests.
        */
        if (_releaseMajor >= 11)
        {
          if (projHasTests)
          {
            targetDOM.addChild(createProjectReferenceDOM(workspaceDir, 
                                                         testProjectFile));
          }
        }
        else
        {
          targetDOM.addChild(createProjectReferenceDOM(workspaceDir, 
                                                       testProjectFile));
        }      
      }
    }

    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }

  private void replaceWebSourcePaths(File projectDir, List sourceRoots,
                                     Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdeveloper.model.J2eeSettings"]
    //     /hash[@n="webContentSet"]
    //       /list[@n="url-path"]
    Xpp3Dom pathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdeveloper.model.J2eeSettings");
    Xpp3Dom contentSetDOM =
      findNamedChild(pathsDOM, "hash", "webContentSet");
    Xpp3Dom sourceDOM = findNamedChild(contentSetDOM, "list", "url-path");

    //
    // <url path="[relative-path-to-source-root]" />
    //
    Xpp3Dom targetDOM = new Xpp3Dom("list");
    for (Iterator i = sourceRoots.iterator(); i.hasNext(); )
    {
      File sourceRoot = new File((String) i.next());
      String relativeRoot = getRelativeDir(projectDir, sourceRoot);
      Xpp3Dom urlDOM = new Xpp3Dom("url");
      urlDOM.setAttribute("path", relativeRoot);
      targetDOM.addChild(urlDOM);
    }

    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }

  private void replaceWebappInfo(String projectName, Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdeveloper.model.J2eeSettings"]
    //     /value[@n="j2eeWebAppName" v="maven-generated-webapp"]
    //     /value[@n="j2eeWebContextRoot" v="maven-generated-context-root"]
    Xpp3Dom settingsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdeveloper.model.J2eeSettings");
    Xpp3Dom webappNameDOM =
      findNamedChild(settingsDOM, "value", "j2eeWebAppName");
    Xpp3Dom webappContextDOM =
      findNamedChild(settingsDOM, "value", "j2eeWebContextRoot");

    // update the webapp name
    webappNameDOM.setAttribute("v", projectName + "-webapp");

    // update the webapp context root
    
    if (contextRoot == null)
    {
      contextRoot = projectName + "-context-root";
    }
    
    webappContextDOM.setAttribute("v", contextRoot);
  }

  private void replaceSourcePaths(File projectDir, List sourceRoots,
                                  List resourceRoots, Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdeveloper.model.PathsConfiguration"]
    //     /hash[@n="javaContentSet"]
    //       /list[@n="url-path"]
    Xpp3Dom pathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdeveloper.model.PathsConfiguration");
    Xpp3Dom contentSetDOM =
      findNamedChild(pathsDOM, "hash", "javaContentSet");
    Xpp3Dom sourceDOM = findNamedChild(contentSetDOM, "list", "constituent-sets");

    //
    // <url path="[relative-path-to-source-root]" />
    //
    Xpp3Dom targetDOM = new Xpp3Dom("list");

    Collections.sort(sourceRoots);
    for (Iterator i = sourceRoots.iterator(); i.hasNext(); )
    {
      File sourceRoot = new File((String) i.next());
      Xpp3Dom hashDOM = new Xpp3Dom("hash");

      Xpp3Dom listDOM = new Xpp3Dom("list");
      listDOM.setAttribute("n", "pattern-filters");
      hashDOM.addChild(listDOM);

      Xpp3Dom stringDOM = new Xpp3Dom("string");
      stringDOM.setAttribute("v", "+**");
      listDOM.addChild(stringDOM);

      listDOM = new Xpp3Dom("list");
      listDOM.setAttribute("n", "url-path");
      hashDOM.addChild(listDOM);

      String relativeRoot = getRelativeDir(projectDir, sourceRoot);
      Xpp3Dom urlDOM = new Xpp3Dom("url");
      urlDOM.setAttribute("path", relativeRoot);
      listDOM.addChild(urlDOM);

      targetDOM.addChild(hashDOM);
    }

    // TODO: get bug fixed in 10.1.3 for copying resources
    Collections.sort(resourceRoots, new Comparator()
        {
          public int compare(Object a, Object b)
          {
            Resource ra = (Resource) a;
            Resource rb = (Resource) b;
            return ra.getDirectory().compareTo(rb.getDirectory());
          }

        });

    for (Iterator i = resourceRoots.iterator(); i.hasNext(); )
    {
      Resource resource = (Resource) i.next();
      File resourceRoot = new File(resource.getDirectory());
      String relativeRoot = getRelativeDir(projectDir, resourceRoot);

      Xpp3Dom hashDOM = new Xpp3Dom("hash");

      Xpp3Dom listDOM = new Xpp3Dom("list");
      listDOM.setAttribute("n", "pattern-filters");
      hashDOM.addChild(listDOM);

      Xpp3Dom stringDOM = null;
      // TODO: This is a Hack for excluding the golden files,
      // which are not really xml files.  We need a way, in
      // the pom file to specify excludes.
      if (relativeRoot.startsWith("src/test/resources"))
      {
        stringDOM = new Xpp3Dom("string");
        stringDOM.setAttribute("v",
                            "-oracle/adfinternal/view/faces/renderkit/golden/");
        listDOM.addChild(stringDOM);
      }

      stringDOM = new Xpp3Dom("string");
      stringDOM.setAttribute("v", "+**");
      listDOM.addChild(stringDOM);

      listDOM = new Xpp3Dom("list");
      listDOM.setAttribute("n", "url-path");
      hashDOM.addChild(listDOM);

      Xpp3Dom urlDOM = new Xpp3Dom("url");
      urlDOM.setAttribute("path", relativeRoot);
      listDOM.addChild(urlDOM);

      targetDOM.addChild(hashDOM);
    }

    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }

  private void replaceResourcePaths(File projectDir, List resourceRoots,
                                    Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.ide.model.ResourcePaths"]
    //     /hash[@n="resourcesContentSet"]
    //       /list[@n="url-path"]

    Xpp3Dom pathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.ide.model.ResourcePaths");
    Xpp3Dom contentSetDOM =
      findNamedChild(pathsDOM, "hash", "resourcesContentSet");
    Xpp3Dom sourceDOM = findNamedChild(contentSetDOM, "list", "url-path");

    //
    // <url path="[relative-path-to-source-root]" />
    //
    Xpp3Dom targetDOM = new Xpp3Dom("list");
    for (Iterator i = resourceRoots.iterator(); i.hasNext(); )
    {
      Resource resource = (Resource) i.next();
      File resourceRoot = new File(resource.getDirectory());
      String relativeRoot = getRelativeDir(projectDir, resourceRoot);
      Xpp3Dom urlDOM = new Xpp3Dom("url");
      urlDOM.setAttribute("path", relativeRoot);
      targetDOM.addChild(urlDOM);
    }

    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }

  private void replaceDependencies(File projectDir, List dependencies,
                                   Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.ide.model.DependencyConfiguration"]
    //     /list[@n="dependencyList"]
    Xpp3Dom configDOM =
      findNamedChild(projectDOM, "hash", "oracle.ide.model.DependencyConfiguration");
    Xpp3Dom sourceDOM =
      findNamedChild(configDOM, "list", "dependencyList");

    Xpp3Dom targetDOM = new Xpp3Dom("list");
    for (Iterator i = dependencies.iterator(); i.hasNext(); )
    {
      Dependency dependency = (Dependency) i.next();
      MavenProject dependentProject =
        findDependentProject(dependency.getManagementKey());
      if (dependentProject != null)
      {
        File dependentProjectFile = getJProjectFile(dependentProject);
        String relativePath =
          getRelativeFile(projectDir, dependentProjectFile);

        Xpp3Dom hashDOM = new Xpp3Dom("hash");
        Xpp3Dom valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "class");
        valueDOM.setAttribute("v",
                              "oracle.jdeveloper.library.ProjectLibrary");
        Xpp3Dom srcOwnValDOM = new Xpp3Dom("value");
        srcOwnValDOM.setAttribute("n", "sourceOwnerURL");
        Xpp3Dom urlDOM = new Xpp3Dom("url");
        urlDOM.setAttribute("n", "sourceURL");
        urlDOM.setAttribute("path", relativePath);
        hashDOM.addChild(valueDOM);
        hashDOM.addChild(srcOwnValDOM);
        hashDOM.addChild(urlDOM);
        targetDOM.addChild(hashDOM);
      }
    }

    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }

  private void replaceLibraries(File projectDir, List artifacts,
                                Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdevimpl.config.JProjectLibraries"]
    //     /hash[@n="internalDefinitions"]
    //       /list[@n="libraryDefinitions"]
    Xpp3Dom projectLibsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdevimpl.config.JProjectLibraries");
    Xpp3Dom internalDefsDOM =
      findNamedChild(projectLibsDOM, "hash", "internalDefinitions");
    Xpp3Dom sourceDefsDOM =
      findNamedChild(internalDefsDOM, "list", "libraryDefinitions");

    // /jpr:project
    //   /hash[@n="oracle.jdevimpl.config.JProjectLibraries"]
    //     /list[@n="libraryReferences"]
    Xpp3Dom sourceRefsDOM =
      findNamedChild(projectLibsDOM, "list", "libraryReferences");

    Xpp3Dom targetDefsDOM = new Xpp3Dom("list");
    Xpp3Dom targetRefsDOM = new Xpp3Dom("list");

    //
    // libraryDefinitions
    //
    // <hash>
    //   <list n="classPath">
    //     <url path="[path-to-artifact]" jar-entry="" />
    //   </list>
    //   <value n="deployedByDefault" v="true"/>
    //   <value n="description" v="[artifact.id]"/>
    //   <value n="id" v="[artifact.id]"/>
    // </hash>
    //

    // sort the artifacts
    Collections.sort(artifacts, new Comparator()
        {
          public int compare(Object a, Object b)
          {
            Artifact arta = (Artifact) a;
            Artifact artb = (Artifact) b;
            return arta.getId().compareTo(artb.getId());
          }

        });

    List libraryRefs = new LinkedList();
    for (Iterator i = artifacts.iterator(); i.hasNext(); )
    {
      Artifact artifact = (Artifact) i.next();

      if (!isDependentProject(artifact.getDependencyConflictId()))
      {
        String id = artifact.getId();
        String path = getRelativeFile(projectDir, artifact.getFile());

        // libraryDefinitions entry
        Xpp3Dom hashDOM = new Xpp3Dom("hash");
        Xpp3Dom listDOM = new Xpp3Dom("list");
        listDOM.setAttribute("n", "classPath");

        Xpp3Dom urlDOM = new Xpp3Dom("url");
        urlDOM.setAttribute("path", path);
        urlDOM.setAttribute("jar-entry", "");
        listDOM.addChild(urlDOM);
        hashDOM.addChild(listDOM);

        Xpp3Dom valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "deployedByDefault");
        valueDOM.setAttribute("v", "true");
        hashDOM.addChild(valueDOM);

        valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "description");
        valueDOM.setAttribute("v", id);
        hashDOM.addChild(valueDOM);

        valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "id");
        valueDOM.setAttribute("v", id);
        hashDOM.addChild(valueDOM);
        targetDefsDOM.addChild(hashDOM);

        libraryRefs.add(id);
      }
    }

    // This boolean is set by specifying the jdev.plugin.add.libraries
    // property at the top of a project's pom file.  There are projects
    // that don't need these libraries in their .jpr files to compile and this
    // property allows them to be excluded.
    //
    // IMPORTANT NOTE: if this property is set in a project,
    // then libraries will NOT be added, even though they
    // may be specified under the maven-jdev-plugin.
    if (_addLibraries)
    {
      // Add libraries.  The default libraries can be
      // overridden in the trunk/toplevel pom file.
      if (_releaseMajor >= 11)
      {
        // Add the default libraries
        libraryRefs.add(0,"JSF 1.2");
        libraryRefs.add(0,"JSP Runtime");
      }

      // Add the libraries
      if (libraries != null)
      {
        for (int i = 0; i < libraries.length; i++)
        {
          // Default libraries for release 11 were already
          // added above.
          if (   (_releaseMajor >= 11)
              && (   ("JSF 1.2".equalsIgnoreCase(libraries[i]))
                  || ("JSP Runtime".equalsIgnoreCase(libraries[i]))
                 )
             )
          {
            continue;
          }
          // Add the library
          libraryRefs.add(0, libraries[i]);
        }
      }
    }

    //
    // libraryReferences
    //
    // <hash>
    //   <value n="id" v="[artifact.id]"/>
    //   <value n="isJDK" v="false"/>
    // </hash>
    //
    Collections.sort(libraryRefs);

    for (Iterator i = libraryRefs.iterator(); i.hasNext(); )
    {
      String id = (String) i.next();

      // libraryReferences entry
      Xpp3Dom hashDOM = new Xpp3Dom("hash");
      Xpp3Dom valueDOM = new Xpp3Dom("value");
      valueDOM.setAttribute("n", "id");
      valueDOM.setAttribute("v", id);
      hashDOM.addChild(valueDOM);

      valueDOM = new Xpp3Dom("value");
      valueDOM.setAttribute("n", "isJDK");
      valueDOM.setAttribute("v", "false");
      hashDOM.addChild(valueDOM);
      targetRefsDOM.addChild(hashDOM);
    }

    // First, add JSP Runtime dependency if src/main/webapp exists
    // TODO: use a better merge algorithm
    removeChildren(sourceDefsDOM);
    removeChildren(sourceRefsDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDefsDOM, targetDefsDOM, Boolean.FALSE);
    Xpp3Dom.mergeXpp3Dom(sourceRefsDOM, targetRefsDOM, Boolean.FALSE);
  }

  private void replaceLocalTagLibraries(Xpp3Dom targetLibsDOM)
    throws XmlPullParserException
  {
    TldContentHandler tldHandler = new TldContentHandler();
    String path = null;

    // Loop through all the .tld files in the WEB-INF dir
    // Parse each and get the values needed for the TagLibraries
    // hash in the .jpr file.
    try
    {
      File webInfDir =
        new File(project.getBasedir(), "src/main/webapp/WEB-INF");
      if (webInfDir == null)
        return;

      File[] files = webInfDir.listFiles();
      if (files == null)
        return;

      Xpp3Dom hashDOM = null;
      Xpp3Dom valueDOM = null;
      for (int i = 0; i < files.length; i++)
      {
        path = files[i].getPath();
        if (path.endsWith(".tld"))
        {
          hashDOM = new Xpp3Dom("hash");
          // we have a tag library.  Parse it and
          // get the values needed for the .jpr file

          // Parse
          tldHandler.parseTld(files[i]);
          // call gettors to get the values
          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "jspVersion");
          valueDOM.setAttribute("v", tldHandler.getJspVersion());
          hashDOM.addChild(valueDOM);

          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "name");
          valueDOM.setAttribute("v", tldHandler.getName());
          hashDOM.addChild(valueDOM);

          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "prefix");
          valueDOM.setAttribute("v", tldHandler.getPrefix());
          hashDOM.addChild(valueDOM);

          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "tldURL");
          valueDOM.setAttribute("v",
            "WEB-INF/" + path.substring(path.indexOf("WEB-INF") +  8));
          hashDOM.addChild(valueDOM);

          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "URI");
          valueDOM.setAttribute("v", tldHandler.getURI());
          hashDOM.addChild(valueDOM);

          valueDOM = new Xpp3Dom("value");
          valueDOM.setAttribute("n", "version");
          valueDOM.setAttribute("v", tldHandler.getVersion());
          hashDOM.addChild(valueDOM);

          // Add each file's hash to the tag-libraries "list"
          targetLibsDOM.addChild(hashDOM);
        } // endif
      } // endfor
      return;
    }
    catch (SAXException saxex)
    {
      getLog().info("SAX Parse Exception parsing " + path + ": " +
                    saxex.getMessage(), saxex);
    }
    catch (IOException ioe)
    {
      getLog().info("Unable to open an InputStream to " + path, ioe);
    }
    catch (ParserConfigurationException pce)
    {
      getLog().info("Unable to create SAX parser for " + path, pce);
    }
  }

  private void replaceTagLibraries(Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // This boolean is set by specifying the jdev.plugin.add.taglibs
    // property at the top of a project's pom file.  There are projects
    // that don't need taglibs in their .jpr files to compile and this
    // allows them to be excluded.
    if (!_addTagLibs)
      return;

    // /jpr:project
    //   /hash[@n="oracle.jdevimpl.webapp.jsp.libraries.model.ProjectTagLibraries"]
    //       /list[@n="tag-libaries"]
    Xpp3Dom projectTagsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdevimpl.webapp.jsp.libraries.model.ProjectTagLibraries");
    Xpp3Dom tagLibsDOM =
      findNamedChild(projectTagsDOM, "list", "tag-libraries");

    Xpp3Dom targetLibsDOM = new Xpp3Dom("list");

    //
    // tagLibraryDefinitions
    //
    //<hash>
    //  <hash n="baseLibrary">
    //    <value n="name" v="JSF HTML"></value>
    //    <value n="version" v="1.2"></value>
    //  </hash>
    //  <value n="jspVersion" v="2.1"></value>
    //  <value n="name" v="JSF HTML"></value>
    //
    //  <value n="tldURL" v="@oracle.home@/jdeveloper/modules/oracle.jsf_1.2.9/glassfish.jsf_1.2.9.0.jar!/META-INF"></value>        
    //  <value n="URI" v="http://java.sun.com/jsf/html"></value>
    //  <value n="version" v="1.2"></value>
    //</hash>
    //

    // Parent "hash"
    Xpp3Dom hashDOM = null;

    // <value...
    Xpp3Dom valueDOM = null;

    if (distributedTagLibraries != null &&
        distributedTagLibraries.length > 0)
    {
      // Process each distributed Tag Library
      for (int i = 0; i < distributedTagLibraries.length; i++)
      {
        Properties disTagLib = distributedTagLibraries[i];
        String nameName = null;
        String nameValue = null;
        String versionName = null;
        String versionValue = null;

        // Create parent hash for each taglib
        hashDOM = new Xpp3Dom("hash");

        // baseLibrary "hash" for each taglib
        Xpp3Dom hashBaseDOM = new Xpp3Dom("hash");
        hashBaseDOM.setAttribute("n", "baseLibrary");
        // Add baseLibrary hash to parent hash
        hashDOM.addChild(hashBaseDOM);

        // Process each property of the taglib
        for (Enumeration keys = disTagLib.propertyNames();
             keys.hasMoreElements(); )
        {
          // Get the name value pair
          String name = (String) keys.nextElement();
          String value = (String) disTagLib.get(name);

          // Put the name and version values
          // inside the baseLibrary hash.
          // This only happens once per taglib
          if ("name".equals(name))
          {
            nameName = name;
            nameValue = value;

            // n="name, v=<name of taglib> in baseLibrary
            valueDOM = new Xpp3Dom("value");
            valueDOM.setAttribute("n", name);
            valueDOM.setAttribute("v", value);
            hashBaseDOM.addChild(valueDOM);

            // Duplicate the "name"  <value...
            // outside of the baseLibrary
            // n="name, v=<name of taglib> in parent hash
            valueDOM = new Xpp3Dom("value");
            valueDOM.setAttribute("n", nameName);
            valueDOM.setAttribute("v", nameValue);
            hashDOM.addChild(valueDOM);
          }
          else if ("version".equals(name))
          {
            versionName = name;
            versionValue = value;

            // n="version" v=<taglib version> in baseLibrary
            valueDOM = new Xpp3Dom("value");
            valueDOM.setAttribute("n", name);
            valueDOM.setAttribute("v", value);
            hashBaseDOM.addChild(valueDOM);

            // Duplicate the "version" <value...
            // outside of the baseLibrary
            // n="version" v=<taglib version> in parent hash
            valueDOM = new Xpp3Dom("value");
            valueDOM.setAttribute("n", versionName);
            valueDOM.setAttribute("v", versionValue);
            hashDOM.addChild(valueDOM);
          }
          else
          {
            if ("tld".equals(name))
            {
              // Did not want to have a URL in the pom file.
              // I just wanted the user to specify the name
              // of the tld file.  So we fix it for JDev
              // here.
              name += "URL";
              value = tagLibDirectory + "/" + value;
            }
            valueDOM = new Xpp3Dom("value");
            valueDOM.setAttribute("n", name);
            valueDOM.setAttribute("v", value);
            hashDOM.addChild(valueDOM);
          }
        } //endfor processing each property

        // We are done with this disTagLib
        // Add it to the targetLibsDOM
        if (hashDOM != null)
          targetLibsDOM.addChild(hashDOM);
      } // endfor processing each distributed tag lib
    } //endif
    else
    {
      // Use Default tag library configuration.  See comment before
      // replaceTagLibraries.
      replaceDefaultTagLibraries(projectDOM, targetLibsDOM);
    }

    // Generate .jpr entries from the .tld files in the project's
    // src/main/webapp/WEB-INF directory.
    replaceLocalTagLibraries(targetLibsDOM);

    // First, add JSP Runtime dependency if src/main/webapp exists
    // TODO: use a better merge algorithm
    removeChildren(tagLibsDOM);

    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(tagLibsDOM, targetLibsDOM, Boolean.FALSE);
  }

  private void replaceDefaultTagLibraries(Xpp3Dom projectDOM,
                                          Xpp3Dom targetLibsDOM)
    throws XmlPullParserException
  {
    // Begin JSF HTML Tag lib
    Xpp3Dom hashDOM     = new Xpp3Dom("hash");
    Xpp3Dom hashBaseDOM = new Xpp3Dom("hash");
    Xpp3Dom valueDOM    = null;

    hashBaseDOM.setAttribute("n", "baseLibrary");

    // Add baseLibrary hash to parent hash
    hashDOM.addChild(hashBaseDOM);

    // Create parent hash for each taglib
    //        hashDOM = new Xpp3Dom("hash");

    // baseLibrary "hash" for each taglib
    // Xpp3Dom hashBaseDOM = new Xpp3Dom("hash");
    //        hashBaseDOM.setAttribute("n", "baseLibrary");

    // n="name, v=<name of taglib> in baseLibrary
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "name");
    valueDOM.setAttribute("v", "JSF HTML");
    hashBaseDOM.addChild(valueDOM);

    // Duplicate the "name"  <value...
    // outside of the baseLibrary
    // n="name, v=<name of taglib> in parent hash
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "name");
    valueDOM.setAttribute("v", "JSF HTML");
    hashDOM.addChild(valueDOM);

    // n="version" v=<taglib version> in baseLibrary
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "version");
    valueDOM.setAttribute("v", "1.2");
    hashBaseDOM.addChild(valueDOM);

    // Duplicate the "version" <value...
    // outside of the baseLibrary
    // n="name, v=<name of taglib> in parent hash
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "version");
    valueDOM.setAttribute("v", "1.2");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "jspVersion");
    valueDOM.setAttribute("v", "2.1");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "tldURL");
    valueDOM.setAttribute("v", tagLibDirectory + "/html_basic.tld");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "URI");
    valueDOM.setAttribute("v", "http://java.sun.com/jsf/html");
    hashDOM.addChild(valueDOM);

    // We are done with this disTagLib
    // Add it to the targetLibsDOM
    if (hashDOM != null)
      targetLibsDOM.addChild(hashDOM);

    // Begin JSF Core Taglib
    hashDOM     = new Xpp3Dom("hash");
    hashBaseDOM = new Xpp3Dom("hash");

    hashBaseDOM.setAttribute("n", "baseLibrary");

    // Add baseLibrary hash to parent hash
    hashDOM.addChild(hashBaseDOM);

    // n="name, v=<name of taglib> in baseLibrary
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "name");
    valueDOM.setAttribute("v", "JSF Core");
    hashBaseDOM.addChild(valueDOM);

    // Duplicate the "name"  <value...
    // outside of the baseLibrary
    // n="name, v=<name of taglib> in parent hash
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "name");
    valueDOM.setAttribute("v", "JSF Core");
    hashDOM.addChild(valueDOM);

    // n="version" v=<taglib version> in baseLibrary
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "version");
    valueDOM.setAttribute("v", "1.2");
    hashBaseDOM.addChild(valueDOM);

    // Duplicate the "version" <value...
    // outside of the baseLibrary
    // n="name, v=<name of taglib> in parent hash
    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "version");
    valueDOM.setAttribute("v", "1.2");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "jspVersion");
    valueDOM.setAttribute("v", "2.1");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "tldURL");
    valueDOM.setAttribute("v", tagLibDirectory + "/jsf_core.tld");
    hashDOM.addChild(valueDOM);

    valueDOM = new Xpp3Dom("value");
    valueDOM.setAttribute("n", "URI");
    valueDOM.setAttribute("v", "http://java.sun.com/jsf/core");
    hashDOM.addChild(valueDOM);

    // We are done with this disTagLib
    // Add it to the targetLibsDOM
    if (hashDOM != null)
      targetLibsDOM.addChild(hashDOM);
  }

  private void replaceParameters(String projectName, Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    if ((_releaseMajor >= 11) && (projectName != null))
    {
      replaceCompiler(projectDOM);
      replaceMakeProjectAndRunTarget(projectDOM);
    }
  }
  private void replaceCompiler(Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    // <hash n="oracle.jdeveloper.compiler.OjcConfiguration">
    //   <value n="assertionsEnabled" v="true"/>
    //   <value n="compiler.name" v="Ojc"/>
    //   <list n="copyRes">
    //      <string v=".java"/>
    Xpp3Dom configDOM =
      findNamedChild(projectDOM, "hash",
                     "oracle.jdeveloper.compiler.OjcConfiguration");
    Xpp3Dom compilerDOM = findNamedChild(configDOM, "value", "compiler.name");
    String compilerValue = "Ojc";

    if (   (compiler != null)
        && "Javac".equalsIgnoreCase(compiler)
       )
    {
      compilerValue = "Javac";
    }
    compilerDOM.setAttribute("v", compilerValue);

    return;
  }

  private void replaceMakeProjectAndRunTarget(Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdeveloper.runner.RunConfigurations"]
    //     /hash[@n="runConfigurationDefinitions"]
    //       /hash[@n="Default"]
    //         /value[@n="compileBeforeRun" v="false"]
    //         /url[@n="targetURL" path="src/main/webapp/index.jspx"]
    Xpp3Dom configDOM =
      findNamedChild(projectDOM, "hash",
                     "oracle.jdeveloper.runner.RunConfigurations");
    Xpp3Dom defsDOM =
      findNamedChild(configDOM, "hash", "runConfigurationDefinitions");
    Xpp3Dom defaultDOM = findNamedChild(defsDOM, "hash", "Default");
    Xpp3Dom makeProjectDom =
      findNamedChild(defaultDOM, "value", "compileBeforeRun");

    if (makeProject)
      makeProjectDom.setAttribute("v", "true");
    else
      makeProjectDom.setAttribute("v", "false");

    Xpp3Dom javaOptionsDom =
      findNamedChild(defaultDOM, "value", "javaOptions");

    if (javaOptions != null)
      javaOptionsDom.setAttribute("v", javaOptions);

   if ((runTarget != null) && !"".equals(runTarget))
    {
      // Convert file separator chars to generic
      String targetURL = "";
      if (File.separatorChar == '/')
        targetURL = runTarget.replace('\\', '/'); // Unix
      else
        targetURL = runTarget.replace('/', '\\'); // Windows

      Xpp3Dom targetDOM = new Xpp3Dom("url");
      targetDOM.setAttribute("path", targetURL);
      targetDOM.setAttribute("n", "targetURL");
      defaultDOM.addChild(targetDOM);
    }

    return;
  }

  private void copyTagLibraries(File projectDir, List dependencies,
                                List artifacts)
    throws IOException
  {
    File targetDir = new File(projectDir, "src/main/webapp/WEB-INF");

    for (Iterator i = dependencies.iterator(); i.hasNext(); )
    {
      Dependency dependency = (Dependency) i.next();
      MavenProject dependentProject =
        findDependentProject(dependency.getManagementKey());
      if (dependentProject != null)
      {
        List resourceRoots = dependentProject.getResources();
        for (Iterator j = resourceRoots.iterator(); j.hasNext(); )
        {
          Resource resource = (Resource) j.next();
          String resourceRoot = resource.getDirectory();
          File resourceDirectory = new File(resourceRoot);
          if (resourceDirectory.exists())
          {
            DirectoryScanner scanner = new DirectoryScanner();
            scanner.setBasedir(resourceRoot);
            scanner.addDefaultExcludes();
            scanner.setIncludes(new String[]
                { "META-INF/*.tld" });
            scanner.scan();

            String[] tldFiles = scanner.getIncludedFiles();
            for (int k = 0; k < tldFiles.length; k++)
            {
              File sourceFile = new File(resourceDirectory, tldFiles[k]);
              File targetFile = new File(targetDir, sourceFile.getName());

              if (targetFile.exists())
                targetFile.delete();
              FileUtils.copyFile(sourceFile, targetFile);
            }
          }
        }
      }
    }


    Map sourceMap = new TreeMap();

    for (Iterator i = artifacts.iterator(); i.hasNext(); )
    {
      Artifact artifact = (Artifact) i.next();
      if (!isDependentProject(artifact.getDependencyConflictId()) &&
          "jar".equals(artifact.getType()))
      {
        File file = artifact.getFile();
        JarFile jarFile = new JarFile(file);
        Enumeration jarEntries = jarFile.entries();
        while (jarEntries.hasMoreElements())
        {
          JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
          String name = jarEntry.getName();
          if (name.startsWith("META-INF/") && name.endsWith(".tld"))
          {
            List taglibs = (List) sourceMap.get(name);
            if (taglibs == null)
            {
              taglibs = new ArrayList();
              sourceMap.put(name, taglibs);
            }

            taglibs.add(file);
          }
        }
      }
    }

    for (Iterator i = sourceMap.entrySet().iterator(); i.hasNext(); )
    {
      Map.Entry e = (Map.Entry) i.next();
      List taglibs = (List) e.getValue();
      String name = (String) e.getKey();

      for (Iterator ti = taglibs.iterator(); ti.hasNext(); )
      {
        File file = (File) ti.next();
        File sourceFile = new File(name);
        StringBuffer buff = new StringBuffer(sourceFile.getName());
        if (taglibs.size() > 1)
        {
          String jarName =
            file.getName().substring(0, file.getName().length() -
                                     ".jar".length());
          buff.insert(buff.length() - ".tld".length(), "-" + jarName);
        }

        URL jarURL = file.toURL();
        URL sourceURL =
          new URL("jar:" + jarURL.toExternalForm() + "!/" + name);
        File targetFile = new File(targetDir, buff.toString());
        if (targetFile.exists())
          targetFile.delete();
        FileUtils.copyURLToFile(sourceURL, targetFile);
        targetFile.setReadOnly();
      }
    }
  }

  private void replaceOutputDirectory(File projectDir, File outputDir,
                                      Xpp3Dom projectDOM)
    throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdevimpl.config.JProjectPaths"]

    Xpp3Dom projectPathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdevimpl.config.JProjectPaths");
    Xpp3Dom sourceDOM = new Xpp3Dom("url");

    //
    // <url @n="outputDirectory" path="[relative-path-to-output-dir]" />
    //
    sourceDOM.setAttribute("path", getRelativeDir(projectDir, outputDir));
    sourceDOM.setAttribute("n", "outputDirectory");
    projectPathsDOM.addChild(sourceDOM);
  }

  /**
   * Returns the JDeveloper project file for a Maven POM.
   *
   * @param project  the Maven POM
   *
   * @return  the JDeveloper project file
   */
  private File getJProjectFile(MavenProject project)
  {
    String jprName = project.getArtifactId() + ".jpr";
    return new File(project.getBasedir(), jprName);
  }

  /**
   * Returns the JDeveloper test project file for a Maven POM.
   *
   * @param project  the Maven POM
   *
   * @return  the JDeveloper test project file
   */
  private File getJProjectTestFile(MavenProject project)
  {
    String jprName = project.getArtifactId() + "-test.jpr";
    return new File(project.getBasedir(), jprName);
  }

  /**
   * Returns the JDeveloper workspace file for a Maven POM.
   *
   * @param project  the Maven POM
   *
   * @return  the JDeveloper workspace file
   */
  private File getJWorkspaceFile(MavenProject project)
  {
    StringBuilder jwsName = new StringBuilder(project.getArtifactId());    

    if (appendVersion)
    {
      jwsName.append("-");
      jwsName.append(release);
    }
    jwsName.append(".jws");
    return new File(project.getBasedir(), jwsName.toString());
  }

  /**
   * Reads a JDeveloper workspace file into DOM.
   *
   * @param workspaceFile  the JDeveloper workspace file
   *
   * @return the parsed DOM
   */
  private Xpp3Dom readWorkspaceDOM(File workspaceFile)
    throws IOException, XmlPullParserException
  {
    return readDOM(workspaceFile, release + "/workspace.xml");
  }

  /**
   * Reads a JDeveloper project file into DOM.
   *
   * @param projectFile  the JDeveloper project file
   *
   * @return the parsed DOM
   */
  private Xpp3Dom readProjectDOM(File projectFile)
    throws IOException, XmlPullParserException
  {
    return readDOM(projectFile, release + "/project.xml");
  }

  /**
   * Reads a source file into DOM, defaulting to a packaged resource if
   * the source file does not already exist.
   *
   * @param sourceFile    the source file to be parsed
   * @param resourcePath  the default packaged resource
   *
   * @return the parsed DOM
   */
  private Xpp3Dom readDOM(File sourceFile, String resourcePath)
    throws IOException, XmlPullParserException
  {
    Reader reader = null;
    try
    {
      if (!force && sourceFile.exists())
      {
        // parse the existing source file
        reader = new FileReader(sourceFile);
      }
      else
      {
        // parse the default resource file
        URL resource = getClass().getResource(resourcePath);

        // ensure that the resourcePath can be found
        if (resource == null)
          throw new IOException("Unable to read resource: " +
                                resourcePath);

        reader = new InputStreamReader(resource.openStream());
      }
      return Xpp3DomBuilder.build(reader);
    }
    finally
    {
      IOUtil.close(reader);
    }
  }

  /**
   * Writes a XML DOM to the target file.
   *
   * @param targetFile  the target file
   * @param sourceDOM   the source DOM
   */
  private void writeDOM(File targetFile, Xpp3Dom sourceDOM)
    throws IOException, XmlPullParserException
  {
    FileWriter writer = null;
    try
    {
      writer = new FileWriter(targetFile);
      Xpp3DomWriter.write(writer, sourceDOM);
    }
    finally
    {
      IOUtil.close(writer);
    }
  }

  private String getRelativeDir(File source, File target)
  {
    return getRelativePath(source, target, true);
  }

  private String getRelativeFile(File source, File target)
  {
    return getRelativePath(source, target, false);
  }

  /**
   * Returns the relative path between two files.
   *
   * @param source  the source file
   * @param target  the target file
   *
   * @return  the relative path between two files
   */
  private String getRelativePath(File source, File target,
                                 boolean isDirectory)
  {
    String sourcePath = source.getAbsolutePath();
    String targetPath = target.getAbsolutePath();

    if (targetPath.startsWith(sourcePath + File.separatorChar))
    {
      String relativePath = targetPath.substring(sourcePath.length() + 1);
      relativePath = relativePath.replace(File.separatorChar, '/');
      if (isDirectory)
        relativePath += "/";
      return relativePath;
    }
    else
    {
      String[] sourcePaths = sourcePath.split("\\" + File.separator);
      String[] targetPaths = targetPath.split("\\" + File.separator);

      // On Windows, the first element in the absolute path is a drive letter
      if (System.getProperty("os.name").startsWith("Windows"))
      {
        // uppercase the drive letter because Cygwin sometimes delivers
        // a lowercase drive letter
        sourcePaths[0] = sourcePaths[0].toUpperCase();
        targetPaths[0] = targetPaths[0].toUpperCase();
      }

      int sourcePathCount = sourcePaths.length;
      int targetPathCount = targetPaths.length;
      int commonPathCount = 0;

      int minPathCount = Math.min(sourcePathCount, targetPathCount);
      for (int i = 0; i < minPathCount; i++)
      {
        if (sourcePaths[i].equals(targetPaths[i]))
          commonPathCount++;
      }

      if (commonPathCount > 0)
      {
        int sourceRelativePathCount = sourcePathCount - commonPathCount;
        int targetRelativePathCount = targetPathCount - commonPathCount;

        int relativePathCount =
          sourceRelativePathCount + targetRelativePathCount;
        String[] relativePaths = new String[relativePathCount];

        for (int i = 0; i < sourceRelativePathCount; i++)
        {
          relativePaths[i] = "..";
        }

        for (int i = 0; i < targetRelativePathCount; i++)
        {
          relativePaths[sourceRelativePathCount + i] =
              targetPaths[commonPathCount + i];
        }

        // join
        StringBuffer relativePath = new StringBuffer();
        for (int i = 0; i < relativePathCount; i++)
        {
          if (i > 0)
            relativePath.append("/");
          relativePath.append(relativePaths[i]);
        }
        return relativePath.toString();
      }
      else
      {
        return targetPath;
      }
    }
  }

  private Xpp3Dom findNamedChild(Xpp3Dom parent, String childName,
                                 String attrValue)
  {
    Xpp3Dom[] hash = parent.getChildren(childName);
    for (int i = 0; i < hash.length; i++)
    {
      if (attrValue.equals(hash[i].getAttribute("n")))
        return hash[i];
    }

    Xpp3Dom child = new Xpp3Dom(childName);
    child.setAttribute("n", attrValue);
    parent.addChild(child);

    return child;
  }

  private MavenProject findDependentProject(String dependencyManagementKey)
  {
    for (Iterator i = reactorProjects.iterator(); i.hasNext(); )
    {
      MavenProject reactorProject = (MavenProject) i.next();
      String ident =
        reactorProject.getArtifact().getDependencyConflictId();
      if (ident.equals(dependencyManagementKey))
        return reactorProject.getExecutionProject();
    }

    return null;
  }

  private boolean isDependentProject(String dependencyManagementKey)
  {
    return (findDependentProject(dependencyManagementKey) != null);
  }

  private void removeChildren(Xpp3Dom parent)
  {
    while (parent.getChildCount() != 0)
      parent.removeChild(0);
  }

  private Xpp3Dom createProjectReferenceDOM(File workspaceDir,
                                            File projectFile)
  {
    Xpp3Dom hashDOM = new Xpp3Dom("hash");
    Xpp3Dom urlDOM = new Xpp3Dom("url");
    urlDOM.setAttribute("n", "URL");
    urlDOM.setAttribute("path", getRelativeFile(workspaceDir, projectFile));
    
    if (_releaseMajor < 11)
    {
      Xpp3Dom valueDOM = new Xpp3Dom("value");
      valueDOM.setAttribute("n", "nodeClass");
      valueDOM.setAttribute("v", "oracle.jdeveloper.model.JProject");
      hashDOM.addChild(valueDOM);
    }
    hashDOM.addChild(urlDOM);
    return hashDOM;
  }

  private void _parseRelease()
  {
    String nums[] = release.split("\\.");
    try
    {
      _releaseMajor = Integer.parseInt(nums[0]);
    }
    catch (NumberFormatException e)
    {
      // Default release is currently 10.x
      _releaseMajor = 10;
    }
    getLog().info("releaseMajor is " + Integer.valueOf(_releaseMajor).toString());
  }

  private int     _releaseMajor = 0;
  private boolean _addLibraries = true;
  private boolean _addTagLibs   = true;

  private static final String _PROPERTY_ADD_LIBRARY = "jdev.plugin.add.libraries";
  private static final String _PROPERTY_ADD_TAGLIBS = "jdev.plugin.add.taglibs";

  // Does nothing in v10.1.3
  private static final String _PROPERTY_HAS_TESTS   = "jdev.project.has.tests";
}
