Esempio n. 1
0
  /**
   * This method will movie files from the source directory to the destination directory based on
   * the pattern.
   *
   * @param inSourceDirectory The source directory to copy from.
   * @param inDestinationDirectory The destination directory to copy to.
   * @param inPattern The file pattern to match to locate files to copy.
   */
  protected void moveFiles(
      final String inSourceDirectory, final String inDestinationDirectory, final String inPattern) {
    Move moveTask = (Move) antProject.createTask("move");

    FileSet fileSet = AntUtils.createFileset(inSourceDirectory, inPattern, new ArrayList());
    moveTask.setTodir(new File(inDestinationDirectory));
    moveTask.addFileset(fileSet);
    moveTask.execute();
  }
Esempio n. 2
0
  private List<Dependency> addModuleDependencies(
      List<Dependency> dependencies, String moduleName, String moduleLocation) {
    log("Adding dependencies from " + moduleName + " module...");

    // Read dependencies from module's pom.xml
    URL pomLocation = null;
    File newDir = new File("target", "appfuse-" + moduleName);

    if (!newDir.exists()) {
      newDir.mkdirs();
    }

    File pom = new File("target/appfuse-" + moduleName + "/pom.xml");

    try {
      // replace github.com with raw.github.com and trunk with master
      trunk = trunk.replace("https://github.com", "https://raw.github.com");
      tag = tag.replace("trunk", "master");
      pomLocation = new URL(trunk + tag + moduleLocation + "/pom.xml");
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }

    Get get = (Get) AntUtils.createProject().createTask("get");
    get.setSrc(pomLocation);
    get.setDest(pom);
    get.execute();

    MavenProject p = createProjectFromPom(pom);

    List moduleDependencies = p.getOriginalModel().getDependencies();

    // set the properties for appfuse if root module
    if (moduleName.equalsIgnoreCase("root")) {
      appfuseProperties = p.getOriginalModel().getProperties();
    }

    // create a list of artifactIds to check for duplicates (there's no equals() on Dependency)
    Set<String> artifactIds = new LinkedHashSet<String>();

    for (Dependency dep : dependencies) {
      artifactIds.add(dep.getArtifactId());
    }

    // add all non-appfuse dependencies
    for (Object moduleDependency : moduleDependencies) {
      Dependency dep = (Dependency) moduleDependency;

      if (dep.getGroupId().equals("javax.servlet")
          && dep.getArtifactId().equals("jsp-api")
          && "jsf".equals(project.getProperties().getProperty("web.framework"))) {
        // skip adding dependency for old group id of jsp-api
        continue;
      }

      if (!artifactIds.contains(dep.getArtifactId()) && !dep.getArtifactId().contains("appfuse")) {
        dependencies.add(dep);
      }
    }

    return dependencies;
  }
Esempio n. 3
0
/**
 * This mojo is used to "install" source artifacts from Subversion into an AppFuse project. If you
 * get an OutOfMemoryError when running this plugin, you should be able to fix it by setting your
 * MAVEN_OPTS environment variable to "-Xms128M -Xmx256M".
 *
 * @author <a href="mailto:[email protected]">Matt Raible</a>
 * @goal full-source
 */
public class InstallSourceMojo extends AbstractMojo {
  private static final String APPFUSE_GROUP_ID = "org.appfuse";
  private static final String FILE_SEP = System.getProperty("file.separator");
  private static final String LINE_SEP = System.getProperty("line.separator");

  Project antProject = AntUtils.createProject();
  Properties appfuseProperties;

  // ThreadLocale to hold properties as they're built when traversing through a modular project
  private static final ThreadLocal<Map> propertiesContextHolder = new ThreadLocal<Map>();

  /**
   * The path where the files from SVN will be placed. This is intentionally set to "src" since
   * that's the default src directory used for exporting AppFuse artifacts.
   *
   * @parameter expression="${appfuse.destinationDirectory}" default-value="${basedir}/src"
   */
  private String destinationDirectory;

  /**
   * The directory containing the source code.
   *
   * @parameter expression="${appfuse.trunk}" default-value="https://github.com/appfuse/appfuse/"
   */
  private String trunk;

