Permalink
Browse files

Move Super Dev Mode to the open source repository.

Includes a simple "demo" target that works with the "Hello" sample app.
I've also made some linker options configurable, as necessary to make this work.
Review at http://gwt-code-reviews.appspot.com/1727804


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11016 8db76d5a-ed1c-0410-87a9-c151d255dfc7
  • Loading branch information...
skybrian@google.com
skybrian@google.com committed Jun 5, 2012
1 parent 04ad546 commit cc7626f913ed8b7cd949085a3351c646749fd55c
View
@@ -0,0 +1,81 @@
+<project name="codeserver" default="build" basedir=".">
+ <property name="gwt.root" location="../.." />
+ <property name="project.tail" value="dev/codeserver" />
+ <import file="${gwt.root}/common.ant.xml" />
+
+ <property.ensure name="gwt.dev.jar" location="${gwt.build.lib}/gwt-dev.jar" />
+
+ <!-- location of preprocessed source -->
+ <property name="src" value="${project.build}/src" />
+
+ <!--
+ Nasty hack to fix the source code for the open source build.
+ Constraint: the code in the "java/" directory is how we want it inside Google.
+ But outside Google, Jetty is not repackaged, so we need to fix the import statements.
+ (The right way to do this is probably to repackage Jetty.)
+ -->
+ <target name="preprocess">
+ <delete dir="${src}"/>
+ <mkdir dir="${src}"/>
+ <copy todir="${src}">
+ <fileset dir="java">
+ <include name="**/*.java"/>
+ </fileset>
+ </copy>
+ <replace dir="${src}" token="com.google.gwt.thirdparty.org.mortbay.jetty"
+ value="org.mortbay.jetty"/>
+ </target>
+
+ <target name="compile" depends="preprocess">
+ <mkdir dir="${javac.out}" />
+ <gwt.javac srcdir="${src}">
+ <classpath>
+ <pathelement location="${gwt.dev.jar}" />
+ </classpath>
+ </gwt.javac>
+ </target>
+
+ <target name="build" depends="compile" description="builds gwt-codeserver.jar">
+ <gwt.jar>
+ <fileset dir="${javac.out}"/>
+ <fileset dir="java">
+ <include name="**/*.html"/>
+ <include name="**/*.js"/>
+ </fileset>
+
+ <manifest>
+ <!-- why doesn't this work?
+ <attribute name="Class-Path" value="gwt-dev.jar gwt.user.jar" />
+ -->
+ <attribute name="Main-Class" value="com.google.gwt.dev.codeserver.CodeServer" />
+ </manifest>
+ </gwt.jar>
+ </target>
+
+ <!-- no-op for now -->
+ <target name="verify"/>
+
+ <target name="demo" depends="build" description="starts the code server with a sample app">
+
+ <!-- hack to make sourcemaps generation work in the compiler -->
+ <!-- See: http://code.google.com/p/google-web-toolkit/issues/detail?id=7397 -->
+ <property.ensure name="json.jar"
+ location="${gwt.tools}/redist/json/r2_20080312/json-1.5.jar" />
+
+ <property.ensure name="gwt.user.jar" location="${gwt.build.lib}/gwt-user.jar" />
+ <property.ensure name="sample-src" location="${gwt.root}/samples/hello/src" />
+
+ <java fork="true" failonerror="true" classname="com.google.gwt.dev.codeserver.CodeServer">
+ <classpath>
+ <pathelement location="${project.lib}"/>
+ <pathelement location="${gwt.dev.jar}"/>
+ <pathelement location="${json.jar}" />
+ <pathelement location="${gwt.user.jar}"/>
+ </classpath>
+ <arg value="-src"/>
+ <arg value="${sample-src}"/>
+ <arg value="com.google.gwt.sample.hello.Hello"/>
+ </java>
+ </target>
+
+</project>
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 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.dev.codeserver;
+
+import com.google.gwt.dev.util.Util;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * The directory tree where Super Dev Mode keeps all the files for one GWT app.
+ * Each time we recompile the app, we create a new subdirectory (see {@link CompileDir}).
+ * In addition, there are some files that are shared between recompiles, such as
+ * the unit cache.
+ */
+class AppSpace {
+
+ static final String COMPILE_DIR_PREFIX = "compile-";
+ private final File root;
+
+ /**
+ * @see #create
+ */
+ private AppSpace(File root) {
+ this.root = root;
+ }
+
+ File getSpeedTracerLogFile() {
+ return new File(root, "speedtracer.html");
+ }
+
+ File getUnitCacheDir() {
+ return new File(root, "gwt-unitcache");
+ }
+
+ File getCompileDir(int compileId) {
+ return new File(root, COMPILE_DIR_PREFIX + compileId);
+ }
+
+ /**
+ * Creates an app directory, doing any cleanup needed.
+ * @param dir the directory to use. It need not exist, but
+ * the parent dir should exist.
+ */
+ static AppSpace create(File dir) throws IOException {
+ if (!dir.exists() && !dir.mkdir()) {
+ throw new IOException("can't create app directory: " + dir);
+ }
+
+ // clean up existing subdirectories
+ for (File candidate : dir.listFiles()) {
+ if (candidate.getName().startsWith(COMPILE_DIR_PREFIX)) {
+ System.err.println("deleting: " + candidate);
+ Util.recursiveDelete(candidate, false);
+ }
+ }
+
+ return new AppSpace(dir);
+ }
+}
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2011 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.dev.codeserver;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import com.google.gwt.util.tools.Utility;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * <p>This class contains the {@link #main main method} that starts the code server for
+ * "Super Dev Mode", a replacement for developer mode that doesn't require
+ * browser plugins.</p>
+ *
+ * <p>This tool is EXPERIMENTAL. There is no authentication, no encryption, no XSS
+ * protection, and it makes all source code on the GWT compiler's classpath available
+ * via HTTP. It is only safe to run on localhost (the default).</p>
+ */
+public class CodeServer {
+
+ /**
+ * Starts the code server. Shuts down the JVM if startup fails.
+ * @param args Command-line options that can be parsed by {@link Options}.
+ */
+ public static void main(String[] args) throws Exception {
+
+ Options options = new Options();
+ if (!options.parseArgs(args)) {
+ System.exit(1);
+ }
+
+ try {
+ start(options);
+
+ System.out.println();
+ System.out.println("The code server is ready.");
+ System.out.println("Next, visit: http://localhost:" + options.getPort() + "/");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Starts the code server with the given command line options. To shut it down, see
+ * {@link WebServer#stop}.
+ *
+ * <p>Only one code server should be started at a time because the GWT compiler uses
+ * a lot of static variables.</p>
+ */
+ public static WebServer start(Options options) throws IOException, UnableToCompleteException {
+ if (options.getModuleNames().isEmpty()) {
+ throw new IllegalArgumentException("Usage: at least one module must be supplied");
+ }
+
+ PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
+ logger.setMaxDetail(TreeLogger.Type.INFO);
+ Modules modules = new Modules();
+
+ File workDir = ensureWorkDir(options);
+ System.out.println("workDir: " + workDir);
+
+ for (String moduleName : options.getModuleNames()) {
+ AppSpace appSpace = AppSpace.create(new File(workDir, moduleName));
+
+ Recompiler recompiler = new Recompiler(appSpace, moduleName,
+ options.getSourcePath(), logger);
+ modules.addModuleState(new ModuleState(recompiler, logger));
+ }
+
+ SourceHandler sourceHandler = new SourceHandler(modules, logger);
+
+ WebServer webServer = new WebServer(sourceHandler, modules,
+ options.getPort(), logger);
+ webServer.start();
+
+ return webServer;
+ }
+
+ /**
+ * Ensures that we have a work directory. If specified via a flag, the
+ * directory must already exist. Otherwise, create a temp directory.
+ */
+ private static File ensureWorkDir(Options options) throws IOException {
+ File workDir = options.getWorkDir();
+ if (workDir == null) {
+ workDir = Utility.makeTemporaryDirectory(null, "gwt-codeserver-");
+ } else {
+ if (!workDir.isDirectory()) {
+ throw new IOException("workspace directory doesn't exist: " + workDir);
+ }
+ }
+ return workDir;
+ }
+}
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 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.dev.codeserver;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import java.io.File;
+
+/**
+ * Defines a directory tree used for compiling a GWT app one time. Each time we recompile
+ * the app, we will create a new, empty CompileDir. This way, a failed compile doesn't
+ * modify the last good compile.
+ *
+ * The CompileDir gets created within the appropriate {@link AppSpace} for the app
+ * being compiled.
+ */
+class CompileDir {
+ private final File dir;
+
+ /**
+ * @see #create
+ */
+ private CompileDir(File dir) {
+ this.dir = dir;
+ }
+
+ File getWarDir() {
+ return new File(dir, "war");
+ }
+
+ File getDeployDir() {
+ return new File(getWarDir(), "WEB-INF/deploy");
+ }
+
+ File getExtraDir() {
+ return new File(dir, "extras");
+ }
+
+ File getGenDir() {
+ return new File(dir, "gen");
+ }
+
+ File getWorkDir() {
+ return new File(dir, "work");
+ }
+
+ File getLogFile() {
+ return new File(dir, "compile.log");
+ }
+
+ File findSymbolMapDir(String moduleName) {
+ // The JUnit module moves the symbolMaps directory in a post linker.
+ // TODO(skybrian) query this information from the compiler somehow?
+ File[] candidates = {
+ new File(getExtraDir(), moduleName + "/symbolMaps"),
+ new File(getWarDir(), moduleName + "/.junit_symbolMaps")
+ };
+
+ for (File candidate : candidates) {
+ if (candidate.isDirectory()) {
+ return candidate;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new compileDir directory structure. The directory must not already exist,
+ * but its parent should exist.
+ * @throws UnableToCompleteException if unable to create the directory
+ */
+ static CompileDir create(File dir, TreeLogger logger)
+ throws UnableToCompleteException {
+
+ CompileDir result = new CompileDir(dir);
+
+ mkdir(dir, logger);
+ mkdir(result.getWarDir(), logger);
+
+ return result;
+ }
+
+ private static void mkdir(File dirToCreate, TreeLogger logger)
+ throws UnableToCompleteException {
+ if (!dirToCreate.mkdir()) {
+ logger.log(TreeLogger.Type.ERROR, "unable to create directory: " + dirToCreate);
+ throw new UnableToCompleteException();
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit cc7626f

Please sign in to comment.