Updated project creator for new WAR world
a) Added extra params for the new options
b) Updated the starter app to include a server side component
c) Removed the shell scripts and moved their work to ant build file
d) Removed projectCreator. Moved its functionality to applicationCreator
e) Cleaned up the code for ApplicationCreator

Patch by: amitmanjhi
Review by: jat (desk review)



git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4004 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/tools/.classpathsrc b/user/src/com/google/gwt/user/tools/.classpathsrc
index 336a085..19b3e77 100644
--- a/user/src/com/google/gwt/user/tools/.classpathsrc
+++ b/user/src/com/google/gwt/user/tools/.classpathsrc
@@ -5,6 +5,6 @@
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry kind="lib" path="@gwtUserPath"/>
    <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
-   <classpathentry kind="output" path="bin"/>
+   <classpathentry kind="output" path="war/WEB-INF/classes"/>
 @eclipseClassPathEntries
 </classpath>
diff --git a/user/src/com/google/gwt/user/tools/App.launchsrc b/user/src/com/google/gwt/user/tools/App.launchsrc
index b35bd08..1f9e95c 100644
--- a/user/src/com/google/gwt/user/tools/App.launchsrc
+++ b/user/src/com/google/gwt/user/tools/App.launchsrc
@@ -10,7 +10,8 @@
 @eclipseExtraLaunchPaths
 </listAttribute>
 <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="@vmargs -Xmx256M"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out www @startupUrl"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out
+  war -startupUrl @startupUrl @moduleName"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="@projectName"/>
 <booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
 </launchConfiguration>
diff --git a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc
index eae6bd1..f2cd244 100644
--- a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc
+++ b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc
@@ -1,6 +1,10 @@
 package @clientPackage;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.rpc.ServiceDefTarget;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
@@ -37,7 +41,6 @@
 
     // Create the dialog box
     final DialogBox dialogBox = new DialogBox();
-    dialogBox.setText("Welcome to GWT!");
     dialogBox.setAnimationEnabled(true);
     Button closeButton = new Button("close");
     VerticalPanel dialogVPanel = new VerticalPanel();
@@ -50,14 +53,36 @@
         dialogBox.hide();
       }
     });
-
+    
     // Set the contents of the Widget
     dialogBox.setWidget(dialogVPanel);
+ 
+    final EchoServiceAsync echoService = GWT.create(EchoService.class);
+    ServiceDefTarget target = (ServiceDefTarget) echoService;
+
+    // Use a module-relative URLs to ensure that this client code can find
+    // its way home, even when the URL changes (as might happen when you
+    // deploy this as a webapp under an external servlet container).
+    String moduleRelativeURL = GWT.getModuleBaseURL() + "echo";
+    target.setServiceEntryPoint(moduleRelativeURL);
+    
+    final String textToServer = "Hello GWT World!";
     
     button.addClickListener(new ClickListener() {
       public void onClick(Widget sender) {
+        final String dialogBoxText = "Sending to the server: " + textToServer;
+        dialogBox.setText(dialogBoxText);
         dialogBox.center();
         dialogBox.show();
+        echoService.echo(textToServer, new AsyncCallback<String>() {
+          public void onFailure(Throwable caught) {
+            Window.alert("Rpc failure");
+          }
+
+          public void onSuccess(String result) {
+            dialogBox.setText(dialogBoxText + "\n " + result);
+          }
+        });
       }
     });
   }
diff --git a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
index 5a23afa..d105aeb 100644
--- a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
+++ b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
@@ -19,7 +19,7 @@
     <!-- If you add any GWT meta tags, they must   -->
     <!-- be added before this line.                -->
     <!--                                           -->
-    <script type="text/javascript" language="javascript" src="@moduleName.nocache.js"></script>
+    <script type="text/javascript" language="javascript" src="@deployDir/@newModuleName.nocache.js"></script>
   </head>
 
   <!--                                           -->
diff --git a/user/src/com/google/gwt/user/tools/ApplicationCreator.java b/user/src/com/google/gwt/user/tools/ApplicationCreator.java
index 99948f9..9126cd5 100644
--- a/user/src/com/google/gwt/user/tools/ApplicationCreator.java
+++ b/user/src/com/google/gwt/user/tools/ApplicationCreator.java
@@ -21,6 +21,7 @@
 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.ArgHandlerDir;
 import com.google.gwt.util.tools.ArgHandlerExtra;
 import com.google.gwt.util.tools.ArgHandlerOutDir;
 import com.google.gwt.util.tools.ArgHandlerString;