  /**
   * The tag containing the source code - defaults to '/trunk', but you may want to set it to
   * '/tags/TAGNAME'
   *
   * @parameter expression="${appfuse.tag}" default-value="trunk/"
   */
  private String tag;

  /**
   * <i>Maven Internal</i>: Project to interact with.
   *
   * @parameter expression="${project}"
   * @required
   * @readonly
   * @noinspection UnusedDeclaration
   */
  private MavenProject project;

  public void execute() throws MojoExecutionException, MojoFailureException {
    // http://issues.appfuse.org/browse/APF-1025
    System.setProperty("file.encoding", "UTF-8");

    // If appfuse.version is specified as a property, and not a SNAPSHOT, use it for the tag
    String appfuseVersion = project.getProperties().getProperty("appfuse.version");

    if ((appfuseVersion != null) && !appfuseVersion.endsWith("SNAPSHOT") && tag.equals("trunk/")) {
      tag = "tags/APPFUSE_" + appfuseVersion.toUpperCase().replaceAll("-", "_") + "/";
      // APF-1168: Allow milestone and release candidates
      if (tag.contains("_M")) {
        tag = tag.replace("_M", "-M");
      } else if (tag.contains("_R")) {
        tag = tag.replace("_R", "-R");
      }
    }

    String daoFramework = project.getProperties().getProperty("dao.framework");

    if (daoFramework == null) {
      log("No dao.framework property specified, defaulting to 'hibernate'");
    }

    String webFramework = project.getProperties().getProperty("web.framework");

    boolean modular = (project.getPackaging().equals("pom") && !project.hasParent());
    if (project.getPackaging().equals("jar")
        || (project.getPackaging().equals("war") && !project.hasParent())) {
      // export data-common
      log("Installing source from data-common module...");
      export("data/common/src", (modular) ? "core/src" : destinationDirectory);

      // export persistence framework
      log("Installing source from " + daoFramework + " module...");
      export("data/" + daoFramework + "/src", (modular) ? "core/src" : destinationDirectory);

      // export service module
      log("Installing source from service module...");
      export("service/src", (modular) ? "core/src" : destinationDirectory);

      // move Base*TestCase to test directory
      moveFiles(
          (modular) ? "core/src/main" : destinationDirectory + "/main",
          (modular) ? "core/src/test" : destinationDirectory + "/test",
          "**/Base*TestCase.java");

      // delete dao.framework related files from test directory
      deleteFile("test/resources/hibernate.cfg.xml");
      deleteFile("test/resources/META-INF");
      deleteFile("test/resources/sql-map-config.xml");

      // If JPA, delete hibernate.cfg.xml b/c it will cause issues when
      // using jpaconfiguration with the hibernate3-maven-plugin
      if ("jpa".equalsIgnoreCase(daoFramework)) {
        deleteFile("main/resources/hibernate.cfg.xml");
      }
    }

    // it's OK if a project created with appfuse-ws doesn't have a web framework defined
    // currently, a project with appfuse-ws can be identified by enunciate
    boolean isWebServicesProject = false;
    for (Object pluginArtifact : project.getPluginArtifacts()) {
      if (((Artifact) pluginArtifact).getArtifactId().contains("enunciate")) {
        isWebServicesProject = true;
        break;
      }
    }

    if (project.getPackaging().equalsIgnoreCase("war")) {

      if (webFramework == null && !isWebServicesProject) {
        getLog()
            .error(
                "The web.framework property is not specified - please modify your pom.xml to add "
                    + " this property. For example: <web.framework>struts</web.framework>.");
        throw new MojoExecutionException(
            "No web.framework property specified, please modify pom.xml to add it.");
      }

      if (project.hasParent()) {
        // copy jdbc.properties to core/src/test/resources
        // FileUtils.copyFileToDirectory(new File("src/main/resources/jdbc.properties"), new
        // File("../core/src/test/resources"));

        // delete hibernate, ibatis and jpa files from web project
        deleteFile("main/resources/hibernate.cfg.xml");
        deleteFile("main/resources/META-INF");
        deleteFile("main/resources/sql-map-config.xml");

        // there's a jdbc.properties in test/resources that shouldn't be there
        deleteFile("test/resources/jdbc.properties");
      } else if (!isAppFuse()) {
        // there's a jdbc.properties in test/resources that shouldn't be there
        deleteFile("test/resources/jdbc.properties");
      }
    }

    log("Source successfully exported, modifying pom.xml...");

    List dependencies = project.getOriginalModel().getDependencies();
    List<Dependency> newDependencies = new ArrayList<Dependency>();

    // remove all appfuse dependencies
    for (Object dependency : dependencies) {
      Dependency dep = (Dependency) dependency;

      if (!dep.getGroupId().equals(APPFUSE_GROUP_ID)) {
        newDependencies.add(dep);
      }
    }

    if (!project.getPackaging().equals("pom") && !project.hasParent()) {

      // add dependencies from root appfuse pom
      newDependencies = addModuleDependencies(newDependencies, "root", "");

      // Add dependencies from appfuse-data
      newDependencies = addModuleDependencies(newDependencies, "data", "data");

      // Add dependencies from appfuse-data-common
      newDependencies = addModuleDependencies(newDependencies, "data-common", "data/common");

      // Add dependencies from appfuse-${dao.framework}
      newDependencies =
          addModuleDependencies(newDependencies, daoFramework, "data/" + daoFramework);

      // Add dependencies from appfuse-service
      newDependencies = addModuleDependencies(newDependencies, "service", "service");

      if (!isWebServicesProject && project.getPackaging().equals("war")) {
        newDependencies = addWebDependencies(appfuseVersion, newDependencies, webFramework);
      }

      createFullSourcePom(newDependencies);
    } else {
      if (project.getPackaging().equals("pom")) {
        // add dependencies from root appfuse pom
        newDependencies = addModuleDependencies(newDependencies, "root", "");

        createFullSourcePom(newDependencies);
      }

      if (project.getPackaging().equals("jar")) {
        newDependencies.clear();

        // Add dependencies from appfuse-data
        newDependencies = addModuleDependencies(newDependencies, "data", "data");

        // Add dependencies from appfuse-data-common
        newDependencies = addModuleDependencies(newDependencies, "data-common", "data/common");

        // Add dependencies from appfuse-${dao.framework}
        newDependencies =
            addModuleDependencies(newDependencies, daoFramework, "data/" + daoFramework);

        // Add dependencies from appfuse-service
        newDependencies = addModuleDependencies(newDependencies, "service", "service");

        createFullSourcePom(newDependencies);
      }

      if (project.getPackaging().equals("war")) {
        newDependencies.clear();

        newDependencies = addWebDependencies(appfuseVersion, newDependencies, webFramework);

        createFullSourcePom(newDependencies);
      }
    }
  }

