/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed 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 com.google.gwt.user.tools;

import com.google.gwt.dev.About;
import com.google.gwt.dev.ArgProcessorBase;
import com.google.gwt.dev.Compiler;
import com.google.gwt.dev.DevMode;
import com.google.gwt.dev.GwtVersion;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.collect.HashSet;
import com.google.gwt.user.tools.util.ArgHandlerIgnore;
import com.google.gwt.user.tools.util.ArgHandlerOverwrite;
import com.google.gwt.user.tools.util.CreatorUtilities;
import com.google.gwt.util.tools.ArgHandlerExtra;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerOutDir;
import com.google.gwt.util.tools.ArgHandlerString;
import com.google.gwt.util.tools.Utility;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Creates a GWT application skeleton.
 */
public final class WebAppCreator {

  class ArgProcessor extends ArgProcessorBase {

    private final class ArgHandlerOutDirExtension extends ArgHandlerOutDir {
      @Override
      public void setDir(File dir) {
        outDir = dir;
      }
    }

    public ArgProcessor() {
      registerHandler(new ArgHandlerOverwriteExtension());
      registerHandler(new ArgHandlerIgnoreExtension());
      registerHandler(new ArgHandlerTemplates());
      registerHandler(new ArgHandlerModuleName());
      registerHandler(new ArgHandlerOutDirExtension());
      registerHandler(new ArgHandlerCreateEclipseProject());
      registerHandler(new ArgHandlerCreateEclipseProjectOnly());
      registerHandler(new ArgHandlerJUnitPath());
      registerHandler(new ArgHandlerCreateMavenProject());
      registerHandler(new ArgHandlerCreateAntFile());
    }

    @Override
    protected String getName() {
      return WebAppCreator.class.getName();
    }
  }

  private final class ArgHandlerIgnoreExtension extends ArgHandlerIgnore {

    @Override
    public boolean setFlag(boolean value) {
      if (value && overwrite) {
        System.err.println("-ignore cannot be used with -overwrite");
        return false;
      }
      ignore = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return ignore;
    }
  }

  private final class ArgHandlerJUnitPath extends ArgHandlerString {

    @Override
    public String[] getDefaultArgs() {
      return null;
    }

    @Override
    public String getPurpose() {
      return "Specifies the path to your junit.jar (optional)";
    }

    @Override
    public String getTag() {
      return "-junit";
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"pathToJUnitJar"};
    }

    @Override
    public boolean isRequired() {
      return false;
    }