@@ -28,6 +29,7 @@
 import com.google.gwt.util.tools.Utility;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -144,6 +146,18 @@
     }
   }
 
+  static class FileCreator {
+    private final File dir;
+    private final String sourceName;
+    private final String className;
+
+    FileCreator(File dir, String sourceName, String className) {
+      this.dir = dir;
+      this.sourceName = sourceName;
+      this.className = className;
+    }
+  }
+
   private static final String PACKAGE_PATH;
 
   static {
@@ -172,11 +186,11 @@
    * @throws IOException
    */
   static void createApplication(String fullClassName, File outDir,
-      String eclipse, boolean overwrite, boolean ignore)
-      throws IOException {
-    createApplication(fullClassName, outDir, eclipse, overwrite, ignore, null, null);
+      String eclipse, boolean overwrite, boolean ignore) throws IOException {
+    createApplication(fullClassName, outDir, eclipse, overwrite, ignore, null,
+        null);
   }
-  
+
   /**
    * @param fullClassName Name of the fully-qualified Java class to create as an
    *          Application.
@@ -193,11 +207,35 @@
       String eclipse, boolean overwrite, boolean ignore,
       List<String> extraClassPaths, List<String> extraModules)
       throws IOException {
+    createApplication(fullClassName, outDir, eclipse, overwrite, ignore,
+        extraClassPaths, extraModules, null, null);
+  }
+
+  /**
+   * @param fullClassName Name of the fully-qualified Java class to create as an
+   *          Application.
+   * @param outDir Where to put the output files
+   * @param eclipse The name of a project to attach a .launch config to
+   * @param overwrite Overwrite an existing files if they exist.
+   * @param ignore Ignore existing files if they exist.
+   * @param extraClassPaths A list of paths to append to the class path for
+   *          launch configs.
+   * @param extraModules A list of GWT modules to add 'inherits' tags for.
+   * @param newModuleName The new module name
+   * @param deployDir The deploy directory
+   * @throws IOException
+   */
+  static void createApplication(String fullClassName, File outDir,
+      String eclipse, boolean overwrite, boolean ignore,
+      List<String> extraClassPaths, List<String> extraModules,
+      String newModuleName, File deployDir) throws IOException {
 
     // Figure out the installation directory
+
     String installPath = Utility.getInstallPath();
     String gwtUserPath = installPath + '/' + "gwt-user.jar";
     String gwtDevPath = installPath + '/' + Utility.getDevJarName();
+    String gwtServletPath = installPath + '/' + "gwt-servlet.jar";
 
     // Validate the arguments for extra class path entries and modules.
     if (!CreatorUtilities.validatePathsAndModules(gwtUserPath, extraClassPaths,
@@ -236,19 +274,26 @@
     pos = clientPackageName.lastIndexOf('.');
     File basePackageDir;
     String moduleName;
+    String serverPackageName = null;
     File javaDir = Utility.getDirectory(outDir, "src", true);
+    Utility.getDirectory(outDir, "test", true);
+    File warDir = Utility.getDirectory(outDir, "war", true);
+    File webInfDir = Utility.getDirectory(warDir, "WEB-INF", true);
     if (pos >= 0) {
       String basePackage = clientPackageName.substring(0, pos);
       moduleName = basePackage + "." + className;
+      serverPackageName = basePackage + ".server";
       basePackage = basePackage.replace('.', '/');
       basePackageDir = Utility.getDirectory(javaDir, basePackage, true);
     } else {
       moduleName = className;
       basePackageDir = javaDir;
+      serverPackageName = "server";
     }
     File clientDir = Utility.getDirectory(basePackageDir, "client", true);
     File publicDir = Utility.getDirectory(basePackageDir, "public", true);
-    String startupUrl = moduleName + "/" + className + ".html";
+    File serverDir = Utility.getDirectory(basePackageDir, "server", true);
+    String startupUrl = className + ".html";
 
     // Create a map of replacements
     //
@@ -256,103 +301,125 @@
     replacements.put("@className", className);
     replacements.put("@moduleName", moduleName);
     replacements.put("@clientPackage", clientPackageName);
+    replacements.put("@serverPackage", serverPackageName);
     replacements.put("@gwtUserPath", basePathEnv + gwtUserPath);
     replacements.put("@gwtDevPath", basePathEnv + gwtDevPath);
-    replacements.put("@shellClass", "com.google.gwt.dev.GWTShell");
+    replacements.put("@shellClass", "com.google.gwt.dev.GWTHosted");
     replacements.put("@compileClass", "com.google.gwt.dev.GWTCompiler");
     replacements.put("@startupUrl", startupUrl);
-    replacements.put("@vmargs", isMacOsX ? "-XstartOnFirstThread" : "");
+    replacements.put("@vmargs", isMacOsX
+        ? "<jvmarg value=\"-XstartOnFirstThread\"/>" : "");
     replacements.put("@eclipseExtraLaunchPaths",
         CreatorUtilities.createEclipseExtraLaunchPaths(extraClassPaths));
     replacements.put("@extraModuleInherits",
         createExtraModuleInherits(extraModules));
     replacements.put("@extraClassPathsColon", CreatorUtilities.appendPaths(":",
         extraClassPaths));
-    replacements.put("@extraClassPathsSemicolon", CreatorUtilities.appendPaths(";", extraClassPaths));
+    replacements.put("@extraClassPathsSemicolon", CreatorUtilities.appendPaths(
+        ";", extraClassPaths));
+    replacements.put("@newModuleName", (newModuleName != null) ? newModuleName
+        : moduleName);
+    replacements.put("@deployDir", deployDir.getName());
 
     {
-      // Create the module
-      File moduleXML = Utility.createNormalFile(basePackageDir, className
-          + ModuleDefLoader.GWT_MODULE_XML_SUFFIX, overwrite, ignore);
-      if (moduleXML != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "Module.gwt.xmlsrc");
-        Utility.writeTemplateFile(moduleXML, out, replacements);
+      // create the module xml file, skeleton html file, skeleton css file,
+      // web.xml file
+      FileCreator fileCreators[] = new FileCreator[] {
+          new FileCreator(basePackageDir, "Module.gwt.xml", className
+              + ModuleDefLoader.GWT_MODULE_XML_SUFFIX),
+          new FileCreator(warDir, "AppHtml.html", className + ".html"),
+          new FileCreator(warDir, "AppCss.css", className + ".css"),
+          new FileCreator(webInfDir, "web.xml", "web.xml"),};
+      for (FileCreator fileCreator : fileCreators) {
+        File file = Utility.createNormalFile(fileCreator.dir,
+            fileCreator.className, overwrite, ignore);
+        if (file != null) {
+          String out = Utility.getFileFromClassPath(PACKAGE_PATH
+              + fileCreator.sourceName + "src");
+          Utility.writeTemplateFile(file, out, replacements);
+        }
       }
     }
 
     {
-      // Create a skeleton html file
-      File publicHTML = Utility.createNormalFile(publicDir,
-          className + ".html", overwrite, ignore);
-      if (publicHTML != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "AppHtml.htmlsrc");
-        Utility.writeTemplateFile(publicHTML, out, replacements);
-      }
-    }
-
-    {
-      // Create a skeleton css file
-      File publicCSS = Utility.createNormalFile(publicDir, className + ".css",
-          overwrite, ignore);
-      if (publicCSS != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "AppCss.csssrc");
-        Utility.writeTemplateFile(publicCSS, out, replacements);
-      }
-    }
-
-    {
-      // Create a skeleton Application class
-      File javaClass = Utility.createNormalFile(clientDir, className + ".java",
-          overwrite, ignore);
-      if (javaClass != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "AppClassTemplate.javasrc");
-        Utility.writeTemplateFile(javaClass, out, replacements);
+      /*
+       * Create a skeleton Application: main client class, rpc stub for the
+       * client, async counterpart of the rpc stub, rpc implementation on the
+       * server.
+       */
+      FileCreator fileCreators[] = new FileCreator[] {
+          new FileCreator(clientDir, "AppClass", className),
+          new FileCreator(clientDir, "RpcClient", "EchoService"),
+          new FileCreator(clientDir, "RpcAsyncClient", "EchoServiceAsync"),
+          new FileCreator(serverDir, "RpcServer", "EchoServiceImpl"),};
+      for (FileCreator fileCreator : fileCreators) {
+        File javaClass = Utility.createNormalFile(fileCreator.dir,
+            fileCreator.className + ".java", overwrite, ignore);
+        if (javaClass != null) {
+          String out = Utility.getFileFromClassPath(PACKAGE_PATH
+              + fileCreator.sourceName + "Template.javasrc");
+          Utility.writeTemplateFile(javaClass, out, replacements);
+        }
       }
     }
 
     if (eclipse != null) {
-      // Create an eclipse launch config
       replacements.put("@projectName", eclipse);
-      File launchConfig = Utility.createNormalFile(outDir, className
-          + ".launch", overwrite, ignore);
-      if (launchConfig != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "App.launchsrc");
-        Utility.writeTemplateFile(launchConfig, out, replacements);
+      // Build the list of extra paths
+      replacements.put("@gwtServletPath", basePathEnv + gwtServletPath);
+      StringBuilder buf = new StringBuilder();
+      if (extraClassPaths != null) {
+        for (String path : extraClassPaths) {
+          buf.append("    <pathelement path=\"" + path + "\"/>");
+        }
       }
-    }
+      replacements.put("@extraAntPathElements", buf.toString());
 
-    // create startup files
-    String extension;
-    if (isWindows) {
-      extension = ".cmd";
-    } else {
-      extension = "";
-    }
+      StringBuilder classpathEntries = new StringBuilder();
+      if (extraClassPaths != null) {
+        for (String path : extraClassPaths) {
+          File f = new File(path);
 
-    File gwtshell = Utility.createNormalFile(outDir, className + "-shell"
-        + extension, overwrite, ignore);
-    if (gwtshell != null) {
-      String out = Utility.getFileFromClassPath(PACKAGE_PATH + "gwtshell"
-          + extension + "src");
-      Utility.writeTemplateFile(gwtshell, out, replacements);
-      if (extension.length() == 0) {
-        chmodExecutable(gwtshell);
+          if (!f.exists()) {
+            throw new FileNotFoundException("extraClassPath: " + path
+                + " must be present before .launch file can be created.");
+          }
+          // Handle both .jar files and paths
+          String kindString;
+          if (f.isDirectory()) {
+            kindString = "output";
+          } else if (path.endsWith(".jar")) {
+            kindString = "lib";
+          } else {
+            throw new RuntimeException("Don't know how to handle path: " + path
+                + ". It doesn't appear to be a directory or a .jar file");
+          }
+          classpathEntries.append("   <classpathentry kind=\"");
+          classpathEntries.append(kindString);
+          classpathEntries.append("\" path=\"");
+          classpathEntries.append(path);
+          classpathEntries.append("\"/>\n");
+        }
       }
-    }
+      replacements.put("@eclipseClassPathEntries", classpathEntries.toString());
 
-    File gwtcompile = Utility.createNormalFile(outDir, className + "-compile"
-        + extension, overwrite, ignore);
-    if (gwtcompile != null) {
-      String out = Utility.getFileFromClassPath(PACKAGE_PATH + "gwtcompile"
-          + extension + "src");
-      Utility.writeTemplateFile(gwtcompile, out, replacements);
-      if (extension.length() == 0) {
-        chmodExecutable(gwtcompile);
+      /*
+       * create an ant file, an eclipse .project, an eclipse .classpath, and an
+       * eclipse launch-config
+       */
+      FileCreator fileCreators[] = new FileCreator[] {
+          new FileCreator(outDir, "project.ant.xml", "build.xml"),
+          new FileCreator(outDir, ".project", ".project"),
+          new FileCreator(outDir, ".classpath", ".classpath"),
+          new FileCreator(outDir, "App.launch", className + ".launch"),};
+      for (FileCreator fileCreator : fileCreators) {
+        File file = Utility.createNormalFile(fileCreator.dir,
+            fileCreator.className, overwrite, ignore);
+        if (file != null) {
+          String out = Utility.getFileFromClassPath(PACKAGE_PATH
+              + fileCreator.sourceName + "src");
+          Utility.writeTemplateFile(file, out, replacements);
+        }
       }
     }
   }
@@ -393,13 +460,15 @@
   private ArgHandlerAddModule moduleHandler = new ArgHandlerAddModule();
   private File outDir;
   private boolean overwrite = false;
+  private String newModuleName = null;
+  private File deployDir;
 
   protected ApplicationCreator() {
 
     registerHandler(new ArgHandlerEclipse() {
       @Override
       public String getPurpose() {
-        return "Creates a debug launch config for the named eclipse project";
+        return "Creates an ant file, an eclipse project, and a launch config";
       }
 
       @Override
@@ -440,6 +509,64 @@
       }
     });
 
+    // handler to process newModuleName argument
+    registerHandler(new ArgHandlerString() {
+      @Override
+      public String[] getDefaultArgs() {
+        return null; // later reset to moduleName
+      }
+
+      @Override
+      public String getPurpose() {
+        return "Specifies the new name of the module";
+      }
+
+      @Override
+      public String getTag() {
+        return "-moduleName";
+      }
+
+      @Override
+      public String[] getTagArgs() {
+        return new String[] {"moduleName"};
+      }
+
+      @Override
+      public boolean setString(String str) {
+        newModuleName = str;
+        return true;
+      }
+
+    });
+
+    // handler to create the deployDir
+    registerHandler(new ArgHandlerDir() {
+
+      @Override
+      public String[] getDefaultArgs() {
+        return new String[] {"-deployDir", "deployDir"};
+      }
+
+      @Override
+      public String getPurpose() {
+        return "Specifies the deploy directory (defaults to deployDir)";
+      }
+
+      @Override
+      public String getTag() {
+        return "-deployDir";
+      }
+
+      @Override
+      public void setDir(File dir) {
+        if (dir.getName().length() == 0) {
+          throw new IllegalArgumentException("deployDir may not be empty");
+        }
+        deployDir = dir;
+      }
+
+    });
+
     registerHandler(new ArgHandlerAppClass());
     registerHandler(classPathHandler);
     registerHandler(moduleHandler);
@@ -449,7 +576,7 @@
     try {
       createApplication(fullClassName, outDir, eclipse, overwrite, ignore,
           classPathHandler.getExtraClassPathList(),
-          moduleHandler.getExtraModuleList());
+          moduleHandler.getExtraModuleList(), newModuleName, deployDir);
       return true;
     } catch (IOException e) {
       System.err.println(e.getClass().getName() + ": " + e.getMessage());
diff --git a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
index 4228170..84faca6 100644
--- a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
+++ b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
@@ -1,4 +1,4 @@
-<module>
+<module rename-to='@newModuleName' deploy-to='/@deployDir'>
 
       <!-- Inherit the core Web Toolkit stuff.                        -->
       <inherits name='com.google.gwt.user.User'/>
diff --git a/user/src/com/google/gwt/user/tools/ProjectCreator.java b/user/src/com/google/gwt/user/tools/ProjectCreator.java
deleted file mode 100644
index 0ea5d2b..0000000
--- a/user/src/com/google/gwt/user/tools/ProjectCreator.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright 2007 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.user.tools.util.ArgHandlerAddToClassPath;
-import com.google.gwt.user.tools.util.ArgHandlerEclipse;
-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.ArgHandlerOutDir;
-import com.google.gwt.util.tools.ArgHandlerString;
-import com.google.gwt.util.tools.ToolBase;
-import com.google.gwt.util.tools.Utility;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Creates a new GWT project.
- */
-public final class ProjectCreator extends ToolBase {
-
-  private static final String PACKAGE_PATH;
-
-  static {
-    String path = ProjectCreator.class.getName();
-    path = path.substring(0, path.lastIndexOf('.') + 1);
-    PACKAGE_PATH = path.replace('.', '/');
-  }
-
-  public static void main(String[] args) {
-    ProjectCreator creator = new ProjectCreator();
-    if (creator.processArgs(args)) {
-      if (creator.run()) {
-        return;
-      }
-    }
-
-    System.exit(1);
-  }
-
-  /**
-   * Create a set of project files.
-   * 
-   * @param eclipse The name of project to create.
-   * @param ant The name of an ant file to create.
-   * @param outDir The directory to write into.
-   * @param overwrite Overwrite an existing files if they exist.
-   * @param ignore Ignore existing files if they exist.
-   * @throws IOException
-   */
-  static void createProject(String eclipse, String ant, File outDir,
-      boolean overwrite, boolean ignore) throws IOException {
-    createProject(eclipse, ant, outDir, overwrite, ignore, null);
-  }
-
-  /**
-   * Create a set of project files.
-   * 
-   * @param eclipse The name of project to create.
-   * @param ant The name of an ant file to create.
-   * @param outDir The directory to write into.
-   * @param overwrite Overwrite an existing files if they exist.
-   * @param ignore Ignore existing files if they exist.
-   * @param extraClassPaths class path entries passed on the command line
-   * @throws IOException
-   */
-  static void createProject(String eclipse, String ant, File outDir,
-      boolean overwrite, boolean ignore, List<String> extraClassPaths)
-      throws IOException {
-
-    // Figure out the installation directory
-    String installPath = Utility.getInstallPath();
-
-    // Create a map of replacements.
-    Map<String, String> replacements = new HashMap<String, String>();
-    String userJarPath = installPath + '/' + "gwt-user.jar";
-    replacements.put("@gwtUserPath", userJarPath);
-
-    // Check to see that the passed extra path/module arguments are valid.
-    if (!CreatorUtilities.validatePathsAndModules(userJarPath, extraClassPaths,
-        null)) {
-      return;
-    }
-
-    Utility.getDirectory(outDir, "src", true);
-    Utility.getDirectory(outDir, "test", true);
-
-    if (ant != null) {
-      // Create an ant build file
-      replacements.put("@projectName", ant);
-
-      // Build the list of extra paths
-      StringBuilder buf = new StringBuilder();
-      if (extraClassPaths != null) {
-        for (String path : extraClassPaths) {
-          buf.append("    <pathelement path=\"" + path + "\"/>");
-        }
-      }
-      replacements.put("@extraAntPathElements", buf.toString());
-
-      File antXML = Utility.createNormalFile(outDir, ant + ".ant.xml",
-          overwrite, ignore);
-      if (antXML != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + "project.ant.xmlsrc");
-        Utility.writeTemplateFile(antXML, out, replacements);
-      }
-    }
-
-    if (eclipse != null) {
-      // Create an eclipse project file
-      replacements.put("@projectName", eclipse);
-      File dotProject = Utility.createNormalFile(outDir, ".project", overwrite,
-          ignore);
-      if (dotProject != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH + ".projectsrc");
-        Utility.writeTemplateFile(dotProject, out, replacements);
-      }
-
-      StringBuilder classpathEntries = new StringBuilder();
-      if (extraClassPaths != null) {
-        for (String path : extraClassPaths) {
-          File f = new File(path);
-
-          if (!f.exists()) {
-            throw new FileNotFoundException("extraClassPath: " + path
-                + " must be present before .launch file can be created.");
-          }
-          // Handle both .jar files and paths
-        String kindString;
-          if (f.isDirectory()) {
-            kindString = "output";
-          } else if (path.endsWith(".jar")) {
-            kindString = "lib";
-          } else {
-            throw new RuntimeException("Don't know how to handle path: " + path
-                + ". It doesn't appear to be a directory or a .jar file");
-          }
-          classpathEntries.append("   <classpathentry kind=\"");
-          classpathEntries.append(kindString);
-          classpathEntries.append("\" path=\"");
-          classpathEntries.append(path);
-          classpathEntries.append("\"/>\n");
-        }
-      }
-
-      replacements.put("@eclipseClassPathEntries", classpathEntries.toString());
-
-      // Create an eclipse classpath file
-      File dotClasspath = Utility.createNormalFile(outDir, ".classpath",
-          overwrite, ignore);
-      if (dotClasspath != null) {
-        String out = Utility.getFileFromClassPath(PACKAGE_PATH
-            + ".classpathsrc");
-        Utility.writeTemplateFile(dotClasspath, out, replacements);
-      }
-    }
-  }
-
-  private String ant = null;
-  private String eclipse = null;
-  private boolean ignore = false;
-  private File outDir = null;
-  private boolean overwrite = false;
-  private ArgHandlerAddToClassPath classPathHandler = new ArgHandlerAddToClassPath();
-
-  protected ProjectCreator() {
-
-    registerHandler(new ArgHandlerString() {
-
-      @Override
-      public String getPurpose() {
-        return "Generate an Ant buildfile to compile source (.ant.xml will be appended)";
-      }
-
-      @Override
-      public String getTag() {
-        return "-ant";
-      }
-
-      @Override
-      public String[] getTagArgs() {
-        return new String[] {"projectName"};
-      }
-
-      @Override
-      public boolean setString(String str) {
-        ant = str;
-        return true;
-      }
-
-    });
-
-    registerHandler(new ArgHandlerEclipse() {
-      @Override
-      public String getPurpose() {
-        return "Generate an eclipse project";
-      }
-
-      @Override
-      public boolean setString(String str) {
-        eclipse = str;
-        return true;
-      }
-    });
-
-    registerHandler(new ArgHandlerOutDir() {
-      @Override
-      public void setDir(File dir) {
-        outDir = dir;
-      }
-    });
-
-    registerHandler(new ArgHandlerOverwrite() {
-      @Override
-      public boolean setFlag() {
-        if (ignore) {
-          System.err.println("-overwrite cannot be used with -ignore.");
-          return false;
-        }
-        overwrite = true;
-        return true;
-      }
-    });
-
-    registerHandler(new ArgHandlerIgnore() {
-      @Override
-      public boolean setFlag() {
-        if (overwrite) {
-          System.err.println("-ignore cannot be used with -overwrite.");
-          return false;
-        }
-        ignore = true;
-        return true;
-      }
-    });
-
-    registerHandler(classPathHandler);
-  }
-
-  protected boolean run() {
-    try {
-      if (ant == null && eclipse == null) {
-        System.err.println("Please specify either -ant or -eclipse.");
-        printHelp();
-        return false;
-      }
-      createProject(eclipse, ant, outDir, overwrite, ignore,
-          classPathHandler.getExtraClassPathList());
-      return true;
-    } catch (IOException e) {
-      System.err.println(e.getClass().getName() + ": " + e.getMessage());
-      return false;
-    }
-  }
-}
diff --git a/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc
new file mode 100644
index 0000000..52eef3e
--- /dev/null
+++ b/user/src/com/google/gwt/user/tools/RpcAsyncClientTemplate.javasrc
@@ -0,0 +1,10 @@
+package @clientPackage;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * The async counterpart of <code>EchoService</code>. 
+ */
+public interface EchoServiceAsync {
+  void echo (String input, AsyncCallback<String> callback);
+}
diff --git a/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc
new file mode 100644
index 0000000..419660c
--- /dev/null
+++ b/user/src/com/google/gwt/user/tools/RpcClientTemplate.javasrc
@@ -0,0 +1,10 @@
+package @clientPackage;
+
+import com.google.gwt.user.client.rpc.RemoteService;
+
+/**
+ * The client side stub for the Rpc service.
+ */
+public interface EchoService extends RemoteService {
+  String echo (String input);
+}
diff --git a/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc b/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc
new file mode 100644
index 0000000..3f4ae7e
--- /dev/null
+++ b/user/src/com/google/gwt/user/tools/RpcServerTemplate.javasrc
@@ -0,0 +1,16 @@
+package @serverPackage;
+
+import @clientPackage.EchoService;
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+/**
+ * The server side implementation of the Rpc service.
+ */
+public class EchoServiceImpl extends RemoteServiceServlet implements
+    EchoService {
+
+  public String echo(String input) {
+    return "Server says: " + input;
+  }
+
+}
diff --git a/user/src/com/google/gwt/user/tools/gwtcompile.cmdsrc b/user/src/com/google/gwt/user/tools/gwtcompile.cmdsrc
deleted file mode 100644
index 80f6e97..0000000
--- a/user/src/com/google/gwt/user/tools/gwtcompile.cmdsrc
+++ /dev/null
@@ -1 +0,0 @@
-@java -Xmx256M -cp "%~dp0\src;%~dp0\bin;@gwtUserPath;@gwtDevPath@extraClassPathsSemicolon" @compileClass -out "%~dp0\www" %* @moduleName
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/tools/gwtcompilesrc b/user/src/com/google/gwt/user/tools/gwtcompilesrc
deleted file mode 100644
index 75064a8..0000000
--- a/user/src/com/google/gwt/user/tools/gwtcompilesrc
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-APPDIR=`dirname $0`;
-java @vmargs -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:@gwtUserPath:@gwtDevPath@extraClassPathsColon" @compileClass -out "$APPDIR/www" "$@" @moduleName;
diff --git a/user/src/com/google/gwt/user/tools/gwtshell.cmdsrc b/user/src/com/google/gwt/user/tools/gwtshell.cmdsrc
deleted file mode 100644
index dd14324..0000000
--- a/user/src/com/google/gwt/user/tools/gwtshell.cmdsrc
+++ /dev/null
@@ -1 +0,0 @@
-@java -Xmx256M -cp "%~dp0\src;%~dp0\bin;@gwtUserPath;@gwtDevPath@extraClassPathsSemicolon" @shellClass -out "%~dp0\www" %* @startupUrl
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/tools/gwtshellsrc b/user/src/com/google/gwt/user/tools/gwtshellsrc
deleted file mode 100644
index 195b443..0000000
--- a/user/src/com/google/gwt/user/tools/gwtshellsrc
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-APPDIR=`dirname $0`;
-java @vmargs -Xmx256M -cp "$APPDIR/src:$APPDIR/bin:@gwtUserPath:@gwtDevPath@extraClassPathsColon" @shellClass -out "$APPDIR/www" "$@" @startupUrl;
diff --git a/user/src/com/google/gwt/user/tools/project.ant.xmlsrc b/user/src/com/google/gwt/user/tools/project.ant.xmlsrc
index 942140d..de75dc9 100644
--- a/user/src/com/google/gwt/user/tools/project.ant.xmlsrc
+++ b/user/src/com/google/gwt/user/tools/project.ant.xmlsrc
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<project name="@projectName" default="compile" basedir=".">
+<project name="@projectName" default="build" basedir=".">
   <description>
     @projectName build file.  This is used to package up your project as a jar,
     if you want to distribute it.  This isn't needed for normal operation.
   </description>
+  <property name="outdir" location="war" />
+  <property name="extradir" location="extra" />
 
   <!-- set classpath -->
   <path id="project.class.path">
@@ -13,36 +15,78 @@
     <!-- Additional dependencies (such as junit) go here -->
   </path>
 
-  <target name="compile" description="Compile src to bin">
-    <mkdir dir="bin"/>
-    <javac srcdir="src:test" destdir="bin" includes="**" debug="on" debuglevel="lines,vars,source" source="1.4">
+  <!-- TODO:  
+   1. revisit this once GWT supports shared dir as a first-clas citizen
+   2. For a 1.4 server, split this so that the server side code is compiled
+   with a target=1.4 build rule -->
+  <target name="javac" description="Compile project to WEB-INF/classes">
+    <mkdir dir="${outdir}/WEB-INF/classes"/>
+    <javac srcdir="src:test"
+      destdir="${outdir}/WEB-INF/classes"
+      includes="**"
+      debug="true"
+      debuglevel="lines,vars,source"
+      source="1.5"
+      target="1.5"
+      nowarn="true"
+      encoding="utf-8">
       <classpath refid="project.class.path"/>
     </javac>
   </target>
 
-  <target name="package" depends="compile" description="Package up the project as a jar">
-    <jar destfile="@projectName.jar">
-      <fileset dir="bin">
-        <include name="**/*.class"/>
-      </fileset>
-      <!-- Get everything; source, modules, html files -->
-      <fileset dir="src">
-        <include name="**"/>
-      </fileset>
-      <fileset dir="test">
-        <include name="**"/>
-      </fileset>
-    </jar>
+  <target name="deploy" depends="gwtc" description="Copy output to the war folder">
+    <mkdir dir="${outdir}/WEB-INF/lib" />
+    <copy todir="${outdir}/WEB-INF/lib" file="@gwtServletPath" />
   </target>
 
-  <target name="clean">
-    <!-- Delete the bin directory tree -->
-    <delete file="@projectName.jar"/>
-    <delete>
-      <fileset dir="bin" includes="**/*.class"/>
-    </delete>
+  <!-- can add additional arguments like -logLevel INFO or -style PRETTY -->
+  <target name="gwtc" depends="javac" description="Compile to JavaScript">
+    <java failonerror="true" fork="true"
+          classname="@compileClass">
+      <classpath>
+        <pathelement location="src"/>
+        <pathelement location="@gwtDevPath"/>
+        <pathelement location="${outdir}/WEB-INF/classes"/>
+        <pathelement path="${java.class.path}/"/>
+        <pathelement path="@gwtUserPath"/>
+      </classpath>
+      @vmargs
+      <arg value="-out"/>
+      <arg file="${outdir}"/>
+      <arg value="-extra"/>
+      <arg file="${extradir}"/>
+      <arg value="@moduleName"/>
+    </java>
   </target>
 
-  <target name="all" depends="package"/>
+  <!-- can add additional arguments like -logLevel INFO -->
+  <target name="shell" depends="javac" description="Run the deployed app in GWT hosted mode">
+    <java failonerror="true" fork="true"
+          classname="@shellClass">
+      <jvmarg value="-Xmx256M"/>
+      <classpath>
+        <pathelement location="src"/>
+        <pathelement location="@gwtDevPath"/>
+        <pathelement path="${java.class.path}/"/>
+        <pathelement path="@gwtUserPath"/>
+      </classpath>
+      @vmargs
+      <arg value="-out"/>
+      <arg file="${outdir}"/>
+      <arg value="-startupUrl"/>
+      <arg value="@startupUrl"/>
+      <arg value="@moduleName"/>
+    </java>
+  </target>
+
+  <target name="build" depends="javac, gwtc, deploy" description="Build this project" />
+
+  <target name="clean" description="Cleans this project's intermediate and
+    output files">
+    <!-- uncomment if the WEB-INF/classes dir only contains GWT output --> 
+    <!-- <delete dir="${outdir}/WEB-INF/classes" failonerror="false" /> -->
+    <delete dir="${outdir}/@deployDir" failonerror="false" />
+    <delete dir="${extradir}" failonerror="false" />
+  </target>
 
 </project>
diff --git a/user/src/com/google/gwt/user/tools/web.xmlsrc b/user/src/com/google/gwt/user/tools/web.xmlsrc
new file mode 100644
index 0000000..1d33d1e
--- /dev/null
+++ b/user/src/com/google/gwt/user/tools/web.xmlsrc
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app>
+
+  <servlet>
+    <servlet-name>echoServlet</servlet-name>
+    <servlet-class>@serverPackage.EchoServiceImpl</servlet-class>
+  </servlet>
+  
+  <servlet-mapping>
+    <servlet-name>echoServlet</servlet-name>
+    <url-pattern>/@deployDir/echo</url-pattern>
+  </servlet-mapping>
+
+</web-app>