  private List<Dependency> addWebDependencies(
      String appfuseVersion, List<Dependency> newDependencies, String webFramework) {
    // Add dependencies from appfuse-common-web
    newDependencies = addModuleDependencies(newDependencies, "web", "web");

    Double appfuseVersionAsDouble =
        new Double(appfuseVersion.substring(0, appfuseVersion.lastIndexOf(".")));

    getLog().debug("Detected AppFuse version: " + appfuseVersionAsDouble);

    if (isAppFuse() && appfuseVersionAsDouble < 2.1) {

      // Add dependencies from appfuse-common-web
      newDependencies = addModuleDependencies(newDependencies, "web-common", "web/common");

      // newDependencies = addModuleDependencies(newDependencies, webFramework, "web/" +
      // webFramework);
    }

    // modular archetypes still seem to need these - todo: figure out why
    if (isAppFuse() && project.getPackaging().equals("war") && project.hasParent()) {
      newDependencies = addModuleDependencies(newDependencies, "web-common", "web/common");

      newDependencies = addModuleDependencies(newDependencies, webFramework, "web/" + webFramework);
    }
    return newDependencies;
  }

  private boolean isAppFuse() {
    return (project.getProperties().getProperty("copyright.year") != null);
  }

  private void deleteFile(String filePath) {
    if (!filePath.startsWith("/")) {
      filePath = "/" + filePath;
    }
    File duplicateFile = new File(getFilePath(destinationDirectory + filePath));
    try {
      getLog().debug("Looking for duplicate file at '" + duplicateFile.getCanonicalPath());
      if (duplicateFile.exists()) {
        getLog().debug("Deleting duplicate file at '" + duplicateFile.getCanonicalPath());
        if (duplicateFile.isDirectory()) {
          FileUtils.deleteDirectory(duplicateFile);
        } else {
          FileUtils.forceDeleteOnExit(duplicateFile);
        }
      }
    } catch (IOException io) {
      getLog().error("Failed to delete '" + filePath + "', please delete manually.");
    }
  }