    @Override
    public boolean setString(String str) {
      File f = new File(str);
      if (!f.exists() || !f.isFile()) {
        System.err.println("File not found: " + str);
        return false;
      }
      junitPath = str;
      return true;
    }
  }

  private final class ArgHandlerCreateMavenProject extends ArgHandlerFlag {

    @Override
    public String getPurposeSnippet() {
      return "DEPRECATED: Create a maven2 project structure and pom file (default disabled). "
          + "Equivalent to specifying 'maven' in the list of templates.";
    }

    @Override
    public String getLabel() {
      return "maven";
    }

    @Override
    public boolean setFlag(boolean value) {
      if (value && onlyEclipse) {
        System.err.println("-maven and -XonlyEclipse cannot be used at the same time.");
        return false;
      }
      if (value) {
        templates.add("maven");
      } else {
        templates.remove("maven");
      }
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return templates.contains("maven");
    }
  }

  private final class ArgHandlerModuleName extends ArgHandlerExtra {
    @Override
    public boolean addExtraArg(String arg) {
      if (moduleName != null) {
        System.err.println("Too many arguments.");
        return false;
      }

      if (!CreatorUtilities.isValidModuleName(arg)) {
        System.err.println("'"
            + arg
            + "' does not appear to be a valid fully-qualified Java class name.");
        return false;
      }

      moduleName = arg;
      return true;
    }

    @Override
    public String getPurpose() {
      return "The name of the module to create (e.g. com.example.myapp.MyApp)";
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"moduleName"};
    }

    @Override
    public boolean isRequired() {
      return true;
    }
  }

  private final class ArgHandlerCreateAntFile extends ArgHandlerFlag {

    @Override
    public String getPurposeSnippet() {
      return "DEPRECATED: Create an ant configuration file. "
          + "Equivalent to specifying 'ant' in the list of templates.";
    }

    @Override
    public String getLabel() {
      return "ant";
    }

    @Override
    public boolean setFlag(final boolean value) {
      argProcessingToDos.add(new Procrastinator() {
        @Override
        public void stopProcratinating() {
          if (!value) {
            if (templates.contains("maven")) {
              System.err.println("-maven and -noant are redundant. Continuing.");
            }
            if (templates.contains("ant")) {
              System.err.println("Removing ant template from generated output.");
              templates.remove("ant");
            }
          } else {
            if (!templates.contains("ant")) {
              System.err.println("Adding ant template to generated output.");
              templates.add("ant");
            }
          }
        }
      });
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return templates.contains("ant");
    }
  }

  private final class ArgHandlerCreateEclipseProject extends ArgHandlerFlag {

    public ArgHandlerCreateEclipseProject() {
      addTagValue("-XnoEclipse", false);
    }

    @Override
    public String getPurposeSnippet() {
      return "DEPRECATED: Generate eclipse files. Equivalent to specifying "
          + "'eclipse' in the list of templates.";
    }

    @Override
    public String getLabel() {
      return "createEclipseProject";
    }

    @Override
    public boolean isUndocumented() {
      return true;
    }

    @Override
    public boolean setFlag(boolean value) {
      if (!value) {
        if (onlyEclipse) {
          System.err.println("-XonlyEclipse and -XnoEclipse cannot be used at the same time.");
          return false;
        }
        if (!templates.contains("maven")) {
          System.err.println("-maven and -XnoEclipse are redundant. Continuing.");
        }
        noEclipse = true;
        argProcessingToDos.add(new Procrastinator() {
          @Override
          public void stopProcratinating() {
            if (noEclipse && templates.contains("eclipse")) {
              System.err.println("Removing eclipse template from generated output.");
              templates.remove("eclipse");
            }
          }
        });
      } else {
        noEclipse = false;
      }
      return true;
    }

    @Override
    public boolean isExperimental() {
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return !noEclipse;
    }
  }

  private final class ArgHandlerCreateEclipseProjectOnly extends ArgHandlerFlag {

    public ArgHandlerCreateEclipseProjectOnly() {
      addTagValue("-XonlyEclipse", true);
    }

    @Override
    public String getPurposeSnippet() {
      return "DEPRECATED: Generate only eclipse files. "
          + "Equivalent to only specifying 'eclipse' in the list of templates.";
    }

    @Override
    public String getLabel() {
      return "createEclipseProjectOnly";
    }

    @Override
    public boolean isUndocumented() {
      return true;
    }

    @Override
    public boolean setFlag(boolean value) {
      if (value) {
        if (noEclipse) {
          System.err.println("-XonlyEclipse and -XnoEclipse cannot be used at the same time.");
          return false;
        }
        if (templates.contains("maven")) {
          System.err.println("-maven and -XonlyEclipse cannot be used at the same time.");
          return false;
        }
        onlyEclipse = true;
        argProcessingToDos.add(new Procrastinator() {
          @Override
          public void stopProcratinating() {
            if (onlyEclipse) {
              System.err.println("Removing all templates but 'eclipse' from generated output.");
              templates.clear();
              templates.add("eclipse");
            }
          }
        });
      } else {
        onlyEclipse = false;
      }
      return true;
    }
    
    @Override
    public boolean isExperimental() {
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return onlyEclipse;
    }
  }

  private final class ArgHandlerOverwriteExtension extends ArgHandlerOverwrite {

    @Override
    public boolean setFlag(boolean value) {
      if (value && ignore) {
        System.err.println("-overwrite cannot be used with -ignore");
        return false;
      }
      overwrite = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return overwrite;
    }
  }

  private final class ArgHandlerTemplates extends ArgHandlerString {

    @Override
    public String[] getDefaultArgs() {
      return new String[] {getTag(), "sample, ant, eclipse, readme"};
    }

    @Override
    public String getPurpose() {
      return "Specifies the template(s) to use (comma separeted)."
          + " Defaults to 'sample,ant,eclipse,readme'";
    }

    @Override
    public String getTag() {
      return "-templates";
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"template1,template2,..."};
    }

    @Override
    public boolean isRequired() {
      return false;
    }

    @Override
    public boolean setString(String str) {
      String[] templateList = str.split(", *");
      for (String template : templateList) {
        URL url = getTemplateRoot(template);
        if (url == null) {
          System.err.println("Template not found: " + template);
          return false;
        }
        templates.add(template);
      }
      return true;
    }
  }

  private static final class FileCreator {
    private final File destDir;

    private final String destName;
    private final boolean isBinary;
    private final String sourceName;
    public FileCreator(File destDir, String destName, String sourceName, boolean isBinary) {
      this.destDir = destDir;
      this.sourceName = sourceName;
      this.destName = destName;
      this.isBinary = isBinary;
    }

    @Override
    public String toString() {
      return "FileCreator [destDir=" + destDir + ", destName=" + destName
          + ", sourceName=" + sourceName + ", isBinary=" + isBinary + "]";
    }
  }

  private abstract static class Procrastinator {
    public abstract void stopProcratinating();
  }

  public static void main(String[] args) {
    System.exit(doMain(args) ? 0 : 1);
  }

  protected static boolean doMain(String... args) {
    WebAppCreator creator = new WebAppCreator();
    ArgProcessor argProcessor = creator.new ArgProcessor();
    if (argProcessor.processArgs(args)) {
      return creator.run();
    }
    return false;
  }

  private static String getTemplateBasePath(String template) {
    return "/" + WebAppCreator.class.getPackage().getName().replace('.', '/') + "/templates/" 
        + template + "/";
  }

  private static URL getTemplateRoot(String template) {
    return WebAppCreator.class.getResource("templates/" + template);
  }

  private static String replaceFileName(Map<String, String> replacements, String name) {
    String replacedContents = name;
    Set<Entry<String, String>> entries = replacements.entrySet();
    for (Iterator<Entry<String, String>> iter = entries.iterator(); iter.hasNext();) {
      Entry<String, String> entry = iter.next();
      String replaceThis = entry.getKey();
      replaceThis = replaceThis.replaceAll("@(.*)", "_$1_");
      String withThis = entry.getValue();
      withThis = withThis.replaceAll("\\\\", "\\\\\\\\");
      withThis = withThis.replaceAll("\\$", "\\\\\\$");
      replacedContents = replacedContents.replaceAll(replaceThis, withThis);
    }
    return replacedContents;
  }
  private ArrayList<Procrastinator> argProcessingToDos = new ArrayList<Procrastinator>();
  private boolean ignore = false;
  private String junitPath = null;
  private String moduleName;
  private boolean noEclipse;
  private boolean onlyEclipse;
  private File outDir;
  private boolean overwrite = false;

  private HashSet<String> templates = new HashSet<String>();

  public List<FileCreator> getFiles(Map<String, String> replacements)
      throws IOException, WebAppCreatorException {
    List<FileCreator> files = new ArrayList<FileCreator>();

    Utility.getDirectory(outDir.getPath(), true);

    for (String template : templates) {
      URL templateUrl = getTemplateRoot(template);
      if ("jar".equals(templateUrl.getProtocol())) {
        files.addAll(getTemplateFilesFromZip(replacements, templateUrl, outDir));
      } else if ("file".equals(templateUrl.getProtocol())) {
        File templateRoot = new File(templateUrl.getPath());
        files.addAll(getTemplateFiles(replacements, templateRoot, outDir,
            getTemplateBasePath(template)));
      } else {
        throw new WebAppCreatorException("Cannot handle template '" + template + "' protocol: " 
            + templateUrl.getProtocol());
      }
    }
    
    return files;
  }

  public Map<String, String> getReplacements(String installPath, String theModuleName) {
    // GWT libraries
    String gwtUserPath = installPath + '/' + "gwt-user.jar";
    String gwtDevPath = installPath + '/' + "gwt-dev.jar";
    String gwtCodeServerPath = installPath + '/' + "gwt-codeserver.jar";
    String gwtValidationPath = installPath + '/' + "validation-api-1.0.0.GA.jar";
    String gwtValidationSourcesPath = installPath + '/' + "validation-api-1.0.0.GA-sources.jar";

    // Generate a DTD reference.
    String gwtModuleDtd = "\n<!-- Custom-built GWT. You probably want to uncomment the DOCTYPE "
        + "and point it to your GWT checkout"
        + "\n<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit "
        + About.getGwtVersionNum()
        + "//EN\" \"file:///path/to/gwt/checkout/distro-source/core/src/gwt-module.dtd\">"
        + "\n-->";
    GwtVersion gwtVersion = About.getGwtVersionObject();
    if (!gwtVersion.isNoNagVersion() && !gwtVersion.equals(new GwtVersion(null))) {
      // TODO: put gwt-module.dtd online at gwtproject.org
      gwtModuleDtd = "\n<!--"
          + "\n  When updating your version of GWT, you should also update this DTD reference,"
          + "\n  so that your app can take advantage of the latest GWT module capabilities."
          + "\n-->"
          + "\n<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit "
          + About.getGwtVersionNum() + "//EN\""
          + "\n  \"file:///" + installPath + "/gwt-module.dtd\">";
    }

    // Compute module package and name.
    int pos = theModuleName.lastIndexOf('.');
    String modulePackageName = theModuleName.substring(0, pos);
    String moduleShortName = theModuleName.substring(pos + 1);

    // Create a map of replacements
    Map<String, String> replacements = new HashMap<String, String>();

    // Compute module name and directories
    String srcFolder = templates.contains("maven") ? "src/main/java" : "src";
    String testFolder = templates.contains("maven") ? "src/test/java" : "test";
    String warFolder = templates.contains("maven") ? "src/main/webapp" : "war";

    {
      // pro-actively let ant user know that this script can also create tests.
      if (junitPath == null) {
        System.err.println("Not creating tests because -junit argument was not specified.\n");
      }

      String testTargetsBegin = "";
      String testTargetsEnd = "";
      String junitJarPath = junitPath;
      String eclipseTestDir = "";
      if (junitPath != null) {
        eclipseTestDir = "\n   <classpathentry kind=\"src\" path=\""
            + testFolder + "\"/>";
      }
      if (junitPath == null) {
        testTargetsBegin = "\n<!--"
            + "\n"
            + "Test targets suppressed because -junit argument was not specified when running"
            + " webAppCreator.\n";
        testTargetsEnd = "-->\n";
        junitJarPath = "path_to_the_junit_jar";
      }
      replacements.put("@testTargetsBegin", testTargetsBegin);
      replacements.put("@testTargetsEnd", testTargetsEnd);
      replacements.put("@junitJar", junitJarPath);
      replacements.put("@eclipseTestDir", eclipseTestDir);
    }

    replacements.put("@srcFolder", srcFolder);
    replacements.put("@testFolder", testFolder);
    replacements.put("@warFolder", warFolder);

    replacements.put("@moduleShortName", moduleShortName);
    replacements.put("@modulePackageName", modulePackageName);
    replacements.put("@moduleFolder", modulePackageName.replace('.', '/'));
    replacements.put("@moduleName", theModuleName);
    replacements.put("@clientPackage", modulePackageName + ".client");
    replacements.put("@serverPackage", modulePackageName + ".server");
    replacements.put("@sharedPackage", modulePackageName + ".shared");
    replacements.put("@gwtSdk", installPath);
    replacements.put("@gwtUserPath", gwtUserPath);
    replacements.put("@gwtDevPath", gwtDevPath);
    replacements.put("@gwtCodeServerPath", gwtCodeServerPath);
    replacements.put("@gwtValidationPath", gwtValidationPath);
    replacements.put("@gwtValidationSourcesPath", gwtValidationSourcesPath);
    replacements.put("@gwtVersion", About.getGwtVersionNum());
    replacements.put("@gwtModuleDtd", gwtModuleDtd);
    replacements.put("@shellClass", DevMode.class.getName());
    replacements.put("@compileClass", Compiler.class.getName());
    replacements.put("@startupUrl", moduleShortName + ".html");
    replacements.put("@renameTo", moduleShortName.toLowerCase());
    replacements.put("@moduleNameJUnit", theModuleName + "JUnit");

    // Add command to copy gwt-servlet-deps.jar into libs, unless this is a
    // maven project. Maven projects should include libs as maven dependencies.
    String copyServletDeps = "";
    copyServletDeps = "<copy todir=\"" + warFolder + "/WEB-INF/lib\" "
        + "file=\"${gwt.sdk}/gwt-servlet-deps.jar\" />";
    replacements.put("@copyServletDeps", copyServletDeps);

    // Collect the list of server libs to include on the eclipse classpath.
    File libDirectory = new File(outDir + "/" + warFolder + "/WEB-INF/lib");
    StringBuilder serverLibs = new StringBuilder();
    if (libDirectory.exists()) {
      for (File file : libDirectory.listFiles()) {
        if (file.getName().toLowerCase().endsWith(".jar")) {
          serverLibs.append("   <classpathentry kind=\"lib\" path=\"" + warFolder + "/WEB-INF/lib/");
          serverLibs.append(file.getName());
          serverLibs.append("\"/>\n");
        }
      }
    }
    replacements.put("@serverClasspathLibs", serverLibs.toString());

    String antEclipseRule = "";
    if (!templates.contains("eclipse")) {
      /*
       * Generate a rule into the build file that allows for the generation of
       * an eclipse project later on. This is primarily for distro samples. This
       * is a quick and dirty way to inject a build rule, but it works.
       */
      antEclipseRule = "\n\n"
          + "  <target name=\"eclipse.generate\" depends=\"libs\" description"
          + "=\"Generate eclipse project\">\n"
          + "    <java failonerror=\"true\" fork=\"true\" classname=\""
          + this.getClass().getName() + "\">\n" + "      <classpath>\n"
          + "        <path refid=\"project.class.path\"/>\n"
          + "      </classpath>\n" + "      <arg value=\"-XonlyEclipse\"/>\n"
          + "      <arg value=\"-ignore\"/>\n" + "      <arg value=\""
          + theModuleName + "\"/>\n" + "    </java>\n" + "  </target>";
    } else {
      antEclipseRule = "";
    }
    replacements.put("@antEclipseRule", antEclipseRule);
    return replacements;
  }

  /**
   * Create the sample app.
   * 
   * @throws IOException if any disk write fails
   * @throws WebAppCreatorException if any tag expansion of template processing fails
   * @deprecated as of GWT 2.1, replaced by {@link #doRun(String)}
   */
  @Deprecated
  protected void doRun() throws IOException, WebAppCreatorException {
    doRun(Utility.getInstallPath());
  }

  /**
   * Create the sample app.
   * 
   * @param installPath directory containing GWT libraries
   * @throws IOException if any disk write fails
   * @throws WebAppCreatorException  if any tag expansion of template processing fails
   */
  protected void doRun(String installPath) throws IOException, WebAppCreatorException {
    for (Procrastinator toDo : argProcessingToDos) {
      toDo.stopProcratinating();
    }

    // Maven projects do not need Ant nor Eclipse files
    if (templates.contains("maven")) {
      junitPath = "junit-provided-by-maven";

      if (templates.contains("eclipse")) {
        System.err.println("'maven' template is being generated removing 'eclipse'"
            + " template from generated output.");
        templates.remove("eclipse");            
      }
      if (templates.contains("ant")) {
        System.err.println("'maven' template is being generated removing 'ant'"
            + " template from generated output.");
        templates.remove("ant");
      }
    }

    // Eagerly look for test templates
    if (junitPath != null) {
      ArrayList<String> testTemplates = new ArrayList<String>();
      for (String template : templates) {
        String testTemplateName = "_" + template + "-test";
        if (getTemplateRoot(testTemplateName) != null) {
          testTemplates.add(testTemplateName);
        }
      }
      templates.addAll(testTemplates);
    }

    System.out.println("Generating from templates: " + templates);

    // Generate string replacements 
    Map<String, String> replacements = getReplacements(installPath, moduleName);

    // Create a list with the files to create
    List<FileCreator> files = getFiles(replacements);

    // copy source files, replacing the content as needed
    for (FileCreator fileCreator : files) {
      URL url = WebAppCreator.class.getResource(fileCreator.sourceName);
      if (url == null) {
        throw new WebAppCreatorException("Could not find " + fileCreator.sourceName);
      }
      File file = Utility.createNormalFile(fileCreator.destDir,
          fileCreator.destName, overwrite, ignore);
      if (file == null) {
        continue;
      }
      if (fileCreator.isBinary) {
        byte[] data = Util.readURLAsBytes(url);
        Utility.writeTemplateBinaryFile(file, data);
      } else {
        String data = Util.readURLAsString(url);
        Utility.writeTemplateFile(file, data, replacements);
      }
    }
  }

  protected boolean run() {
    try {
      doRun(Utility.getInstallPath());
      return true;
    } catch (IOException e) {
      System.err.println(e.getClass().getName() + ": " + e.getMessage());
      return false;
    } catch (WebAppCreatorException e) {
      System.err.println(e.getClass().getName() + ": " + e.getMessage());
      return false;
    }
  }

  private Collection<? extends FileCreator> getTemplateFiles(
      Map<String, String> replacements, File srcDirectory, File destDirectory,
      String templateClassRoot) throws IOException {
    List<FileCreator> files = new ArrayList<FileCreator>();
    
    File[] filesInDir = srcDirectory.listFiles();

    for (File srcFile : filesInDir) {
      String replacedName = replaceFileName(replacements, srcFile.getName());
      
      if (srcFile.isDirectory()) {
        File newDirectory = Utility.getDirectory(destDirectory, replacedName, true);
        files.addAll(getTemplateFiles(replacements, srcFile, newDirectory, templateClassRoot
            + srcFile.getName() + "/"));
      } else if (srcFile.getName().endsWith("src")) {
        String srcFilename = templateClassRoot + srcFile.getName();
        String destName = replacedName.substring(0, replacedName.length() - 3);
        files.add(new FileCreator(destDirectory, destName, srcFilename, false));
      } else if (srcFile.getName().endsWith("bin")) {
        String srcFilename = templateClassRoot + srcFile.getName();
        String destName = replacedName.substring(0, replacedName.length() - 3);
        files.add(new FileCreator(destDirectory, destName, srcFilename, true));
      } // else ... ignore everything not a directory, "*src" nor "*bin"
    }
    
    return files;
  }

  private Collection<? extends FileCreator> getTemplateFilesFromZip(
      Map<String, String> replacements, URL zipUrl, File destDirectory)
      throws WebAppCreatorException, IOException {
    String zipPath = zipUrl.getFile();
    int separator = zipPath.indexOf('!');

    if (separator == -1) {
      throw new WebAppCreatorException("Error opening template zip file. '!' not found in "
          + zipUrl);
    }

    String zipFilename = zipPath.substring(0, separator);
    String templateDirName = zipPath.substring(separator + 2);
    ZipFile zipFile;

    try {
      zipFile = new ZipFile(new File(new URI(zipFilename)));
    } catch (URISyntaxException e) {
      throw new WebAppCreatorException("Could not open Zip file. Malformed URI", e);
    }

    Enumeration<? extends ZipEntry> allZipEntries = zipFile.entries();

    ArrayList<FileCreator> templateEntries = new ArrayList<FileCreator>(); 

    while (allZipEntries.hasMoreElements()) {
      ZipEntry entry = allZipEntries.nextElement();
      String fullName = entry.getName();
      if (fullName.startsWith(templateDirName + "/")) {
        String relativeName = fullName.substring(templateDirName.length());
        String replacedName = replaceFileName(replacements, relativeName);
        if (entry.isDirectory()) {
          Utility.getDirectory(destDirectory, replacedName, true);
        } else if (fullName.endsWith("src")) {
          // remove the src suffix 
          String destName = replacedName.substring(0, replacedName.length() - 3);
          templateEntries.add(new FileCreator(destDirectory, destName, "/" + fullName, false));
        } else if (fullName.endsWith("bin")) {
          String destName = replacedName.substring(0, replacedName.length() - 3);
          templateEntries.add(new FileCreator(destDirectory, destName, "/" + fullName, true));
        }
      } // else ... ignore everything not a directory, "*src" nor "*bin"
    }

    return templateEntries;
  }

}
