/*
 * 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<!-- Using DTD from SVN 'trunk'. You probably want to change this"
        + " to a specific, release tagged, DTD -->"
        + "\n<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit "
        + About.getGwtVersionNum()
        + "//EN\" \"http://google-web-toolkit.googlecode.com/svn/trunk/"
        + "/distro-source/core/src/gwt-module.dtd\">";
    GwtVersion gwtVersion = About.getGwtVersionObject();
    if (!gwtVersion.isNoNagVersion() && !gwtVersion.equals(new GwtVersion(null))) {
      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  \"http://google-web-toolkit.googlecode.com/svn/tags/"
          + About.getGwtVersionNum()
          + "/distro-source/core/src/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=\"war/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;
  }

}