  private void createFullSourcePom(List<Dependency> newDependencies) throws MojoFailureException {
    // Change spring-test and jmock dependencies to use <optional>true</option> instead of
    // <scope>test</scope>.
    // This is necessary because Base*TestCase classes are in src/main/java. If we move these
    // classes to their
    // own test module, this will no longer be necessary. For the first version of this mojo, it
    // seems easier
    // to follow the convention used in AppFuse rather than creating a test module and changing all
    // modules to
    // depend on it.

    // create properties based on dependencies while we're at it
    Set<String> projectProperties = new TreeSet<String>();

    for (Dependency dep : newDependencies) {
      if (dep.getArtifactId().equals("spring-test")
          || dep.getArtifactId().contains("jmock")
          || dep.getArtifactId().equals("junit")
          || dep.getArtifactId().equals("shale-test")) {
        dep.setOptional(true);
        dep.setScope(null);
      }
      String version = dep.getVersion();
      // trim off ${}
      if (version.startsWith("${")) {
        version = version.substring(2);
      }

      if (version.endsWith("}")) {
        version = version.substring(0, version.length() - 1);
      }
      projectProperties.add(version);
    }

    // add core as a dependency for modular wars
    if (project.getPackaging().equals("war") && project.hasParent()) {
      Dependency core = new Dependency();
      core.setGroupId("${project.parent.groupId}");
      core.setArtifactId("core");
      core.setVersion("${project.parent.version}");
      newDependencies.add(core);

      // workaround for JSF requiring JSP 2.1 - this is a true hack
      if (project.getProperties().getProperty("web.framework").equals("jsf")) {
        Dependency jsp21 = new Dependency();
        jsp21.setGroupId("javax.servlet.jsp");
        jsp21.setArtifactId("jsp-api");
        jsp21.setVersion("${jsp.version}");
        jsp21.setScope("provided");
        newDependencies.add(jsp21);

        // replace jsp.version property as well
        project.getOriginalModel().getProperties().setProperty("jsp.version", "2.1");
      }
    }

    Collections.sort(newDependencies, new BeanComparator("groupId"));

    project.getOriginalModel().setDependencies(newDependencies);

    Properties currentProperties = project.getOriginalModel().getProperties();

    Set<String> currentKeys = new LinkedHashSet<String>();
    for (Object key : currentProperties.keySet()) {
      currentKeys.add((String) key);
    }

    StringBuffer sortedProperties = new StringBuffer();

    Properties appfuseProperties = getAppFuseProperties();

    // holder for properties - stored in ThreadLocale
    Map<String, String> propertiesForPom = new LinkedHashMap<String, String>();

    for (String key : projectProperties) {
      // don't add property if it already exists in project
      if (!currentKeys.contains(key)) {
        String value = appfuseProperties.getProperty(key);

        // this happens when the version number is hard-coded
        if (value == null) {
          continue;
        }

        // hack for Tapestry depending on commons-pool (a.k.a. commons-dbcp 1.2.2)
        if ("tapestry".equals(project.getProperties().getProperty("web.framework"))
            && key.equals("commons.dbcp.version")) {
          value = "1.2.2";
        }

        if (value.contains("&amp;")) {
          value = "<![CDATA[" + value + "]]>";
        }

        sortedProperties
            .append("        <")
            .append(key)
            .append(">")
            .append(value)
            .append("</")
            .append(key)
            .append(">" + "\n");
        propertiesForPom.put(key, value);
      }
    }

    if (project.getPackaging().equals("pom") || project.hasParent()) {
      // store sorted properties in a thread local for later retrieval
      Map<String, String> properties = new LinkedHashMap<String, String>();
      if (propertiesContextHolder.get() != null) {
        properties = (LinkedHashMap) propertiesContextHolder.get();
      }

      for (String key : propertiesForPom.keySet()) {
        if (!properties.containsKey(key)) {
          properties.put(key, propertiesForPom.get(key));
        }
      }

      propertiesContextHolder.set(properties);
    }

    StringWriter writer = new StringWriter();

    try {
      project.writeOriginalModel(writer);

      File pom = new File("pom-fullsource.xml");

      if (pom.exists()) {
        pom.delete();
      }

      FileWriter fw = new FileWriter(pom);
      fw.write(writer.toString());
      fw.flush();
      fw.close();
    } catch (IOException ex) {
      getLog().error("Unable to create pom-fullsource.xml: " + ex.getMessage(), ex);
      throw new MojoFailureException(ex.getMessage());
    }

    log("Updated dependencies in pom.xml...");

    // I tried to use regex here, but couldn't get it to work - going with the old fashioned way
    // instead
    String pomXml = writer.toString();
    int startTag = pomXml.indexOf("\n  <dependencies>");

    String dependencyXml = pomXml.substring(startTag, pomXml.indexOf("</dependencies>", startTag));
    // change 2 spaces to 4
    dependencyXml = dependencyXml.replaceAll("  ", "    ");
    dependencyXml =
        "\n    <!-- Dependencies calculated by AppFuse when running full-source plugin -->"
            + dependencyXml;

    try {
      String packaging = project.getPackaging();
      String pathToPom = "pom.xml";
      if (project.hasParent()) {
        if (packaging.equals("jar")) {
          pathToPom = "core/" + pathToPom;
        } else if (packaging.equals("war")) {
          pathToPom = "web/" + pathToPom;
        }
      }

      String originalPom = FileUtils.readFileToString(new File(pathToPom), "UTF-8");
      // replace tabs with spaces (in case user has changed their pom.xml
      originalPom = originalPom.replace("\t", "    ");
      startTag = originalPom.indexOf("\n    <dependencies>");

      StringBuffer sb = new StringBuffer();
      sb.append(originalPom.substring(0, startTag));
      sb.append(dependencyXml);
      sb.append(originalPom.substring(originalPom.indexOf("</dependencies>", startTag)));

      String adjustedPom = sb.toString();

      // Calculate properties and add them to pom if not a modular project - otherwise properties
      // are added
      // near the end of this method from a threadlocal
      if (!project.getPackaging().equals("pom") && !project.hasParent()) {
        adjustedPom = addPropertiesToPom(adjustedPom, sortedProperties);
      }

      adjustedPom = adjustLineEndingsForOS(adjustedPom);

      FileUtils.writeStringToFile(
          new File(pathToPom), adjustedPom, "UTF-8"); // was pomWithProperties
    } catch (IOException ex) {
      getLog().error("Unable to write to pom.xml: " + ex.getMessage(), ex);
      throw new MojoFailureException(ex.getMessage());
    }

    boolean renamePackages = true;
    if (System.getProperty("renamePackages") != null) {
      renamePackages = Boolean.valueOf(System.getProperty("renamePackages"));
    }

    if (renamePackages && !project.getPackaging().equals("pom")) {
      log("Renaming packages to '" + project.getGroupId() + "'...");
      RenamePackages renamePackagesTool = new RenamePackages(project.getGroupId());
      if (project.hasParent()) {
        if (project.getPackaging().equals("jar")) {
          renamePackagesTool.setBaseDir("core/src");
        } else {
          renamePackagesTool.setBaseDir("web/src");
        }
      }

      renamePackagesTool.execute();
    }

    // when performing full-source on a modular project, add the properties to the root pom.xml at
    // the end
    if (project.getPackaging().equals("war") && project.hasParent()) {
      // store sorted properties in a thread local for later retrieval
      Map properties = propertiesContextHolder.get();
      // alphabetize the properties by key
      Set<String> propertiesToAdd = new TreeSet<String>(properties.keySet());

      StringBuffer calculatedProperties = new StringBuffer();

      for (String key : propertiesToAdd) {
        // don't add property if it already exists in project
        Set<Object> keysInProject = project.getParent().getOriginalModel().getProperties().keySet();
        if (!keysInProject.contains(key)) {
          String value = getAppFuseProperties().getProperty(key);

          if (value.contains("&amp;")) {
            value = "<![CDATA[" + value + "]]>";
          }

          calculatedProperties.append("        <");
          calculatedProperties.append(key);
          calculatedProperties.append(">");
          calculatedProperties.append(value);
          calculatedProperties.append("</");
          calculatedProperties.append(key);
          calculatedProperties.append(">");
          calculatedProperties.append("\n");
        }
      }

      try {
        String originalPom = FileUtils.readFileToString(new File("pom.xml"), "UTF-8");

        // Move modules to build section.
        originalPom = originalPom.replaceAll("  <modules>", "");
        // Because I hate f*****g regex.
        originalPom = originalPom.replaceAll("    <module>.*?</module>", "");
        originalPom = originalPom.replaceAll("  </modules>", "");

        originalPom =
            originalPom.replace(
                "<repositories>",
                "<modules>\n"
                    + "        <module>core</module>\n"
                    + "        <module>web</module>\n"
                    + "    </modules>\n\n    <repositories>");

        String pomWithProperties = addPropertiesToPom(originalPom, calculatedProperties);

        FileUtils.writeStringToFile(new File("pom.xml"), pomWithProperties, "UTF-8");
      } catch (IOException ex) {
        getLog().error("Unable to read root pom.xml: " + ex.getMessage(), ex);
        throw new MojoFailureException(ex.getMessage());
      }
    }

    // cleanup so user isn't aware that files were created
    File pom = new File("pom-fullsource.xml");

    if (pom.exists()) {
      pom.delete();
    }
  }

  private static String addPropertiesToPom(
      String existingPomXmlAsString, StringBuffer sortedProperties) {
    String adjustedPom = existingPomXmlAsString;

    // add new properties
    adjustedPom =
        adjustedPom.replace(
            "<jdbc.password/>",
            "<jdbc.password/>"
                + LINE_SEP
                + LINE_SEP
                + "        <!-- Properties calculated by AppFuse when running full-source plugin -->\n"
                + sortedProperties);

    // also look for empty jdbc.password tag since the archetype plugin sometimes expands empty
    // elements
    adjustedPom =
        adjustedPom.replace(
            "<jdbc.password></jdbc.password>",
            "<jdbc.password/>"
                + LINE_SEP
                + LINE_SEP
                + "        <!-- Properties calculated by AppFuse when running full-source plugin -->\n"
                + sortedProperties);

    adjustedPom =
        adjustedPom.replaceAll(
            "<amp.fullSource>false</amp.fullSource>", "<amp.fullSource>true</amp.fullSource>");

    return adjustLineEndingsForOS(adjustedPom);
  }

  private static String adjustLineEndingsForOS(String adjustedPom) {
    String os = System.getProperty("os.name");

    if (os.startsWith("Linux") || os.startsWith("Mac")) {
      // remove the \r returns
      adjustedPom = adjustedPom.replaceAll("\r", "");
    } else if (os.startsWith("Windows")) {
      // use windows line endings
      adjustedPom = adjustedPom.replaceAll(">\n", ">\r\n");
    }

    return adjustedPom;
  }

  private Properties getAppFuseProperties() {
    // should only happen when executing full-source on modular modules (b/c they don't export
    // root).
    if (appfuseProperties == null) {
      File pom = new File("target/appfuse-root/pom.xml");
      appfuseProperties = createProjectFromPom(pom).getOriginalModel().getProperties();
    }
    return appfuseProperties;
  }

  private String getFilePath(String s) {
    s = s.replace("/", FILE_SEP);
    // log("returning: " + s);
    return s;
  }

  private void export(String url, String destinationDirectory) throws MojoExecutionException {
    SubversionUtils svn = new SubversionUtils(trunk + tag + url, destinationDirectory);

    try {
      svn.export();
    } catch (SVNException e) {
      SVNErrorMessage err = e.getErrorMessage();

      /*
       * Display all tree of error messages.
       * Utility method SVNErrorMessage.getFullMessage() may be used instead of the loop.
       */
      while (err != null) {
        getLog().error(err.getErrorCode().getCode() + " : " + err.getMessage());
        err = err.getChildErrorMessage();
      }

      throw new MojoExecutionException(e.getMessage());
    }
  }

  private void log(String msg) {
    getLog().info("[AppFuse] " + msg);
  }

  private List<Dependency> addModuleDependencies(
      List<Dependency> dependencies, String moduleName, String moduleLocation) {
    log("Adding dependencies from " + moduleName + " module...");

    // Read dependencies from module's pom.xml
    URL pomLocation = null;
    File newDir = new File("target", "appfuse-" + moduleName);

    if (!newDir.exists()) {
      newDir.mkdirs();
    }

    File pom = new File("target/appfuse-" + moduleName + "/pom.xml");

    try {
      // replace github.com with raw.github.com and trunk with master
      trunk = trunk.replace("https://github.com", "https://raw.github.com");
      tag = tag.replace("trunk", "master");
      pomLocation = new URL(trunk + tag + moduleLocation + "/pom.xml");
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }

    Get get = (Get) AntUtils.createProject().createTask("get");
    get.setSrc(pomLocation);
    get.setDest(pom);
    get.execute();

    MavenProject p = createProjectFromPom(pom);

    List moduleDependencies = p.getOriginalModel().getDependencies();

    // set the properties for appfuse if root module
    if (moduleName.equalsIgnoreCase("root")) {
      appfuseProperties = p.getOriginalModel().getProperties();
    }

    // create a list of artifactIds to check for duplicates (there's no equals() on Dependency)
    Set<String> artifactIds = new LinkedHashSet<String>();

    for (Dependency dep : dependencies) {
      artifactIds.add(dep.getArtifactId());
    }

    // add all non-appfuse dependencies
    for (Object moduleDependency : moduleDependencies) {
      Dependency dep = (Dependency) moduleDependency;

      if (dep.getGroupId().equals("javax.servlet")
          && dep.getArtifactId().equals("jsp-api")
          && "jsf".equals(project.getProperties().getProperty("web.framework"))) {
        // skip adding dependency for old group id of jsp-api
        continue;
      }

      if (!artifactIds.contains(dep.getArtifactId()) && !dep.getArtifactId().contains("appfuse")) {
        dependencies.add(dep);
      }
    }

    return dependencies;
  }

  private MavenProject createProjectFromPom(File pom) {
    MavenEmbedder maven = new MavenEmbedder();
    maven.setOffline(true);
    maven.setClassLoader(Thread.currentThread().getContextClassLoader());
    maven.setLogger(new MavenEmbedderConsoleLogger());

    MavenProject p = null;

    try {
      maven.setAlignWithUserInstallation(true);
      maven.start();
      p = maven.readProjectWithDependencies(pom);
      maven.stop();
    } catch (Exception e) {
      e.printStackTrace();
    }

    return p;
  }

  /**
   * This method will create an ANT based LoadFile task based on an infile and a property name. The
   * property will be loaded with the infile for use later by the Replace task.
   *
   * @param inFile The file to process
   * @param propName the name to assign it to
   * @return The ANT LoadFile task that loads a property with a file
   */
  protected LoadFile createLoadFileTask(String inFile, String propName) {
    LoadFile loadFileTask = (LoadFile) antProject.createTask("loadfile");
    loadFileTask.init();
    loadFileTask.setProperty(propName);
    loadFileTask.setSrcFile(new File(inFile));

    return loadFileTask;
  }

  /**
   * This method will movie files from the source directory to the destination directory based on
   * the pattern.
   *
   * @param inSourceDirectory The source directory to copy from.
   * @param inDestinationDirectory The destination directory to copy to.
   * @param inPattern The file pattern to match to locate files to copy.
   */
  protected void moveFiles(
      final String inSourceDirectory, final String inDestinationDirectory, final String inPattern) {
    Move moveTask = (Move) antProject.createTask("move");

    FileSet fileSet = AntUtils.createFileset(inSourceDirectory, inPattern, new ArrayList());
    moveTask.setTodir(new File(inDestinationDirectory));
    moveTask.addFileset(fileSet);
    moveTask.execute();
  }
}