Remove long-deprecated GWTShell and GWTCompiler tools.
Change-Id: Ifa9eb9f20bfed18f4252e6d9841937ceb1d75743
Review-Link: https://gwt-review.googlesource.com/#/c/1030/
Review by: skybrian@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11411 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/build.xml b/dev/build.xml
index 0ea5528..08677ef 100755
--- a/dev/build.xml
+++ b/dev/build.xml
@@ -34,7 +34,6 @@
excludes="**/super/**">
<classpath>
<pathelement location="${javac.out}" />
- <pathelement location="${gwt.tools.lib}/tomcat/servlet-api-2.5.jar" />
<pathelement location="${gwt.tools.lib}/junit/junit-4.8.2.jar" />
<pathelement location="${gwt.tools.lib}/jfreechart/jfreechart-1.0.3.jar" />
<pathelement location="${gwt.tools.lib}/selenium/selenium-java-client-driver.jar" />
@@ -63,33 +62,13 @@
<include name="jetty/jetty-6.1.11.jar" />
<include name="icu4j/4.4.2/icu4j.jar" />
<include name="protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar" />
- <include name="tomcat/ant-launcher-1.6.5.jar" />
- <include name="tomcat/catalina-1.0.jar" />
- <include name="tomcat/catalina-optional-1.0.jar" />
- <include name="tomcat/commons-beanutils-1.6.jar" />
- <include name="tomcat/commons-collections-3.1.jar" />
- <include name="tomcat/commons-digester-1.5.jar" />
+ <!-- dependencies needed for JSP support in DevMode: BEGIN -->
<include name="tomcat/commons-el-1.0.jar" />
- <include name="tomcat/commons-logging-1.0.jar" />
- <include name="tomcat/commons-modeler-1.1.jar" />
- <include name="tomcat/jakarta-regexp-1.3.jar" />
<include name="tomcat/jasper-compiler-1.0.jar" />
<include name="tomcat/jasper-runtime-1.0.jar" />
<include name="tomcat/jsp-api-2.0.jar" />
- <include name="tomcat/mx4j-jmx-1.1.jar" />
- <include name="tomcat/naming-common-1.0.jar" />
- <include name="tomcat/naming-factory-1.0.jar" />
- <include name="tomcat/naming-java-1.0.jar" />
- <include name="tomcat/naming-resources-1.0.jar" />
- <include name="tomcat/servlet-api-2.5.jar" />
- <include name="tomcat/servlet-api-2.4.jar" />
- <include name="tomcat/servlets-common-1.0.jar" />
- <include name="tomcat/servlets-default-1.0.jar" />
- <include name="tomcat/servlets-invoker-1.0.jar" />
- <include name="tomcat/tomcat-coyote-1.0.jar" />
- <include name="tomcat/tomcat-http11-1.0.jar" />
- <include name="tomcat/tomcat-jk2-2.1.jar" />
- <include name="tomcat/tomcat-util-5.1.jar" />
+ <!-- dependencies needed for JSP support in DevMode: END -->
+ <include name="apache/commons/commons-collections-3.2.1.jar" />
<!-- htmlunit dependencies not already included: BEGIN -->
<include name="apache/http/httpclient-4.1.2.jar" />
<include name="apache/http/httpcore-4.1.2.jar" />
@@ -131,33 +110,13 @@
<zipfileset src="${gwt.tools.lib}/jetty/jetty-6.1.11.jar" />
<zipfileset src="${gwt.tools.lib}/icu4j/4.4.2/icu4j.jar" />
<zipfileset src="${gwt.tools.lib}/protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/ant-launcher-1.6.5.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/catalina-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/catalina-optional-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/commons-beanutils-1.6.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/commons-collections-3.1.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/commons-digester-1.5.jar" />
+ <!-- dependencies needed for JSP support in DevMode: BEGIN -->
<zipfileset src="${gwt.tools.lib}/tomcat/commons-el-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/commons-logging-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/commons-modeler-1.1.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/jakarta-regexp-1.3.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/jasper-compiler-1.0.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/jasper-runtime-1.0.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/jsp-api-2.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/mx4j-jmx-1.1.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/naming-common-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/naming-factory-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/naming-java-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/naming-resources-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/servlet-api-2.5.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/servlet-api-2.4.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/servlets-common-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/servlets-default-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/servlets-invoker-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/tomcat-coyote-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/tomcat-http11-1.0.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/tomcat-jk2-2.1.jar" />
- <zipfileset src="${gwt.tools.lib}/tomcat/tomcat-util-5.1.jar" />
+ <!-- dependencies needed for JSP support in DevMode: END -->
+ <zipfileset src="${gwt.tools.lib}/apache/commons/commons-collections-3.2.1.jar" />
<!-- htmlunit dependencies not already included: BEGIN -->
<zipfileset src="${gwt.tools.lib}/apache/http/httpclient-4.1.2.jar" />
<zipfileset src="${gwt.tools.lib}/apache/http/httpcore-4.1.2.jar" />
@@ -220,7 +179,7 @@
<classpath>
<pathelement location="${gwt.tools.lib}/apache/ant-1.6.5.jar" />
<pathelement location="${gwt.tools.lib}/eclipse/jdt-3.4.2_r894.jar" />
- <pathelement location="${gwt.tools.lib}/tomcat/commons-collections-3.1.jar" />
+ <pathelement location="${gwt.tools.lib}/apache/commons/commons-collections-3.2.1.jar" />
<pathelement location="${gwt.tools.lib}/guava/guava-10.0.1/guava-10.0.1-rebased.jar" />
<pathelement location="${gwt.tools.lib}/jscomp/r1649/compiler-rebased.jar" />
</classpath>
diff --git a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
index 7c65f6e..914713d 100644
--- a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
+++ b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
@@ -63,7 +63,7 @@
}
});
- compilerThread.setName("GWTCompiler Thread");
+ compilerThread.setName("GWT Compiler Thread");
compilerThread.start();
// TODO(jat): create an app frame for loggerWindow
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
deleted file mode 100644
index ef2e4ea..0000000
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.dev;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.dev.CompileTaskRunner.CompileTask;
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.cfg.ModuleDefLoader;
-import com.google.gwt.dev.jjs.JJSOptions;
-import com.google.gwt.dev.jjs.PermutationResult;
-import com.google.gwt.dev.shell.CheckForUpdates;
-import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
-import com.google.gwt.dev.util.FileBackedObject;
-import com.google.gwt.dev.util.Util;
-import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
-import com.google.gwt.dev.util.arg.ArgHandlerOutDir;
-import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
-import com.google.gwt.util.tools.ToolBase;
-import com.google.gwt.util.tools.Utility;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.FutureTask;
-
-/**
- * The main executable entry point for the GWT Java to JavaScript compiler.
- *
- * @deprecated Use {@link Compiler} instead
- */
-@Deprecated
-public class GWTCompiler {
-
- static final class ArgProcessor extends PrecompileTaskArgProcessor {
- public ArgProcessor(LegacyCompilerOptions options) {
- super(options);
-
- registerHandler(new ArgHandlerOutDir(options));
-
- // Override the ArgHandlerWorkDirRequired in the super class.
- registerHandler(new ArgHandlerWorkDirOptional(options));
-
- registerHandler(new ArgHandlerLocalWorkers(options));
- }
-
- @Override
- protected String getName() {
- return GWTCompiler.class.getName();
- }
- }
-
- /**
- * Simple implementation of {@link LegacyCompilerOptions}.
- */
- public static class GWTCompilerOptionsImpl extends PrecompileTaskOptionsImpl
- implements LegacyCompilerOptions {
-
- private int localWorkers;
- private File outDir;
-
- public GWTCompilerOptionsImpl() {
- }
-
- public GWTCompilerOptionsImpl(LegacyCompilerOptions other) {
- copyFrom(other);
- }
-
- public void copyFrom(LegacyCompilerOptions other) {
- super.copyFrom(other);
- setLocalWorkers(other.getLocalWorkers());
- setOutDir(other.getOutDir());
- }
-
- @Override
- public int getLocalWorkers() {
- return localWorkers;
- }
-
- @Override
- public File getOutDir() {
- return outDir;
- }
-
- @Override
- public void setLocalWorkers(int localWorkers) {
- this.localWorkers = localWorkers;
- }
-
- @Override
- public void setOutDir(File outDir) {
- this.outDir = outDir;
- }
- }
-
- public static void main(String[] args) {
- ToolBase.legacyWarn(GWTCompiler.class, Compiler.class);
- SpeedTracerLogger.init();
- Event compileEvent = SpeedTracerLogger.start(CompilerEventType.COMPILE);
-
- /*
- * NOTE: main always exits with a call to System.exit to terminate any
- * non-daemon threads that were started in Generators. Typically, this is to
- * shutdown AWT related threads, since the contract for their termination is
- * still implementation-dependent.
- */
- final LegacyCompilerOptions options = new GWTCompilerOptionsImpl();
- boolean success = false;
- if (new ArgProcessor(options).processArgs(args)) {
- CompileTask task = new CompileTask() {
- @Override
- public boolean run(TreeLogger logger) throws UnableToCompleteException {
- FutureTask<UpdateResult> updater = null;
- if (!options.isUpdateCheckDisabled()) {
- updater = CheckForUpdates.checkForUpdatesInBackgroundThread(logger,
- CheckForUpdates.ONE_DAY);
- }
- boolean success = new GWTCompiler(options).run(logger);
- if (success) {
- CheckForUpdates.logUpdateAvailable(logger, updater);
- }
- return success;
- }
- };
- if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
- // Exit w/ success code.
- success = true;
- }
- }
-
- compileEvent.end();
- // Exit w/ non-success code.
- System.exit(success ? 0 : 1);
- }
-
- private final GWTCompilerOptionsImpl options;
-
- public GWTCompiler(LegacyCompilerOptions options) {
- this.options = new GWTCompilerOptionsImpl(options);
- }
-
- /**
- * Compiles the set of modules specified in the options.
- */
- public boolean run(TreeLogger logger) throws UnableToCompleteException {
- ModuleDef[] modules = new ModuleDef[options.getModuleNames().size()];
- int i = 0;
- for (String moduleName : options.getModuleNames()) {
- modules[i++] = ModuleDefLoader.loadFromClassPath(logger, moduleName, true);
- }
- return run(logger, modules);
- }
-
- /**
- * Compiles a specific set of modules.
- */
- public boolean run(TreeLogger logger, ModuleDef... modules)
- throws UnableToCompleteException {
- Event compileEvent = SpeedTracerLogger.start(CompilerEventType.COMPILE);
- boolean tempWorkDir = false;
- try {
- if (options.getWorkDir() == null) {
- options.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc"));
- tempWorkDir = true;
- }
-
- for (ModuleDef module : modules) {
- String moduleName = module.getName();
-
- if (options.isValidateOnly()) {
- if (!Precompile.validate(logger, options, module, options.getGenDir())) {
- return false;
- }
- } else {
- long compileStart = System.currentTimeMillis();
- logger = logger.branch(TreeLogger.INFO, "Compiling module "
- + moduleName);
-
- // Optimize early since permutation compiles will run in process.
- options.setOptimizePrecompile(true);
- Precompilation precompilation = Precompile.precompile(logger,
- options, module, options.getGenDir());
-
- if (precompilation == null) {
- return false;
- }
- Permutation[] allPerms = precompilation.getPermutations();
- List<FileBackedObject<PermutationResult>> resultFiles = CompilePerms.makeResultFiles(
- options.getCompilerWorkDir(moduleName), allPerms);
- CompilePerms.compile(logger, precompilation, allPerms,
- options.getLocalWorkers(), resultFiles);
-
- ArtifactSet generatedArtifacts = precompilation.getGeneratedArtifacts();
- JJSOptions precompileOptions = precompilation.getUnifiedAst().getOptions();
-
- precompilation = null; // No longer needed, so save the memory
-
- Link.legacyLink(logger.branch(TreeLogger.TRACE, "Linking into "
- + options.getOutDir().getPath()), module, generatedArtifacts,
- allPerms, resultFiles, options.getOutDir(), precompileOptions);
-
- long compileDone = System.currentTimeMillis();
- long delta = compileDone - compileStart;
- if (logger.isLoggable(TreeLogger.INFO)) {
- logger.log(TreeLogger.INFO, "Compilation succeeded -- "
- + String.format("%.3f", delta / 1000d) + "s");
- }
- }
- }
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Unable to create compiler work directory",
- e);
- return false;
- } finally {
- compileEvent.end();
- if (tempWorkDir) {
- Util.recursiveDelete(options.getWorkDir(), false);
- }
- }
- return true;
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/GWTShell.java b/dev/core/src/com/google/gwt/dev/GWTShell.java
deleted file mode 100644
index 77339ff..0000000
--- a/dev/core/src/com/google/gwt/dev/GWTShell.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.dev;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
-import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.shell.WorkDirs;
-import com.google.gwt.dev.shell.tomcat.EmbeddedTomcatServer;
-import com.google.gwt.dev.util.OutputFileSetOnDirectory;
-import com.google.gwt.dev.util.arg.ArgHandlerDisableUpdateCheck;
-import com.google.gwt.dev.util.arg.ArgHandlerOutDir;
-import com.google.gwt.util.tools.ArgHandlerExtra;
-
-import java.io.File;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * The main executable class for the hosted mode shell.
- */
-@Deprecated
-public class GWTShell extends DevModeBase {
-
- /**
- * Handles the list of startup urls that can be passed at the end of the
- * command line.
- */
- protected static class ArgHandlerStartupURLsExtra extends ArgHandlerExtra {
-
- private final OptionStartupURLs options;
-
- public ArgHandlerStartupURLsExtra(OptionStartupURLs options) {
- this.options = options;
- }
-
- @Override
- public boolean addExtraArg(String arg) {
- options.addStartupURL(arg);
- return true;
- }
-
- @Override
- public String getPurpose() {
- return "Automatically launches the specified URL";
- }
-
- @Override
- public String[] getTagArgs() {
- return new String[] {"url"};
- }
- }
-
- /**
- * The GWTShell argument processor.
- */
- protected static class ArgProcessor extends DevModeBase.ArgProcessor {
- public ArgProcessor(ShellOptionsImpl options, boolean forceServer,
- boolean noURLs) {
- super(options, forceServer);
- if (!noURLs) {
- registerHandler(new ArgHandlerStartupURLsExtra(options));
- }
- registerHandler(new ArgHandlerOutDir(options));
- registerHandler(new ArgHandlerDisableUpdateCheck(options));
- }
-
- @Override
- protected String getName() {
- return GWTShell.class.getName();
- }
- }
-
- /**
- * Concrete class to implement all shell options.
- */
- protected static class ShellOptionsImpl extends HostedModeBaseOptionsImpl
- implements WorkDirs, LegacyCompilerOptions {
- private int localWorkers;
- private File outDir;
-
- public File getCompilerOutputDir(ModuleDef moduleDef) {
- return new File(getOutDir(), moduleDef.getName());
- }
-
- public int getLocalWorkers() {
- return localWorkers;
- }
-
- public File getOutDir() {
- return outDir;
- }
-
- public File getShellPublicGenDir(ModuleDef moduleDef) {
- File moduleWorkDir = new File(getWorkDir(), moduleDef.getName());
- return new File(moduleWorkDir, "public");
- }
-
- @Override
- public File getWorkDir() {
- return new File(getOutDir(), ".gwt-tmp");
- }
-
- public void setLocalWorkers(int localWorkers) {
- this.localWorkers = localWorkers;
- }
-
- public void setOutDir(File outDir) {
- this.outDir = outDir;
- }
- }
-
- public static String checkHost(String hostUnderConsideration,
- Set<String> hosts) {
- hostUnderConsideration = hostUnderConsideration.toLowerCase(Locale.ENGLISH);
- for (String rule : hosts) {
- // match on lowercased regex
- if (hostUnderConsideration.matches(".*" + rule + ".*")) {
- return rule;
- }
- }
- return null;
- }
-
- public static String computeHostRegex(String url) {
- // the entire URL up to the first slash not prefixed by a slash or colon.
- String raw = url.split("(?<![:/])/")[0];
- // escape the dots and put a begin line specifier on the result
- return "^" + raw.replaceAll("[.]", "[.]");
- }
-
- public static String formatRules(Set<String> invalidHttpHosts) {
- StringBuffer out = new StringBuffer();
- for (String rule : invalidHttpHosts) {
- out.append(rule);
- out.append(" ");
- }
- return out.toString();
- }
-
- public static void main(String[] args) {
- /*
- * NOTE: main always exits with a call to System.exit to terminate any
- * non-daemon threads that were started in Generators. Typically, this is to
- * shutdown AWT related threads, since the contract for their termination is
- * still implementation-dependent.
- */
- GWTShell gwtShell = new GWTShell();
- ArgProcessor argProcessor = new ArgProcessor(gwtShell.options, false, false);
- if (argProcessor.processArgs(args)) {
- gwtShell.run();
- // Exit w/ success code.
- System.exit(0);
- }
- // Exit w/ non-success code.
- System.exit(-1);
- }
-
- /**
- * Hiding super field because it's actually the same object, just with a
- * stronger type.
- */
- @SuppressWarnings("hiding")
- protected final ShellOptionsImpl options = (ShellOptionsImpl) super.options;
-
- protected File outDir;
-
- @SuppressWarnings("unused")
- public void restartServer(TreeLogger logger) throws UnableToCompleteException {
- // Unimplemented.
- }
-
- @Override
- protected HostedModeBaseOptions createOptions() {
- return new ShellOptionsImpl();
- }
-
- @Override
- protected void doShutDownServer() {
- // Stop the HTTP server.
- //
- EmbeddedTomcatServer.stop();
- }
-
- @Override
- protected boolean doStartup() {
- File persistentCacheDir = new File(options.getWorkDir(), "gwt-unitCache");
- return super.doStartup(persistentCacheDir);
- }
-
- @Override
- protected int doStartUpServer() {
- // TODO(jat): find a safe way to get an icon for Tomcat
- TreeLogger logger = ui.getWebServerLogger("Tomcat", null);
- // TODO(bruce): make tomcat work in terms of the modular launcher
- String whyFailed = EmbeddedTomcatServer.start(isHeadless() ? getTopLogger()
- : logger, getPort(), options, shouldAutoGenerateResources());
-
- if (whyFailed != null) {
- getTopLogger().log(TreeLogger.ERROR, "Starting Tomcat: " + whyFailed);
- return -1;
- }
- return EmbeddedTomcatServer.getPort();
- }
-
- @Override
- protected synchronized void produceOutput(TreeLogger logger,
- StandardLinkerContext linkerStack, ArtifactSet artifacts,
- ModuleDef module, boolean isRelink) throws UnableToCompleteException {
- /*
- * Legacy: in GWTShell we only copy generated artifacts into the public gen
- * folder. Public files and "autogen" files have special handling (that
- * needs to die).
- */
- if (isRelink) {
- File outputDir = options.getShellPublicGenDir(module);
- outputDir.mkdirs();
- OutputFileSetOnDirectory outFileSet = new OutputFileSetOnDirectory(
- outputDir, "");
- linkerStack.produceOutput(logger, artifacts, Visibility.Public,
- outFileSet);
- outFileSet.close();
- }
- }
-
- protected boolean shouldAutoGenerateResources() {
- return true;
- }
-
- @Override
- protected void warnAboutNoStartupUrls() {
- getTopLogger().log(TreeLogger.WARN,
- "No startup URLs were supplied -- add them to the end of the GWTShell"
- + " command line");
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
index 8d972e9..378ab1a 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -466,9 +466,9 @@
}
/**
- * For convenience in hosted mode, servlets can be automatically loaded and
- * delegated to via {@link com.google.gwt.dev.shell.GWTShellServlet}. If a
- * servlet is already mapped to the specified path, it is replaced.
+ * For convenience in unit tests, servlets can be automatically loaded and
+ * mapped in the embedded web server. If a servlet is already mapped to the
+ * specified path, it is replaced.
*
* @param path the url path at which the servlet resides
* @param servletClassName the name of the servlet to publish
diff --git a/dev/core/src/com/google/gwt/dev/etc/tomcat/conf/web.xml b/dev/core/src/com/google/gwt/dev/etc/tomcat/conf/web.xml
deleted file mode 100644
index fee85f3..0000000
--- a/dev/core/src/com/google/gwt/dev/etc/tomcat/conf/web.xml
+++ /dev/null
@@ -1,566 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!-- A tweaked version of the default Tomcat web.xml to remove everything except the stuff we want to use -->
-<web-app version="2.4">
-
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
-
- <mime-mapping>
- <extension>abs</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ai</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aif</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aifc</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aiff</extension>
- <mime-type>audio/x-aiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>aim</extension>
- <mime-type>application/x-aim</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>art</extension>
- <mime-type>image/x-jg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asf</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>asx</extension>
- <mime-type>video/x-ms-asf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>au</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avi</extension>
- <mime-type>video/x-msvideo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>avx</extension>
- <mime-type>video/x-rad-screenplay</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bcpio</extension>
- <mime-type>application/x-bcpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bin</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>bmp</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>body</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cdf</extension>
- <mime-type>application/x-cdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cer</extension>
- <mime-type>application/x-x509-ca-cert</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>class</extension>
- <mime-type>application/java</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>cpio</extension>
- <mime-type>application/x-cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>csh</extension>
- <mime-type>application/x-csh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>css</extension>
- <mime-type>text/css</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dib</extension>
- <mime-type>image/bmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>doc</extension>
- <mime-type>application/msword</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dtd</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dv</extension>
- <mime-type>video/x-dv</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>dvi</extension>
- <mime-type>application/x-dvi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>eps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>etx</extension>
- <mime-type>text/x-setext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>exe</extension>
- <mime-type>application/octet-stream</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gif</extension>
- <mime-type>image/gif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gtar</extension>
- <mime-type>application/x-gtar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>gz</extension>
- <mime-type>application/x-gzip</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hdf</extension>
- <mime-type>application/x-hdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htc</extension>
- <mime-type>text/x-component</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>htm</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>html</extension>
- <mime-type>text/html</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>hqx</extension>
- <mime-type>application/mac-binhex40</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ief</extension>
- <mime-type>image/ief</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jad</extension>
- <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jar</extension>
- <mime-type>application/java-archive</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>java</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jnlp</extension>
- <mime-type>application/x-java-jnlp-file</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpe</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpeg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jpg</extension>
- <mime-type>image/jpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>js</extension>
- <mime-type>text/javascript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jsf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>jspf</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>kar</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>latex</extension>
- <mime-type>application/x-latex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>m3u</extension>
- <mime-type>audio/x-mpegurl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mac</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>man</extension>
- <mime-type>application/x-troff-man</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>me</extension>
- <mime-type>application/x-troff-me</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mid</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>midi</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mif</extension>
- <mime-type>application/x-mif</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mov</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>movie</extension>
- <mime-type>video/x-sgi-movie</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp1</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp2</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mp3</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpa</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpe</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpeg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpega</extension>
- <mime-type>audio/x-mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpg</extension>
- <mime-type>video/mpeg</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>mpv2</extension>
- <mime-type>video/mpeg2</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ms</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>nc</extension>
- <mime-type>application/x-netcdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>oda</extension>
- <mime-type>application/oda</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pbm</extension>
- <mime-type>image/x-portable-bitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pct</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pdf</extension>
- <mime-type>application/pdf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pgm</extension>
- <mime-type>image/x-portable-graymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pic</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pict</extension>
- <mime-type>image/pict</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pls</extension>
- <mime-type>audio/x-scpls</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>png</extension>
- <mime-type>image/png</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnm</extension>
- <mime-type>image/x-portable-anymap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>pnt</extension>
- <mime-type>image/x-macpaint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppm</extension>
- <mime-type>image/x-portable-pixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ppt</extension>
- <mime-type>application/powerpoint</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ps</extension>
- <mime-type>application/postscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>psd</extension>
- <mime-type>image/x-photoshop</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qt</extension>
- <mime-type>video/quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qti</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>qtif</extension>
- <mime-type>image/x-quicktime</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ras</extension>
- <mime-type>image/x-cmu-raster</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rgb</extension>
- <mime-type>image/x-rgb</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rm</extension>
- <mime-type>application/vnd.rn-realmedia</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>roff</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtf</extension>
- <mime-type>application/rtf</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>rtx</extension>
- <mime-type>text/richtext</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sh</extension>
- <mime-type>application/x-sh</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>shar</extension>
- <mime-type>application/x-shar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>smf</extension>
- <mime-type>audio/x-midi</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sit</extension>
- <mime-type>application/x-stuffit</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>snd</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>src</extension>
- <mime-type>application/x-wais-source</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4cpio</extension>
- <mime-type>application/x-sv4cpio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>sv4crc</extension>
- <mime-type>application/x-sv4crc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>swf</extension>
- <mime-type>application/x-shockwave-flash</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>t</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tar</extension>
- <mime-type>application/x-tar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tcl</extension>
- <mime-type>application/x-tcl</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tex</extension>
- <mime-type>application/x-tex</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texi</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>texinfo</extension>
- <mime-type>application/x-texinfo</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tif</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tiff</extension>
- <mime-type>image/tiff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tr</extension>
- <mime-type>application/x-troff</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>tsv</extension>
- <mime-type>text/tab-separated-values</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>txt</extension>
- <mime-type>text/plain</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ulw</extension>
- <mime-type>audio/basic</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>ustar</extension>
- <mime-type>application/x-ustar</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xbm</extension>
- <mime-type>image/x-xbitmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xht</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xhtml</extension>
- <mime-type>application/xhtml+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xml</extension>
- <mime-type>text/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xpm</extension>
- <mime-type>image/x-xpixmap</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xsl</extension>
- <mime-type>text/xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>xwd</extension>
- <mime-type>image/x-xwindowdump</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wav</extension>
- <mime-type>audio/x-wav</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svg</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>svgz</extension>
- <mime-type>image/svg+xml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>vsd</extension>
- <mime-type>application/x-visio</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Wireless Bitmap -->
- <extension>wbmp</extension>
- <mime-type>image/vnd.wap.wbmp</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Source -->
- <extension>wml</extension>
- <mime-type>text/vnd.wap.wml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML -->
- <extension>wmlc</extension>
- <mime-type>application/vnd.wap.wmlc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- WML Script Source -->
- <extension>wmls</extension>
- <mime-type>text/vnd.wap.wmlscript</mime-type>
- </mime-mapping>
- <mime-mapping>
- <!-- Compiled WML Script -->
- <extension>wmlscriptc</extension>
- <mime-type>application/vnd.wap.wmlscriptc</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>wrl</extension>
- <mime-type>x-world/x-vrml</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>Z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>z</extension>
- <mime-type>application/x-compress</mime-type>
- </mime-mapping>
- <mime-mapping>
- <extension>zip</extension>
- <mime-type>application/zip</mime-type>
- </mime-mapping>
-</web-app>
diff --git a/dev/core/src/com/google/gwt/dev/etc/tomcat/webapps/ROOT/WEB-INF/web.xml b/dev/core/src/com/google/gwt/dev/etc/tomcat/webapps/ROOT/WEB-INF/web.xml
deleted file mode 100644
index e600b2f..0000000
--- a/dev/core/src/com/google/gwt/dev/etc/tomcat/webapps/ROOT/WEB-INF/web.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app>
-
- <servlet>
- <servlet-name>shell</servlet-name>
- <servlet-class>com.google.gwt.dev.shell.GWTShellServlet</servlet-class>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>shell</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
-</web-app>
diff --git a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
deleted file mode 100644
index 9e7ead7..0000000
--- a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
+++ /dev/null
@@ -1,991 +0,0 @@
-/*
- * 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.dev.shell;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.core.ext.linker.impl.HostedModeLinker;
-import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.cfg.ModuleDefLoader;
-import com.google.gwt.dev.jjs.JJSOptionsImpl;
-import com.google.gwt.dev.resource.Resource;
-import com.google.gwt.dev.shell.log.ServletContextTreeLogger;
-import com.google.gwt.dev.util.HttpHeaders;
-import com.google.gwt.dev.util.Util;
-import com.google.gwt.thirdparty.guava.common.collect.MapMaker;
-import com.google.gwt.util.tools.Utility;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Built-in servlet for convenient access to the public path of a specified
- * module.
- */
-public class GWTShellServlet extends HttpServlet {
-
- private static class RequestParts {
- public final String moduleName;
-
- public final String partialPath;
-
- public RequestParts(HttpServletRequest request)
- throws UnableToCompleteException {
- String pathInfo = request.getPathInfo();
- if (pathInfo != null) {
- int slash = pathInfo.indexOf('/', 1);
- if (slash != -1) {
- moduleName = pathInfo.substring(1, slash);
- partialPath = pathInfo.substring(slash + 1);
- return;
- } else {
- moduleName = pathInfo.substring(1);
- partialPath = null;
- return;
- }
- }
- throw new UnableToCompleteException();
- }
- }
-
- /**
- * This the default cache time in seconds for files that aren't either
- * *.cache.*, *.nocache.*.
- */
- private static final int DEFAULT_CACHE_SECONDS = 5;
-
- private static final String XHTML_MIME_TYPE = "application/xhtml+xml";
-
- /**
- * Must keep only weak references to ModuleDefs else we permanently pin them.
- */
- private final Map<String, ModuleDef> loadedModulesByName = new MapMaker().weakValues().makeMap();
-
- /**
- * The lifetime of the module pins the lifetime of the associated servlet;
- * this is because the loaded servlet has a weak backRef to its live module
- * through its context. When the module dies, the servlet needs to die also.
- */
- private final Map<ModuleDef, Map<String, HttpServlet>> loadedServletsByModuleAndClassName =
- new MapMaker().weakKeys().makeMap();
-
- private final Map<String, String> mimeTypes = new HashMap<String, String>();
-
- /**
- * Only for backwards compatibility. Shouldn't we remove this now?
- */
- private final Map<String, ModuleDef> modulesByServletPath = new MapMaker().weakValues().makeMap();
-
- private int nextRequestId;
-
- private final Object requestIdLock = new Object();
-
- private TreeLogger topLogger;
-
- private WorkDirs workDirs;
-
- public GWTShellServlet() {
- initMimeTypes();
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processFileRequest(request, response);
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processFileRequest(request, response);
- }
-
- protected void processFileRequest(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
-
- String pathInfo = request.getPathInfo();
- if (pathInfo.length() == 0 || pathInfo.equals("/")) {
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.println("<html><body><basefont face='arial'>");
- writer.println("To launch an application, specify a URL of the form <code>/<i>module</i>/<i>file.html</i></code>");
- writer.println("</body></html>");
- return;
- }
-
- TreeLogger logger = getLogger();
-
- // Parse the request assuming it is module/resource.
- //
- RequestParts parts;
- try {
- parts = new RequestParts(request);
- } catch (UnableToCompleteException e) {
- sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND,
- "Don't know what to do with this URL: '" + pathInfo + "'");
- return;
- }
-
- String partialPath = parts.partialPath;
- String moduleName = parts.moduleName;
-
- // If the module is renamed, substitute the renamed module name
- ModuleDef moduleDef = loadedModulesByName.get(moduleName);
- if (moduleDef != null) {
- moduleName = moduleDef.getName();
- }
-
- if (partialPath == null) {
- // Redir back to the same URL but ending with a slash.
- //
- response.sendRedirect(moduleName + "/");
- return;
- } else if (partialPath.length() > 0) {
- // Both the module name and a resource.
- //
- doGetPublicFile(request, response, logger, partialPath, moduleName);
- return;
- } else {
- // Was just the module name, ending with a slash.
- //
- doGetModule(request, response, logger, parts);
- return;
- }
- }
-
- @Override
- protected void service(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
-
- TreeLogger logger = getLogger();
- int id = allocateRequestId();
- if (logger.isLoggable(TreeLogger.TRACE)) {
- StringBuffer url = request.getRequestURL();
-
- // Branch the logger in case we decide to log more below.
- logger = logger.branch(TreeLogger.TRACE, "Request " + id + ": " + url,
- null);
- }
-
- String servletClassName = null;
- ModuleDef moduleDef = null;
-
- try {
- // Attempt to split the URL into module/path, which we'll use to see
- // if we can map the request to a module's servlet.
- RequestParts parts = new RequestParts(request);
-
- if ("favicon.ico".equalsIgnoreCase(parts.moduleName)) {
- sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND,
- "Icon not available");
- return;
- }
-
- // See if the request references a module we know.
- moduleDef = getModuleDef(logger, parts.moduleName);
- if (moduleDef != null) {
- // Okay, we know this module. Do we know this servlet path?
- // It is right to prepend the slash because (1) ModuleDefSchema requires
- // every servlet path to begin with a slash and (2) RequestParts always
- // rips off the leading slash.
- String servletPath = "/" + parts.partialPath;
- servletClassName = moduleDef.findServletForPath(servletPath);
-
- // Fall-through below, where we check servletClassName.
- } else {
- // Fall-through below, where we check servletClassName.
- }
- } catch (UnableToCompleteException e) {
- // Do nothing, since it was speculative anyway.
- }
-
- // BEGIN BACKWARD COMPATIBILITY
- if (servletClassName == null) {
- // Try to map a bare path that isn't preceded by the module name.
- // This is no longer the recommended practice, so we warn.
- String path = request.getPathInfo();
- moduleDef = modulesByServletPath.get(path);
- if (moduleDef != null) {
- // See if there is a servlet we can delegate to for the given url.
- servletClassName = moduleDef.findServletForPath(path);
-
- if (servletClassName != null) {
- TreeLogger branch = logger.branch(TreeLogger.WARN,
- "Use of deprecated hosted mode servlet path mapping", null);
- branch.log(
- TreeLogger.WARN,
- "The client code is invoking the servlet with a URL that is not module-relative: "
- + path, null);
- branch.log(
- TreeLogger.WARN,
- "Prepend GWT.getModuleBaseURL() to the URL in client code to create a module-relative URL: /"
- + moduleDef.getName() + path, null);
- branch.log(
- TreeLogger.WARN,
- "Using module-relative URLs ensures correct URL-independent behavior in external servlet containers",
- null);
- }
-
- // Fall-through below, where we check servletClassName.
- } else {
- // Fall-through below, where we check servletClassName.
- }
- }
- // END BACKWARD COMPATIBILITY
-
- // Load/get the servlet if we found one.
- if (servletClassName != null) {
- HttpServlet delegatee = tryGetOrLoadServlet(logger, moduleDef,
- servletClassName);
- if (delegatee == null) {
- logger.log(TreeLogger.ERROR, "Unable to dispatch request", null);
- sendErrorResponse(response,
- HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
- "Unable to find/load mapped servlet class '" + servletClassName
- + "'");
- return;
- }
-
- // Delegate everything to the downstream servlet and we're done.
- delegatee.service(request, response);
- } else {
- // Use normal default processing on this request, since we couldn't
- // recognize it as anything special.
- super.service(request, response);
- }
- }
-
- private int allocateRequestId() {
- synchronized (requestIdLock) {
- return nextRequestId++;
- }
- }
-
- /**
- * Handle auto-generated resources.
- *
- * @return <code>true</code> if a resource was generated
- */
- private boolean autoGenerateResources(HttpServletRequest request,
- HttpServletResponse response, TreeLogger logger, String partialPath,
- String moduleName) throws IOException {
-
- if (partialPath.equals(moduleName + ".nocache.js")) {
- if (request.getParameter("compiled") == null) {
- // Generate the .js file.
- try {
- String js = genSelectionScript(logger, moduleName);
- setResponseCacheHeaders(response, 0); // do not cache selection script
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentType("text/javascript");
- response.getWriter().println(js);
- return true;
- } catch (UnableToCompleteException e) {
- // The error will have already been logged. Continue, since this could
- // actually be a request for a static file that happens to have an
- // unfortunately confusing name.
- }
- }
- } else if (partialPath.equals("hosted.html")) {
- String html = HostedModeLinker.getHostedHtml();
- setResponseCacheHeaders(response, DEFAULT_CACHE_SECONDS);
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentType("text/html");
- response.getWriter().println(html);
- return true;
- }
-
- return false;
- }
-
- private void doGetModule(HttpServletRequest request,
- HttpServletResponse response, TreeLogger logger, RequestParts parts)
- throws IOException {
-
- // Generate a generic empty host page.
- //
- String msg = "The development shell servlet received a request to generate a host page for module '"
- + parts.moduleName + "' ";
-
- logger = logger.branch(TreeLogger.TRACE, msg, null);
-
- try {
- // Try to load the module just to make sure it'll work.
- getModuleDef(logger, parts.moduleName);
- } catch (UnableToCompleteException e) {
- sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND,
- "Unable to find/load module '" + Util.escapeXml(parts.moduleName)
- + "' (see server log for details)");
- return;
- }
-
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.println("<html><head>");
- writer.print("<script language='javascript' src='");
- writer.print(parts.moduleName);
- writer.println(".nocache.js'></script>");
-
- // Create a property for each query param.
- Map<String, String[]> params = getParameterMap(request);
- for (Map.Entry<String, String[]> entry : params.entrySet()) {
- String[] values = entry.getValue();
- if (values.length > 0) {
- writer.print("<meta name='gwt:property' content='");
- writer.print(entry.getKey());
- writer.print("=");
- writer.print(values[values.length - 1]);
- writer.println("'>");
- }
- }
-
- writer.println("</head><body>");
- writer.println("<iframe src=\"javascript:''\" id='__gwt_historyFrame' "
- + "style='position:absolute;width:0;height:0;border:0'></iframe>");
- writer.println("<noscript>");
- writer.println(" <div style=\"width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif\">");
- writer.println(" Your web browser must have JavaScript enabled");
- writer.println(" in order for this application to display correctly.");
- writer.println(" </div>");
- writer.println("</noscript>");
- writer.println("</body></html>");
-
- // Done.
- }
-
- /**
- * Fetch a file and return it as the HTTP response, setting the cache-related
- * headers according to the name of the file (see
- * {@link #getCacheTime(String)}). This function honors If-Modified-Since to
- * minimize the impact of limiting caching of files for development.
- *
- * @param request the HTTP request
- * @param response the HTTP response
- * @param logger a TreeLogger to use for debug output
- * @param partialPath the path within the module
- * @param moduleName the name of the module
- * @throws IOException
- */
- @SuppressWarnings("deprecation")
- private void doGetPublicFile(HttpServletRequest request,
- HttpServletResponse response, TreeLogger logger, String partialPath,
- String moduleName) throws IOException {
-
- // Create a logger branch for this request.
- logger = logger.branch(TreeLogger.TRACE,
- "The development shell servlet received a request for '"
- + partialPath + "' in module '" + moduleName + ".gwt.xml' ", null);
-
- // Handle auto-generation of resources.
- if (shouldAutoGenerateResources()) {
- if (autoGenerateResources(request, response, logger, partialPath,
- moduleName)) {
- return;
- }
- }
-
- URL foundResource = null;
- try {
- // Look for the requested file on the public path.
- //
- ModuleDef moduleDef = getModuleDef(logger, moduleName);
- if (shouldAutoGenerateResources()) {
- Resource publicResource = moduleDef.findPublicFile(partialPath);
- if (publicResource != null) {
- foundResource = publicResource.getURL();
- }
-
- if (foundResource == null) {
- // Look for public generated files
- File shellDir = getShellWorkDirs().getShellPublicGenDir(moduleDef);
- File requestedFile = new File(shellDir, partialPath);
- if (requestedFile.exists()) {
- try {
- foundResource = requestedFile.toURI().toURL();
- } catch (MalformedURLException e) {
- // ignore since it was speculative anyway
- }
- }
- }
- }
-
- /*
- * If the user is coming from compiled web-mode, check the linker output
- * directory for the real bootstrap file.
- */
- if (foundResource == null) {
- File moduleDir = getShellWorkDirs().getCompilerOutputDir(moduleDef);
- File requestedFile = new File(moduleDir, partialPath);
- if (requestedFile.exists()) {
- try {
- foundResource = requestedFile.toURI().toURL();
- } catch (MalformedURLException e) {
- // ignore since it was speculative anyway
- }
- }
- }
-
- if (foundResource == null) {
- String msg;
- if ("gwt.js".equals(partialPath)) {
- msg = "Loading the old 'gwt.js' bootstrap script is no longer supported; please load '"
- + moduleName + ".nocache.js' directly";
- } else {
- msg = "Resource not found: " + partialPath + "; "
- + "(could a file be missing from the public path or a <servlet> "
- + "tag misconfigured in module " + moduleName + ".gwt.xml ?)";
- }
- logger.log(TreeLogger.WARN, msg, null);
- throw new UnableToCompleteException();
- }
- } catch (UnableToCompleteException e) {
- sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND,
- "Cannot find resource '" + partialPath
- + "' in the public path of module '" + moduleName + "'");
- return;
- }
-
- // Get the MIME type.
- String path = foundResource.toExternalForm();
- String mimeType = null;
- try {
- mimeType = getServletContext().getMimeType(path);
- } catch (UnsupportedOperationException e) {
- // Certain minimalist servlet containers throw this.
- // Fall through to guess the type.
- }
-
- if (mimeType == null) {
- mimeType = guessMimeType(path);
- if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE, "Guessed MIME type '" + mimeType + "'", null);
- }
- }
-
- maybeIssueXhtmlWarning(logger, mimeType, partialPath);
-
- long cacheSeconds = getCacheTime(path);
-
- InputStream is = null;
- try {
- // Check for up-to-datedness.
- URLConnection conn = foundResource.openConnection();
- long lastModified = conn.getLastModified();
- if (isNotModified(request, lastModified)) {
- response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- setResponseCacheHeaders(response, cacheSeconds);
- return;
- }
-
- // Set up headers to really send it.
- response.setStatus(HttpServletResponse.SC_OK);
- long now = new Date().getTime();
- response.setHeader(HttpHeaders.DATE,
- HttpHeaders.toInternetDateFormat(now));
- response.setContentType(mimeType);
- String lastModifiedStr = HttpHeaders.toInternetDateFormat(lastModified);
- response.setHeader(HttpHeaders.LAST_MODIFIED, lastModifiedStr);
-
- // Expiration header. Either immediately stale (requiring an
- // "If-Modified-Since") or infinitely cacheable (not requiring even a
- // freshness check).
- setResponseCacheHeaders(response, cacheSeconds);
-
- // Content length.
- int contentLength = conn.getContentLength();
- if (contentLength >= 0) {
- response.setHeader(HttpHeaders.CONTENT_LENGTH,
- Integer.toString(contentLength));
- }
-
- // Send the bytes.
- is = conn.getInputStream();
- streamOut(is, response.getOutputStream(), 1024 * 8);
- } finally {
- Utility.close(is);
- }
- }
-
- /**
- * Generates a module.js file on the fly. Note that the nocache file that is
- * generated that can only be used for hosted mode. It cannot produce a web
- * mode version, since this servlet doesn't know strong names, since by
- * definition of "hosted mode" JavaScript hasn't been compiled at this point.
- */
- private String genSelectionScript(TreeLogger logger, String moduleName)
- throws UnableToCompleteException {
- if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE,
- "Generating a script selection script for module " + moduleName);
- }
- ModuleDef module = getModuleDef(logger, moduleName);
- StandardLinkerContext context = new StandardLinkerContext(logger, module,
- new JJSOptionsImpl());
- ArtifactSet artifacts = context.getArtifactsForPublicResources(logger,
- module);
- HostedModeLinker linker = new HostedModeLinker();
- return linker.generateSelectionScript(logger, context, artifacts);
- }
-
- /**
- * Get the length of time a given file should be cacheable. If the path
- * contains *.nocache.*, it is never cacheable; if it contains *.cache.*, it
- * is infinitely cacheable; anything else gets a default time.
- *
- * @return cache time in seconds, or 0 if the file is not cacheable at all
- */
- private long getCacheTime(String path) {
- int lastDot = path.lastIndexOf('.');
- if (lastDot >= 0) {
- String prefix = path.substring(0, lastDot);
- if (prefix.endsWith(".cache")) {
- // RFC2616 says to never give a cache time of more than a year
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
- return HttpHeaders.SEC_YR;
- } else if (prefix.endsWith(".nocache")) {
- return 0;
- }
- }
- return DEFAULT_CACHE_SECONDS;
- }
-
- private synchronized TreeLogger getLogger() {
- if (topLogger == null) {
- ServletContext servletContext = getServletContext();
- final String attr = "com.google.gwt.dev.shell.logger";
- topLogger = (TreeLogger) servletContext.getAttribute(attr);
- if (topLogger == null) {
- // No shell available, so wrap the regular servlet context logger.
- //
- topLogger = new ServletContextTreeLogger(servletContext);
- }
- }
- return topLogger;
- }
-
- /**
- * We don't actually log this on purpose since the client does anyway.
- */
- private ModuleDef getModuleDef(TreeLogger logger, String moduleName)
- throws UnableToCompleteException {
- synchronized (loadedModulesByName) {
- ModuleDef moduleDef = loadedModulesByName.get(moduleName);
- if (moduleDef == null) {
- moduleDef = ModuleDefLoader.loadFromClassPath(logger, moduleName, false);
- loadedModulesByName.put(moduleName, moduleDef);
- loadedModulesByName.put(moduleDef.getName(), moduleDef);
-
- // BEGIN BACKWARD COMPATIBILITY
- // The following map of servlet path to module is included only
- // for backward-compatibility. We are going to remove this functionality
- // when we go out of beta. The new behavior is that the client should
- // specify the module name as part of the URL and construct it using
- // getModuleBaseURL().
- String[] servletPaths = moduleDef.getServletPaths();
- for (int i = 0; i < servletPaths.length; i++) {
- modulesByServletPath.put(servletPaths[i], moduleDef);
- }
- // END BACKWARD COMPATIBILITY
- }
- return moduleDef;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Map<String, String[]> getParameterMap(HttpServletRequest request) {
- return request.getParameterMap();
- }
-
- private synchronized WorkDirs getShellWorkDirs() {
- if (workDirs == null) {
- ServletContext servletContext = getServletContext();
- final String attr = "com.google.gwt.dev.shell.workdirs";
- workDirs = (WorkDirs) servletContext.getAttribute(attr);
- assert (workDirs != null);
- }
- return workDirs;
- }
-
- private String guessMimeType(String fullPath) {
- int dot = fullPath.lastIndexOf('.');
- if (dot != -1) {
- String ext = fullPath.substring(dot + 1);
- String mimeType = mimeTypes.get(ext);
- if (mimeType != null) {
- return mimeType;
- }
-
- // Otherwise, fall through.
- //
- }
-
- // Last resort.
- //
- return "application/octet-stream";
- }
-
- private void initMimeTypes() {
- mimeTypes.put("abs", "audio/x-mpeg");
- mimeTypes.put("ai", "application/postscript");
- mimeTypes.put("aif", "audio/x-aiff");
- mimeTypes.put("aifc", "audio/x-aiff");
- mimeTypes.put("aiff", "audio/x-aiff");
- mimeTypes.put("aim", "application/x-aim");
- mimeTypes.put("art", "image/x-jg");
- mimeTypes.put("asf", "video/x-ms-asf");
- mimeTypes.put("asx", "video/x-ms-asf");
- mimeTypes.put("au", "audio/basic");
- mimeTypes.put("avi", "video/x-msvideo");
- mimeTypes.put("avx", "video/x-rad-screenplay");
- mimeTypes.put("bcpio", "application/x-bcpio");
- mimeTypes.put("bin", "application/octet-stream");
- mimeTypes.put("bmp", "image/bmp");
- mimeTypes.put("body", "text/html");
- mimeTypes.put("cdf", "application/x-cdf");
- mimeTypes.put("cer", "application/x-x509-ca-cert");
- mimeTypes.put("class", "application/java");
- mimeTypes.put("cpio", "application/x-cpio");
- mimeTypes.put("csh", "application/x-csh");
- mimeTypes.put("css", "text/css");
- mimeTypes.put("dib", "image/bmp");
- mimeTypes.put("doc", "application/msword");
- mimeTypes.put("dtd", "text/plain");
- mimeTypes.put("dv", "video/x-dv");
- mimeTypes.put("dvi", "application/x-dvi");
- mimeTypes.put("eps", "application/postscript");
- mimeTypes.put("etx", "text/x-setext");
- mimeTypes.put("exe", "application/octet-stream");
- mimeTypes.put("gif", "image/gif");
- mimeTypes.put("gtar", "application/x-gtar");
- mimeTypes.put("gz", "application/x-gzip");
- mimeTypes.put("hdf", "application/x-hdf");
- mimeTypes.put("hqx", "application/mac-binhex40");
- mimeTypes.put("htc", "text/x-component");
- mimeTypes.put("htm", "text/html");
- mimeTypes.put("html", "text/html");
- mimeTypes.put("hqx", "application/mac-binhex40");
- mimeTypes.put("ief", "image/ief");
- mimeTypes.put("jad", "text/vnd.sun.j2me.app-descriptor");
- mimeTypes.put("jar", "application/java-archive");
- mimeTypes.put("java", "text/plain");
- mimeTypes.put("jnlp", "application/x-java-jnlp-file");
- mimeTypes.put("jpe", "image/jpeg");
- mimeTypes.put("jpeg", "image/jpeg");
- mimeTypes.put("jpg", "image/jpeg");
- mimeTypes.put("js", "text/javascript");
- mimeTypes.put("jsf", "text/plain");
- mimeTypes.put("jspf", "text/plain");
- mimeTypes.put("kar", "audio/x-midi");
- mimeTypes.put("latex", "application/x-latex");
- mimeTypes.put("m3u", "audio/x-mpegurl");
- mimeTypes.put("mac", "image/x-macpaint");
- mimeTypes.put("man", "application/x-troff-man");
- mimeTypes.put("me", "application/x-troff-me");
- mimeTypes.put("mid", "audio/x-midi");
- mimeTypes.put("midi", "audio/x-midi");
- mimeTypes.put("mif", "application/x-mif");
- mimeTypes.put("mov", "video/quicktime");
- mimeTypes.put("movie", "video/x-sgi-movie");
- mimeTypes.put("mp1", "audio/x-mpeg");
- mimeTypes.put("mp2", "audio/x-mpeg");
- mimeTypes.put("mp3", "audio/x-mpeg");
- mimeTypes.put("mpa", "audio/x-mpeg");
- mimeTypes.put("mpe", "video/mpeg");
- mimeTypes.put("mpeg", "video/mpeg");
- mimeTypes.put("mpega", "audio/x-mpeg");
- mimeTypes.put("mpg", "video/mpeg");
- mimeTypes.put("mpv2", "video/mpeg2");
- mimeTypes.put("ms", "application/x-wais-source");
- mimeTypes.put("nc", "application/x-netcdf");
- mimeTypes.put("oda", "application/oda");
- mimeTypes.put("pbm", "image/x-portable-bitmap");
- mimeTypes.put("pct", "image/pict");
- mimeTypes.put("pdf", "application/pdf");
- mimeTypes.put("pgm", "image/x-portable-graymap");
- mimeTypes.put("pic", "image/pict");
- mimeTypes.put("pict", "image/pict");
- mimeTypes.put("pls", "audio/x-scpls");
- mimeTypes.put("png", "image/png");
- mimeTypes.put("pnm", "image/x-portable-anymap");
- mimeTypes.put("pnt", "image/x-macpaint");
- mimeTypes.put("ppm", "image/x-portable-pixmap");
- mimeTypes.put("ppt", "application/powerpoint");
- mimeTypes.put("ps", "application/postscript");
- mimeTypes.put("psd", "image/x-photoshop");
- mimeTypes.put("qt", "video/quicktime");
- mimeTypes.put("qti", "image/x-quicktime");
- mimeTypes.put("qtif", "image/x-quicktime");
- mimeTypes.put("ras", "image/x-cmu-raster");
- mimeTypes.put("rgb", "image/x-rgb");
- mimeTypes.put("rm", "application/vnd.rn-realmedia");
- mimeTypes.put("roff", "application/x-troff");
- mimeTypes.put("rtf", "application/rtf");
- mimeTypes.put("rtx", "text/richtext");
- mimeTypes.put("sh", "application/x-sh");
- mimeTypes.put("shar", "application/x-shar");
- mimeTypes.put("smf", "audio/x-midi");
- mimeTypes.put("sit", "application/x-stuffit");
- mimeTypes.put("snd", "audio/basic");
- mimeTypes.put("src", "application/x-wais-source");
- mimeTypes.put("sv4cpio", "application/x-sv4cpio");
- mimeTypes.put("sv4crc", "application/x-sv4crc");
- mimeTypes.put("swf", "application/x-shockwave-flash");
- mimeTypes.put("t", "application/x-troff");
- mimeTypes.put("tar", "application/x-tar");
- mimeTypes.put("tcl", "application/x-tcl");
- mimeTypes.put("tex", "application/x-tex");
- mimeTypes.put("texi", "application/x-texinfo");
- mimeTypes.put("texinfo", "application/x-texinfo");
- mimeTypes.put("tif", "image/tiff");
- mimeTypes.put("tiff", "image/tiff");
- mimeTypes.put("tr", "application/x-troff");
- mimeTypes.put("tsv", "text/tab-separated-values");
- mimeTypes.put("txt", "text/plain");
- mimeTypes.put("ulw", "audio/basic");
- mimeTypes.put("ustar", "application/x-ustar");
- mimeTypes.put("xbm", "image/x-xbitmap");
- mimeTypes.put("xht", "application/xhtml+xml");
- mimeTypes.put("xhtml", "application/xhtml+xml");
- mimeTypes.put("xml", "text/xml");
- mimeTypes.put("xpm", "image/x-xpixmap");
- mimeTypes.put("xsl", "text/xml");
- mimeTypes.put("xwd", "image/x-xwindowdump");
- mimeTypes.put("wav", "audio/x-wav");
- mimeTypes.put("svg", "image/svg+xml");
- mimeTypes.put("svgz", "image/svg+xml");
- mimeTypes.put("vsd", "application/x-visio");
- mimeTypes.put("wbmp", "image/vnd.wap.wbmp");
- mimeTypes.put("wml", "text/vnd.wap.wml");
- mimeTypes.put("wmlc", "application/vnd.wap.wmlc");
- mimeTypes.put("wmls", "text/vnd.wap.wmlscript");
- mimeTypes.put("wmlscriptc", "application/vnd.wap.wmlscriptc");
- mimeTypes.put("wrl", "x-world/x-vrml");
- mimeTypes.put("Z", "application/x-compress");
- mimeTypes.put("z", "application/x-compress");
- mimeTypes.put("zip", "application/zip");
- }
-
- /**
- * Checks to see whether or not a client's file is out of date relative to the
- * original.
- */
- private boolean isNotModified(HttpServletRequest request, long ageOfServerCopy) {
- // The age of the server copy *must* have the milliseconds truncated.
- // Since milliseconds isn't part of the GMT format, failure to truncate
- // will leave the file in a state where it appears constantly out of date
- // and yet it can never get in sync because the Last-Modified date keeps
- // truncating off the milliseconds part on its way out.
- //
- ageOfServerCopy -= (ageOfServerCopy % 1000);
-
- long ageOfClientCopy = 0;
- String ifModifiedSince = request.getHeader("If-Modified-Since");
- if (ifModifiedSince != null) {
- // Rip off any additional stuff at the end, such as "; length="
- // (IE does add this).
- //
- int lastSemi = ifModifiedSince.lastIndexOf(';');
- if (lastSemi != -1) {
- ifModifiedSince = ifModifiedSince.substring(0, lastSemi);
- }
- ageOfClientCopy = HttpHeaders.fromInternetDateFormat(ifModifiedSince);
- }
-
- if (ageOfClientCopy >= ageOfServerCopy) {
- // The client already has a good copy.
- //
- return true;
- } else {
- // The client needs a fresh copy of the requested file.
- //
- return false;
- }
- }
-
- private void maybeIssueXhtmlWarning(TreeLogger logger, String mimeType,
- String path) {
- if (!XHTML_MIME_TYPE.equals(mimeType)) {
- return;
- }
-
- String msg = "File was returned with content-type of \"" + mimeType
- + "\". GWT requires browser features that are not available to "
- + "documents with this content-type.";
-
- int ix = path.lastIndexOf('.');
- if (ix >= 0 && ix < path.length()) {
- String base = path.substring(0, ix);
- msg += " Consider renaming \"" + path + "\" to \"" + base + ".html\".";
- }
-
- logger.log(TreeLogger.WARN, msg, null);
- }
-
- private void sendErrorResponse(HttpServletResponse response, int statusCode,
- String msg) throws IOException {
- response.setContentType("text/html");
- response.getWriter().println(msg);
- response.setStatus(statusCode);
- }
-
- /**
- * Sets the Cache-control and Expires headers in the response based on the
- * supplied cache time.
- *
- * Expires is used in addition to Cache-control for older clients or proxies
- * which may not properly understand Cache-control.
- *
- * @param response the HttpServletResponse to update
- * @param cacheTime non-negative number of seconds to cache the response; 0
- * means specifically do not allow caching at all.
- * @throws IllegalArgumentException if cacheTime is negative
- */
- private void setResponseCacheHeaders(HttpServletResponse response,
- long cacheTime) {
- long expires;
- if (cacheTime < 0) {
- throw new IllegalArgumentException("cacheTime of " + cacheTime
- + " is negative");
- }
- if (cacheTime > 0) {
- // Expire the specified seconds in the future.
- expires = new Date().getTime() + cacheTime * HttpHeaders.MS_SEC;
- } else {
- // Prevent caching by using a time in the past for cache expiration.
- // Use January 2, 1970 00:00:00, to account for timezone changes
- // in case a browser tries to convert to a local timezone first
- // 0=Jan 1, so add 1 day's worth of milliseconds to get Jan 2
- expires = HttpHeaders.SEC_DAY * HttpHeaders.MS_SEC;
- }
- response.setHeader(HttpHeaders.CACHE_CONTROL,
- HttpHeaders.CACHE_CONTROL_MAXAGE + cacheTime);
- String expiresString = HttpHeaders.toInternetDateFormat(expires);
- response.setHeader(HttpHeaders.EXPIRES, expiresString);
- }
-
- private boolean shouldAutoGenerateResources() {
- ServletContext servletContext = getServletContext();
- final String attr = "com.google.gwt.dev.shell.shouldAutoGenerateResources";
- Boolean attrValue = (Boolean) servletContext.getAttribute(attr);
- if (attrValue == null) {
- return true;
- }
- return attrValue;
- }
-
- private void streamOut(InputStream in, OutputStream out, int bufferSize)
- throws IOException {
- assert (bufferSize >= 0);
-
- byte[] buffer = new byte[bufferSize];
- int bytesRead = 0;
- while (true) {
- bytesRead = in.read(buffer);
- if (bytesRead >= 0) {
- // Copy the bytes out.
- out.write(buffer, 0, bytesRead);
- } else {
- // End of input stream.
- out.flush();
- return;
- }
- }
- }
-
- private HttpServlet tryGetOrLoadServlet(TreeLogger logger,
- ModuleDef moduleDef, String className) {
-
- // Maps className to live servlet for this module.
- Map<String, HttpServlet> moduleServlets;
- synchronized (loadedServletsByModuleAndClassName) {
- moduleServlets = loadedServletsByModuleAndClassName.get(moduleDef);
- if (moduleServlets == null) {
- moduleServlets = new HashMap<String, HttpServlet>();
- loadedServletsByModuleAndClassName.put(moduleDef, moduleServlets);
- }
- }
-
- synchronized (moduleServlets) {
- HttpServlet servlet = moduleServlets.get(className);
- if (servlet != null) {
- // Found it.
- //
- return servlet;
- }
-
- // Try to load and instantiate it.
- //
- Throwable caught = null;
- try {
- Class<?> servletClass = Class.forName(className);
- Object newInstance = servletClass.newInstance();
- if (!(newInstance instanceof HttpServlet)) {
- logger.log(TreeLogger.ERROR,
- "Not compatible with HttpServlet: " + className
- + " (does your service extend RemoteServiceServlet?)", null);
- return null;
- }
-
- // Success. Hang onto the instance so we can reuse it.
- //
- servlet = (HttpServlet) newInstance;
-
- // We create proxies for ServletContext and ServletConfig to enable
- // RemoteServiceServlets to load public and generated resources via
- // ServletContext.getResourceAsStream()
- //
- ServletContext context = new HostedModeServletContextProxy(
- getServletContext(), moduleDef, getShellWorkDirs());
- ServletConfig config = new HostedModeServletConfigProxy(
- getServletConfig(), context);
-
- servlet.init(config);
-
- moduleServlets.put(className, servlet);
- return servlet;
- } catch (ClassNotFoundException e) {
- caught = e;
- } catch (InstantiationException e) {
- caught = e;
- } catch (IllegalAccessException e) {
- caught = e;
- } catch (ServletException e) {
- caught = e;
- }
- String msg = "Unable to instantiate '" + className + "'";
- logger.log(TreeLogger.ERROR, msg, caught);
- return null;
- }
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java b/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
deleted file mode 100644
index d6b321e..0000000
--- a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
+++ /dev/null
@@ -1,338 +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.dev.shell;
-
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.resource.Resource;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.Set;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-
-/**
- * ServletContext proxy that implements the getResource and getResourceAsStream
- * members so that they can work with the {@link GWTShellServlet}.
- */
-class HostedModeServletContextProxy implements ServletContext {
- private final ServletContext context;
- /**
- * Avoid pinning my moduleDef.
- */
- private final WeakReference<ModuleDef> moduleDefRef;
- private final WorkDirs workDirs;
-
- HostedModeServletContextProxy(ServletContext context, ModuleDef moduleDef,
- WorkDirs workDirs) {
- this.context = context;
- this.moduleDefRef = new WeakReference<ModuleDef>(moduleDef);
- this.workDirs = workDirs;
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
- */
- public Object getAttribute(String arg0) {
- return context.getAttribute(arg0);
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getAttributeNames()
- */
- @SuppressWarnings("unchecked")
- public Enumeration<String> getAttributeNames() {
- return context.getAttributeNames();
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getContext(java.lang.String)
- */
- public ServletContext getContext(String arg0) {
- return context.getContext(arg0);
- }
-
- public String getContextPath() {
- return context.getContextPath();
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
- */
- public String getInitParameter(String arg0) {
- return context.getInitParameter(arg0);
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getInitParameterNames()
- */
- public Enumeration<?> getInitParameterNames() {
- return context.getInitParameterNames();
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getMajorVersion()
- */
- public int getMajorVersion() {
- return context.getMajorVersion();
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getMimeType(java.lang.String)
- */
- public String getMimeType(String arg0) {
- return context.getMimeType(arg0);
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getMinorVersion()
- */
- public int getMinorVersion() {
- return context.getMinorVersion();
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
- */
- public RequestDispatcher getNamedDispatcher(String arg0) {
- return context.getNamedDispatcher(arg0);
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getRealPath(java.lang.String)
- */
- public String getRealPath(String arg0) {
- return context.getRealPath(arg0);
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
- */
- public RequestDispatcher getRequestDispatcher(String arg0) {
- return context.getRequestDispatcher(arg0);
- }
-
- /**
- * @param arg0
- * @return
- * @throws MalformedURLException
- * @see javax.servlet.ServletContext#getResource(java.lang.String)
- */
- @SuppressWarnings("deprecation")
- public URL getResource(String path) throws MalformedURLException {
- ModuleDef moduleDef = moduleDefRef.get();
- assert (moduleDef != null) : "GWTShellServlet should have guaranteed that a"
- + " live servlet will never process a request for a dead module; if you"
- + " are using this servlet outside the context of processing a call,"
- + " then don't do that";
-
- String moduleContext = "/" + moduleDef.getName() + "/";
- if (!path.startsWith(moduleContext)) {
- // Check for a renamed module
- moduleContext = "/" + moduleDef.getCanonicalName() + "/";
- if (!path.startsWith(moduleContext)) {
- // This path is in a different context; just return null
- return null;
- }
- }
-
- String partialPath = path.substring(moduleContext.length());
-
- // Try to get the resource from the application's public path
- Resource publicResource = moduleDef.findPublicFile(partialPath);
- if (publicResource != null) {
- return publicResource.getURL();
- }
-
- // Otherwise try the path in the shell's public generated directory
- File shellDir = workDirs.getShellPublicGenDir(moduleDef);
- File requestedFile = new File(shellDir, partialPath);
- if (requestedFile.exists()) {
- return requestedFile.toURI().toURL();
- }
-
- /*
- * If the user is coming from compiled web-mode, check the linker output
- * directory for the file. We'll default to using the output directory of
- * the first linker defined in the <set-linker> tab.
- */
- File linkDir = workDirs.getCompilerOutputDir(moduleDef);
- requestedFile = new File(linkDir, partialPath);
- if (requestedFile.exists()) {
- try {
- return requestedFile.toURI().toURL();
- } catch (MalformedURLException e) {
- // ignore since it was speculative anyway
- }
- }
-
- return null;
- }
-
- /**
- * @param arg0
- * @return
- * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
- */
- public InputStream getResourceAsStream(String arg0) {
- URL url;
- try {
- url = getResource(arg0);
- if (url != null) {
- return url.openStream();
- }
- } catch (MalformedURLException e) {
- // Ignore the exception; return null
- } catch (IOException e) {
- // Ignore the exception; return null
- }
-
- return null;
- }
-
- /**
- *
- * @param path
- * @return
- * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
- */
- @SuppressWarnings("unchecked")
- public Set<String> getResourcePaths(String path) {
- return context.getResourcePaths(path);
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getServerInfo()
- */
- public String getServerInfo() {
- return context.getServerInfo();
- }
-
- /**
- * @param arg0
- * @return
- * @throws ServletException
- * @deprecated
- * @see javax.servlet.ServletContext#getServlet(java.lang.String)
- */
- @Deprecated
- public Servlet getServlet(String arg0) throws ServletException {
- return context.getServlet(arg0);
- }
-
- /**
- * @return
- * @see javax.servlet.ServletContext#getServletContextName()
- */
- public String getServletContextName() {
- return context.getServletContextName();
- }
-
- /**
- * @return
- * @deprecated
- * @see javax.servlet.ServletContext#getServletNames()
- */
- @Deprecated
- @SuppressWarnings("unchecked")
- public Enumeration<String> getServletNames() {
- return context.getServletNames();
- }
-
- /**
- * @return
- * @deprecated
- * @see javax.servlet.ServletContext#getServlets()
- */
- @Deprecated
- @SuppressWarnings("unchecked")
- public Enumeration<Servlet> getServlets() {
- return context.getServlets();
- }
-
- /**
- * @param arg0
- * @param arg1
- * @deprecated
- * @see javax.servlet.ServletContext#log(java.lang.Exception,
- * java.lang.String)
- */
- @Deprecated
- public void log(Exception arg0, String arg1) {
- context.log(arg0, arg1);
- }
-
- /**
- * @param arg0
- * @see javax.servlet.ServletContext#log(java.lang.String)
- */
- public void log(String arg0) {
- context.log(arg0);
- }
-
- /**
- * @param arg0
- * @param arg1
- * @see javax.servlet.ServletContext#log(java.lang.String,java.lang.Throwable)
- */
- public void log(String arg0, Throwable arg1) {
- context.log(arg0, arg1);
- }
-
- /**
- * @param arg0
- * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
- */
- public void removeAttribute(String arg0) {
- context.removeAttribute(arg0);
- }
-
- /**
- * @param arg0
- * @param arg1
- * @see javax.servlet.ServletContext#setAttribute(java.lang.String,java.lang.Object)
- */
- public void setAttribute(String arg0, Object arg1) {
- context.setAttribute(arg0, arg1);
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/CatalinaLoggerAdapter.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/CatalinaLoggerAdapter.java
deleted file mode 100644
index 9cf2d95..0000000
--- a/dev/core/src/com/google/gwt/dev/shell/tomcat/CatalinaLoggerAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2006 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.shell.tomcat;
-
-import com.google.gwt.core.ext.TreeLogger;
-
-import org.apache.catalina.logger.LoggerBase;
-
-class CatalinaLoggerAdapter extends LoggerBase {
-
- private final TreeLogger logger;
-
- public CatalinaLoggerAdapter(TreeLogger logger) {
- this.logger = logger;
- }
-
- @Override
- public void log(Exception exception, String msg) {
- logger.log(TreeLogger.WARN, msg, exception);
- }
-
- @Override
- public void log(String msg) {
- logger.log(TreeLogger.INFO, msg, null);
- }
-
- @Override
- public void log(String message, int verbosity) {
- TreeLogger.Type type = mapVerbosityToLogType(verbosity);
- logger.log(type, message, null);
- }
-
- @Override
- public void log(String msg, Throwable throwable) {
- logger.log(TreeLogger.WARN, msg, throwable);
- }
-
- @Override
- public void log(String message, Throwable throwable, int verbosity) {
- TreeLogger.Type type = mapVerbosityToLogType(verbosity);
- logger.log(type, message, throwable);
- }
-
- private TreeLogger.Type mapVerbosityToLogType(int verbosity) {
- switch (verbosity) {
- case LoggerBase.FATAL:
- case LoggerBase.ERROR:
- case LoggerBase.WARNING:
- return TreeLogger.WARN;
-
- case LoggerBase.INFORMATION:
- return TreeLogger.DEBUG;
- case LoggerBase.DEBUG:
- return TreeLogger.SPAM;
-
- default:
- // really, this was an unexpected type
- return TreeLogger.WARN;
- }
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/CommonsLoggerAdapter.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/CommonsLoggerAdapter.java
deleted file mode 100644
index d071d2a..0000000
--- a/dev/core/src/com/google/gwt/dev/shell/tomcat/CommonsLoggerAdapter.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2006 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.shell.tomcat;
-
-import com.google.gwt.core.ext.TreeLogger;
-
-/**
- * Maps Tomcat's commons logger onto the GWT shell's tree logger.
- */
-public class CommonsLoggerAdapter implements org.apache.commons.logging.Log {
-
- private TreeLogger log;
-
- /**
- * @param name unused
- */
- public CommonsLoggerAdapter(String name) {
- // NOTE: this is ugly, but I don't know of any other way to get a
- // non-static log to which we can delegate.
- //
- log = EmbeddedTomcatServer.sTomcat.getLogger();
- }
-
- public void debug(Object message) {
- doLog(TreeLogger.SPAM, message, null);
- }
-
- public void debug(Object message, Throwable t) {
- doLog(TreeLogger.SPAM, message, t);
- }
-
- public void error(Object message) {
- doLog(TreeLogger.WARN, message, null);
- }
-
- public void error(Object message, Throwable t) {
- doLog(TreeLogger.WARN, message, t);
- }
-
- public void fatal(Object message) {
- doLog(TreeLogger.WARN, message, null);
- }
-
- public void fatal(Object message, Throwable t) {
- doLog(TreeLogger.WARN, message, t);
- }
-
- public void info(Object message) {
- // Intentionally low-level to us.
- doLog(TreeLogger.TRACE, message, null);
- }
-
- public void info(Object message, Throwable t) {
- // Intentionally low-level to us.
- doLog(TreeLogger.TRACE, message, t);
- }
-
- public boolean isDebugEnabled() {
- return log.isLoggable(TreeLogger.SPAM);
- }
-
- public boolean isErrorEnabled() {
- return log.isLoggable(TreeLogger.WARN);
- }
-
- public boolean isFatalEnabled() {
- return log.isLoggable(TreeLogger.WARN);
- }
-
- public boolean isInfoEnabled() {
- // Intentionally low-level to us.
- return log.isLoggable(TreeLogger.TRACE);
- }
-
- public boolean isTraceEnabled() {
- // Intentionally low-level to us.
- return log.isLoggable(TreeLogger.SPAM);
- }
-
- public boolean isWarnEnabled() {
- return log.isLoggable(TreeLogger.WARN);
- }
-
- public void trace(Object message) {
- // Intentionally low-level to us.
- doLog(TreeLogger.DEBUG, message, null);
- }
-
- public void trace(Object message, Throwable t) {
- // Intentionally low-level to us.
- doLog(TreeLogger.DEBUG, message, t);
- }
-
- public void warn(Object message) {
- doLog(TreeLogger.WARN, message, null);
- }
-
- public void warn(Object message, Throwable t) {
- doLog(TreeLogger.WARN, message, t);
- }
-
- private void doLog(TreeLogger.Type type, Object message, Throwable t) {
- String msg = message.toString();
- log.log(type, msg, t);
- }
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
deleted file mode 100644
index e7d27ac..0000000
--- a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright 2006 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.shell.tomcat;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.resource.Resource;
-import com.google.gwt.dev.resource.impl.ClassPathEntry;
-import com.google.gwt.dev.resource.impl.PathPrefix;
-import com.google.gwt.dev.resource.impl.PathPrefixSet;
-import com.google.gwt.dev.resource.impl.ResourceOracleImpl;
-import com.google.gwt.dev.shell.WorkDirs;
-import com.google.gwt.dev.util.Util;
-
-import org.apache.catalina.Connector;
-import org.apache.catalina.ContainerEvent;
-import org.apache.catalina.ContainerListener;
-import org.apache.catalina.Engine;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.Logger;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.core.StandardHost;
-import org.apache.catalina.startup.Embedded;
-import org.apache.catalina.startup.HostConfig;
-import org.apache.coyote.tomcat5.CoyoteConnector;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Wraps an instance of the Tomcat web server used in hosted mode.
- */
-public class EmbeddedTomcatServer {
-
- static EmbeddedTomcatServer sTomcat;
-
- public static int getPort() {
- return sTomcat.port;
- }
-
- public static String start(TreeLogger topLogger, int port, WorkDirs workDirs) {
- return start(topLogger, port, workDirs, true);
- }
-
- public static synchronized String start(TreeLogger topLogger, int port,
- WorkDirs workDirs, boolean shouldAutoGenerateResources) {
- if (sTomcat != null) {
- throw new IllegalStateException("Embedded Tomcat is already running");
- }
-
- try {
- new EmbeddedTomcatServer(topLogger, port, workDirs,
- shouldAutoGenerateResources);
- return null;
- } catch (LifecycleException e) {
- String msg = e.getMessage();
- if (msg != null && msg.indexOf("already in use") != -1) {
- msg = "Port "
- + port
- + " is already is use; you probably still have another session active";
- } else {
- msg = "Unable to start the embedded Tomcat server; double-check that your configuration is valid";
- }
- return msg;
- }
- }
-
- // Stop the embedded Tomcat server.
- //
- public static synchronized void stop() {
- if (sTomcat != null) {
- try {
- sTomcat.catEmbedded.stop();
- } catch (LifecycleException e) {
- // There's nothing we can really do about this and the logger is
- // gone in many scenarios, so we just ignore it.
- //
- } finally {
- sTomcat = null;
- }
- }
- }
-
- /**
- * Returns what local port the Tomcat connector is running on.
- *
- * When starting Tomcat with port 0 (i.e. choose an open port), there is just
- * no way to figure out what port it actually chose. So we're using pure
- * hackery to steal the port via reflection. The only works because we bundle
- * Tomcat with GWT and know exactly what version it is.
- */
- private static int computeLocalPort(Connector connector) {
- Throwable caught = null;
- try {
- Field phField = CoyoteConnector.class.getDeclaredField("protocolHandler");
- phField.setAccessible(true);
- Object protocolHandler = phField.get(connector);
-
- Field epField = protocolHandler.getClass().getDeclaredField("ep");
- epField.setAccessible(true);
- Object endPoint = epField.get(protocolHandler);
-
- Field ssField = endPoint.getClass().getDeclaredField("serverSocket");
- ssField.setAccessible(true);
- ServerSocket serverSocket = (ServerSocket) ssField.get(endPoint);
-
- return serverSocket.getLocalPort();
- } catch (SecurityException e) {
- caught = e;
- } catch (NoSuchFieldException e) {
- caught = e;
- } catch (IllegalArgumentException e) {
- caught = e;
- } catch (IllegalAccessException e) {
- caught = e;
- }
- throw new RuntimeException(
- "Failed to retrieve the startup port from Embedded Tomcat", caught);
- }
-
- private Embedded catEmbedded;
-
- private Engine catEngine;
-
- private StandardHost catHost = null;
-
- private int port;
-
- private final TreeLogger startupBranchLogger;
-
- private EmbeddedTomcatServer(final TreeLogger topLogger, int listeningPort,
- final WorkDirs workDirs, final boolean shouldAutoGenerateResources)
- throws LifecycleException {
- if (topLogger == null) {
- throw new NullPointerException("No logger specified");
- }
-
- final TreeLogger logger = topLogger.branch(TreeLogger.INFO,
- "Starting HTTP on port " + listeningPort, null);
-
- startupBranchLogger = logger;
-
- // Make myself the one static instance.
- // NOTE: there is only one small implementation reason that this has
- // to be a singleton, which is that the commons logger LogFactory insists
- // on creating your logger class which must have a constructor with
- // exactly one String argument, and since we want LoggerAdapter to delegate
- // to the logger instance available through instance host, there is no
- // way I can think of to delegate without accessing a static field.
- // An inner class is almost right, except there's no outer instance.
- //
- sTomcat = this;
-
- // Assume the working directory is simply the user's current directory.
- //
- File topWorkDir = new File(System.getProperty("user.dir"));
-
- // Tell Tomcat its base directory so that it won't complain.
- //
- String catBase = System.getProperty("catalina.base");
- if (catBase == null) {
- // we (briefly) supported catalina.base.create, so let's not cut support
- // until the deprecated sunset
- catBase = System.getProperty("catalina.base.create");
- if (catBase != null) {
- logger.log(TreeLogger.WARN, "catalina.base.create is deprecated. " +
- "Use catalina.base, and it will be created if necessary.");
- topWorkDir = new File(catBase);
- }
- catBase = generateDefaultCatalinaBase(logger, topWorkDir);
- System.setProperty("catalina.base", catBase);
- }
-
- // Some debug messages for ourselves.
- //
- if (logger.isLoggable(TreeLogger.DEBUG)) {
- logger.log(TreeLogger.DEBUG, "catalina.base = " + catBase, null);
- }
-
- // Set up the logger that will be returned by the Commons logging factory.
- //
- String adapterClassName = CommonsLoggerAdapter.class.getName();
- System.setProperty("org.apache.commons.logging.Log", adapterClassName);
-
- // And set up an adapter that will work with the Catalina logger family.
- //
- Logger catalinaLogger = new CatalinaLoggerAdapter(topLogger);
-
- // Create an embedded server.
- //
- catEmbedded = new Embedded();
- catEmbedded.setDebug(0);
- catEmbedded.setLogger(catalinaLogger);
-
- // The embedded engine is called "gwt".
- //
- catEngine = catEmbedded.createEngine();
- catEngine.setName("gwt");
- catEngine.setDefaultHost("localhost");
- catEngine.setParentClassLoader(this.getClass().getClassLoader());
-
- // It answers localhost requests.
- //
- // String appBase = fCatalinaBaseDir.getAbsolutePath();
- String appBase = catBase + "/webapps";
- catHost = (StandardHost) catEmbedded.createHost("localhost", appBase);
-
- // Hook up a host config to search for and pull in webapps.
- //
- HostConfig hostConfig = new HostConfig();
- catHost.addLifecycleListener(hostConfig);
-
- // Hook pre-install events so that we can add attributes to allow loaded
- // instances to find their development instance host.
- //
- catHost.addContainerListener(new ContainerListener() {
- public void containerEvent(ContainerEvent event) {
- if (StandardHost.PRE_INSTALL_EVENT.equals(event.getType())) {
- StandardContext webapp = (StandardContext) event.getData();
- publishShellLoggerAttribute(logger, topLogger, webapp);
- publishShellWorkDirsAttribute(logger, workDirs, webapp);
- publishShouldAutoGenerateResourcesAttribute(logger,
- shouldAutoGenerateResources, webapp);
- }
- }
- });
-
- // Tell the engine about the host.
- //
- catEngine.addChild(catHost);
- catEngine.setDefaultHost(catHost.getName());
-
- // Tell the embedded manager about the engine.
- //
- catEmbedded.addEngine(catEngine);
- InetAddress nullAddr = null;
- Connector connector = catEmbedded.createConnector(nullAddr, listeningPort,
- false);
- catEmbedded.addConnector(connector);
-
- // start up!
- catEmbedded.start();
- port = computeLocalPort(connector);
-
- if (port != listeningPort) {
- if (logger.isLoggable(TreeLogger.INFO)) {
- logger.log(TreeLogger.INFO, "HTTP listening on port " + port, null);
- }
- }
- }
-
- public TreeLogger getLogger() {
- return startupBranchLogger;
- }
-
- /*
- * Assumes that the leaf is a file (not a directory).
- */
- private void copyFileNoOverwrite(TreeLogger logger, String srcResName,
- Resource srcRes, File catBase) {
-
- File dest = new File(catBase, srcResName);
- try {
- // Only copy if src is newer than desc.
- long srcLastModified = srcRes.getLastModified();
- long dstLastModified = dest.lastModified();
-
- if (srcLastModified < dstLastModified) {
- // Don't copy over it.
- if (logger.isLoggable(TreeLogger.SPAM)) {
- logger.log(TreeLogger.SPAM, "Source is older than existing: "
- + dest.getAbsolutePath(), null);
- }
- return;
- } else if (srcLastModified == dstLastModified) {
- // Exact same time; quietly don't overwrite.
- return;
- } else if (dest.exists()) {
- // Warn about the overwrite
- logger.log(TreeLogger.WARN, "Overwriting existing file '"
- + dest.getAbsolutePath() + "' with '" + srcRes.getLocation()
- + "', which has a newer timestamp");
- }
-
- // Make dest directories as required.
- File destParent = dest.getParentFile();
- if (destParent != null) {
- // No need to check mkdirs result because IOException later anyway.
- destParent.mkdirs();
- }
-
- Util.copy(srcRes.openContents(), new FileOutputStream(dest));
- dest.setLastModified(srcLastModified);
-
- if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE, "Wrote: " + dest.getAbsolutePath(), null);
- }
- } catch (IOException e) {
- logger.log(TreeLogger.WARN, "Failed to write: " + dest.getAbsolutePath(),
- e);
- }
- }
-
- /**
- * Extracts a valid catalina base instance from the classpath. Does not
- * overwrite any existing files.
- */
- private String generateDefaultCatalinaBase(TreeLogger logger, File workDir) {
- logger = logger.branch(
- TreeLogger.TRACE,
- "Property 'catalina.base' not specified; checking for a standard catalina base image instead",
- null);
-
- // Recursively copies out files and directories
- String tomcatEtcDir = "com/google/gwt/dev/etc/tomcat/";
- Map<String, Resource> resourceMap = null;
- Throwable caught = null;
- try {
- resourceMap = getResourcesFor(logger, tomcatEtcDir);
- } catch (URISyntaxException e) {
- caught = e;
- } catch (IOException e) {
- caught = e;
- }
-
- File catBase = new File(workDir, "tomcat");
- if (resourceMap == null || resourceMap.isEmpty()) {
- logger.log(TreeLogger.WARN, "Could not find " + tomcatEtcDir, caught);
- } else {
- for (Entry<String, Resource> entry : resourceMap.entrySet()) {
- copyFileNoOverwrite(logger, entry.getKey(), entry.getValue(), catBase);
- }
- }
-
- return catBase.getAbsolutePath();
- }
-
- /**
- * Hacky, but fast.
- */
- private Map<String, Resource> getResourcesFor(TreeLogger logger,
- String tomcatEtcDir) throws URISyntaxException, IOException {
- ClassLoader contextClassLoader = this.getClass().getClassLoader();
- URL url = contextClassLoader.getResource(tomcatEtcDir);
- if (url == null) {
- return null;
- }
- String prefix = "";
- String urlString = url.toString();
- if (urlString.startsWith("jar:")) {
- assert urlString.toLowerCase(Locale.ENGLISH).contains(".jar!/"
- + tomcatEtcDir);
- urlString = urlString.substring(4, urlString.indexOf('!'));
- url = new URL(urlString);
- prefix = tomcatEtcDir;
- } else if (urlString.startsWith("zip:")) {
- assert urlString.toLowerCase(Locale.ENGLISH).contains(".zip!/"
- + tomcatEtcDir);
- urlString = urlString.substring(4, urlString.indexOf('!'));
- url = new URL(urlString);
- prefix = tomcatEtcDir;
- }
- ClassPathEntry entry = ResourceOracleImpl.createEntryForUrl(logger, url);
- assert (entry != null);
- ResourceOracleImpl resourceOracle = new ResourceOracleImpl(
- Collections.singletonList(entry));
- PathPrefixSet pathPrefixSet = new PathPrefixSet();
- PathPrefix pathPrefix = new PathPrefix(prefix, null, true);
- pathPrefixSet.add(pathPrefix);
- resourceOracle.setPathPrefixes(pathPrefixSet);
- ResourceOracleImpl.refresh(logger, resourceOracle);
- Map<String, Resource> resourceMap = resourceOracle.getResourceMap();
- return resourceMap;
- }
-
- private void publishAttributeToWebApp(TreeLogger logger,
- StandardContext webapp, String attrName, Object attrValue) {
- if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE, "Adding attribute '" + attrName
- + "' to web app '" + webapp.getName() + "'", null);
- }
- webapp.getServletContext().setAttribute(attrName, attrValue);
- }
-
- /**
- * Publish the shell's tree logger as an attribute. This attribute is used to
- * find the logger out of the thin air within the shell servlet.
- */
- private void publishShellLoggerAttribute(TreeLogger logger,
- TreeLogger loggerToPublish, StandardContext webapp) {
- final String attr = "com.google.gwt.dev.shell.logger";
- publishAttributeToWebApp(logger, webapp, attr, loggerToPublish);
- }
-
- /**
- * Publish the shell's work dir as an attribute. This attribute is used to
- * find it out of the thin air within the shell servlet.
- */
- private void publishShellWorkDirsAttribute(TreeLogger logger,
- WorkDirs workDirs, StandardContext webapp) {
- final String attr = "com.google.gwt.dev.shell.workdirs";
- publishAttributeToWebApp(logger, webapp, attr, workDirs);
- }
-
- /**
- * Publish to the web app whether it should automatically generate resources.
- */
- private void publishShouldAutoGenerateResourcesAttribute(TreeLogger logger,
- boolean shouldAutoGenerateResources, StandardContext webapp) {
- publishAttributeToWebApp(logger, webapp,
- "com.google.gwt.dev.shell.shouldAutoGenerateResources",
- shouldAutoGenerateResources);
- }
-}
diff --git a/dev/core/src/org/apache/COPYING b/dev/core/src/org/apache/COPYING
deleted file mode 100644
index d9a10c0..0000000
--- a/dev/core/src/org/apache/COPYING
+++ /dev/null
@@ -1,176 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
diff --git a/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java b/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java
deleted file mode 100644
index f941fad..0000000
--- a/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java
+++ /dev/null
@@ -1,2169 +0,0 @@
-/*
- * Copyright 1999,2004 The Apache Software Foundation.
- *
- * 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.
- */
-// Modified by Google.
-
-package org.apache.catalina.loader;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FilePermission;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessControlException;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Policy;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Vector;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes.Name;
-
-import javax.naming.NameClassPair;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.util.StringManager;
-import org.apache.naming.JndiPermission;
-import org.apache.naming.resources.Resource;
-import org.apache.naming.resources.ResourceAttributes;
-import org.apache.tomcat.util.compat.JdkCompat;
-
-/**
- * Specialized web application class loader.
- * <p>
- * This class loader is a full reimplementation of the
- * <code>URLClassLoader</code> from the JDK. It is desinged to be fully
- * compatible with a normal <code>URLClassLoader</code>, although its internal
- * behavior may be completely different.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - This class loader faithfully follows
- * the delegation model recommended in the specification. The system class
- * loader will be queried first, then the local repositories, and only then
- * delegation to the parent class loader will occur. This allows the web
- * application to override any shared class except the classes from J2SE.
- * Special handling is provided from the JAXP XML parser interfaces, the JNDI
- * interfaces, and the classes from the servlet API, which are never loaded
- * from the webapp repository.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - Due to limitations in Jasper
- * compilation technology, any repository which contains classes from
- * the servlet API will be ignored by the class loader.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - The class loader generates source
- * URLs which include the full JAR URL when a class is loaded from a JAR file,
- * which allows setting security permission at the class level, even when a
- * class is contained inside a JAR.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - Local repositories are searched in
- * the order they are added via the initial constructor and/or any subsequent
- * calls to <code>addRepository()</code> or <code>addJar()</code>.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - No check for sealing violations or
- * security is made unless a security manager is present.
- *
- * @author Remy Maucherat
- * @author Craig R. McClanahan
- * @version $Revision: 1.34 $ $Date: 2004/05/26 15:47:40 $
- */
-public class WebappClassLoader
- extends URLClassLoader
- implements Reloader, Lifecycle
- {
-
- private static org.apache.commons.logging.Log log=
- org.apache.commons.logging.LogFactory.getLog( WebappClassLoader.class );
-
- protected class PrivilegedFindResource
- implements PrivilegedAction {
-
- private File file;
- private String path;
-
- PrivilegedFindResource(File file, String path) {
- this.file = file;
- this.path = path;
- }
-
- public Object run() {
- return findResourceInternal(file, path);
- }
-
- }
-
-
- // ------------------------------------------------------- Static Variables
-
-
- /**
- * The set of trigger classes that will cause a proposed repository not
- * to be added if this class is visible to the class loader that loaded
- * this factory class. Typically, trigger classes will be listed for
- * components that have been integrated into the JDK for later versions,
- * but where the corresponding JAR files are required to run on
- * earlier versions.
- */
- private static final String[] triggers = {
- "javax.servlet.Servlet" // Servlet API
- };
-
- /**
- * Jdk Compatibility Support.
- */
- private static JdkCompat jdkCompat = JdkCompat.getJdkCompat();
-
- /**
- * Set of package names which are not allowed to be loaded from a webapp
- * class loader without delegating first.
- */
- private static final String[] packageTriggers = {
- "javax", // Java extensions
- "org.xml.sax", // SAX 1 & 2
- "org.w3c.dom", // DOM 1 & 2
- "org.apache.xerces", // Xerces 1 & 2
- "org.apache.xalan" // Xalan
- };
-
-
- /**
- * The string manager for this package.
- */
- protected static final StringManager sm =
- StringManager.getManager(Constants.Package);
-
-
- // ----------------------------------------------------------- Constructors
-
-
- /**
- * Construct a new ClassLoader with no defined repositories and no
- * parent ClassLoader.
- */
- public WebappClassLoader() {
-
- super(new URL[0]);
- this.parent = getParent();
- system = getSystemClassLoader();
- securityManager = System.getSecurityManager();
-
- if (securityManager != null) {
- refreshPolicy();
- }
-
- }
-
-
- /**
- * Construct a new ClassLoader with no defined repositories and no
- * parent ClassLoader.
- */
- public WebappClassLoader(ClassLoader parent) {
-
- super(new URL[0], parent);
-
- this.parent = getParent();
-
- system = getSystemClassLoader();
- securityManager = System.getSecurityManager();
-
- if (securityManager != null) {
- refreshPolicy();
- }
- }
-
-
- // ----------------------------------------------------- Instance Variables
-
-
- /**
- * Associated directory context giving access to the resources in this
- * webapp.
- */
- protected DirContext resources = null;
-
-
- /**
- * The cache of ResourceEntry for classes and resources we have loaded,
- * keyed by resource name.
- */
- protected HashMap resourceEntries = new HashMap();
-
-
- /**
- * The list of not found resources.
- */
- protected HashMap notFoundResources = new HashMap();
-
-
- /**
- * The debugging detail level of this component.
- */
- protected int debug = 0;
-
-
- /**
- * Should this class loader delegate to the parent class loader
- * <strong>before</strong> searching its own repositories (i.e. the
- * usual Java2 delegation model)? If set to <code>false</code>,
- * this class loader will search its own repositories first, and
- * delegate to the parent only if the class or resource is not
- * found locally.
- */
- protected boolean delegate = false;
-
-
- /**
- * Last time a JAR was accessed.
- */
- protected long lastJarAccessed = 0L;
-
-
- /**
- * The list of local repositories, in the order they should be searched
- * for locally loaded classes or resources.
- */
- protected String[] repositories = new String[0];
-
-
- /**
- * Repositories URLs, used to cache the result of getURLs.
- */
- protected URL[] repositoryURLs = null;
-
-
- /**
- * Repositories translated as path in the work directory (for Jasper
- * originally), but which is used to generate fake URLs should getURLs be
- * called.
- */
- protected File[] files = new File[0];
-
-
- /**
- * The list of JARs, in the order they should be searched
- * for locally loaded classes or resources.
- */
- protected JarFile[] jarFiles = new JarFile[0];
-
-
- /**
- * The list of JARs, in the order they should be searched
- * for locally loaded classes or resources.
- */
- protected File[] jarRealFiles = new File[0];
-
-
- /**
- * The path which will be monitored for added Jar files.
- */
- protected String jarPath = null;
-
-
- /**
- * The list of JARs, in the order they should be searched
- * for locally loaded classes or resources.
- */
- protected String[] jarNames = new String[0];
-
-
- /**
- * The list of JARs last modified dates, in the order they should be
- * searched for locally loaded classes or resources.
- */
- protected long[] lastModifiedDates = new long[0];
-
-
- /**
- * The list of resources which should be checked when checking for
- * modifications.
- */
- protected String[] paths = new String[0];
-
-
- /**
- * A list of read File and Jndi Permission's required if this loader
- * is for a web application context.
- */
- private ArrayList permissionList = new ArrayList();
-
-
- /**
- * Path where resources loaded from JARs will be extracted.
- */
- private File loaderDir = null;
-
-
- /**
- * The PermissionCollection for each CodeSource for a web
- * application context.
- */
- private HashMap loaderPC = new HashMap();
-
-
- /**
- * Instance of the SecurityManager installed.
- */
- private SecurityManager securityManager = null;
-
-
- /**
- * The parent class loader.
- */
- private ClassLoader parent = null;
-
-
- /**
- * The system class loader.
- */
- private ClassLoader system = null;
-
-
- /**
- * Has this component been started?
- */
- protected boolean started = false;
-
-
- /**
- * Has external repositories.
- */
- protected boolean hasExternalRepositories = false;
-
-
- /**
- * All permission.
- */
- private Permission allPermission = new java.security.AllPermission();
-
-
- // ------------------------------------------------------------- Properties
-
-
- /**
- * Get associated resources.
- */
- public DirContext getResources() {
-
- return this.resources;
-
- }
-
-
- /**
- * Set associated resources.
- */
- public void setResources(DirContext resources) {
-
- this.resources = resources;
-
- }
-
-
- /**
- * Return the debugging detail level for this component.
- */
- public int getDebug() {
-
- return (this.debug);
-
- }
-
-
- /**
- * Set the debugging detail level for this component.
- *
- * @param debug The new debugging detail level
- */
- public void setDebug(int debug) {
-
- this.debug = debug;
-
- }
-
-
- /**
- * Return the "delegate first" flag for this class loader.
- */
- public boolean getDelegate() {
-
- return (this.delegate);
-
- }
-
-
- /**
- * Set the "delegate first" flag for this class loader.
- *
- * @param delegate The new "delegate first" flag
- */
- public void setDelegate(boolean delegate) {
-
- this.delegate = delegate;
-
- }
-
-
- /**
- * If there is a Java SecurityManager create a read FilePermission
- * or JndiPermission for the file directory path.
- *
- * @param path file directory path
- */
- public void addPermission(String path) {
- if (path == null) {
- return;
- }
-
- if (securityManager != null) {
- Permission permission = null;
- if( path.startsWith("jndi:") || path.startsWith("jar:jndi:") ) {
- if (!path.endsWith("/")) {
- path = path + "/";
- }
- permission = new JndiPermission(path + "*");
- addPermission(permission);
- } else {
- if (!path.endsWith(File.separator)) {
- permission = new FilePermission(path, "read");
- addPermission(permission);
- path = path + File.separator;
- }
- permission = new FilePermission(path + "-", "read");
- addPermission(permission);
- }
- }
- }
-
-
- /**
- * If there is a Java SecurityManager create a read FilePermission
- * or JndiPermission for URL.
- *
- * @param url URL for a file or directory on local system
- */
- public void addPermission(URL url) {
- if (url != null) {
- addPermission(url.toString());
- }
- }
-
-
- /**
- * If there is a Java SecurityManager create a Permission.
- *
- * @param url URL for a file or directory on local system
- */
- public void addPermission(Permission permission) {
- if ((securityManager != null) && (permission != null)) {
- permissionList.add(permission);
- }
- }
-
-
- /**
- * Return the JAR path.
- */
- public String getJarPath() {
-
- return this.jarPath;
-
- }
-
-
- /**
- * Change the Jar path.
- */
- public void setJarPath(String jarPath) {
-
- this.jarPath = jarPath;
-
- }
-
-
- /**
- * Change the work directory.
- */
- public void setWorkDir(File workDir) {
- this.loaderDir = new File(workDir, "loader");
- }
-
-
- // ------------------------------------------------------- Reloader Methods
-
-
- /**
- * Add a new repository to the set of places this ClassLoader can look for
- * classes to be loaded.
- *
- * @param repository Name of a source of classes to be loaded, such as a
- * directory pathname, a JAR file pathname, or a ZIP file pathname
- *
- * @exception IllegalArgumentException if the specified repository is
- * invalid or does not exist
- */
- public void addRepository(String repository) {
-
- // Ignore any of the standard repositories, as they are set up using
- // either addJar or addRepository
- if (repository.startsWith("/WEB-INF/lib")
- || repository.startsWith("/WEB-INF/classes"))
- return;
-
- // Add this repository to our underlying class loader
- try {
- URL url = new URL(repository);
- super.addURL(url);
- hasExternalRepositories = true;
- repositoryURLs = null;
- } catch (MalformedURLException e) {
- IllegalArgumentException iae = new IllegalArgumentException
- ("Invalid repository: " + repository);
- jdkCompat.chainException(iae, e);
- throw iae;
- }
-
- }
-
-
- /**
- * Add a new repository to the set of places this ClassLoader can look for
- * classes to be loaded.
- *
- * @param repository Name of a source of classes to be loaded, such as a
- * directory pathname, a JAR file pathname, or a ZIP file pathname
- *
- * @exception IllegalArgumentException if the specified repository is
- * invalid or does not exist
- */
- synchronized void addRepository(String repository, File file) {
-
- // Note : There should be only one (of course), but I think we should
- // keep this a bit generic
-
- if (repository == null)
- return;
-
- if (log.isDebugEnabled())
- log.debug("addRepository(" + repository + ")");
-
- int i;
-
- // Add this repository to our internal list
- String[] result = new String[repositories.length + 1];
- for (i = 0; i < repositories.length; i++) {
- result[i] = repositories[i];
- }
- result[repositories.length] = repository;
- repositories = result;
-
- // Add the file to the list
- File[] result2 = new File[files.length + 1];
- for (i = 0; i < files.length; i++) {
- result2[i] = files[i];
- }
- result2[files.length] = file;
- files = result2;
-
- }
-
-
- synchronized void addJar(String jar, JarFile jarFile, File file)
- throws IOException {
-
- if (jar == null)
- return;
- if (jarFile == null)
- return;
- if (file == null)
- return;
-
- if (log.isDebugEnabled())
- log.debug("addJar(" + jar + ")");
-
- int i;
-
- if ((jarPath != null) && (jar.startsWith(jarPath))) {
-
- String jarName = jar.substring(jarPath.length());
- while (jarName.startsWith("/"))
- jarName = jarName.substring(1);
-
- String[] result = new String[jarNames.length + 1];
- for (i = 0; i < jarNames.length; i++) {
- result[i] = jarNames[i];
- }
- result[jarNames.length] = jarName;
- jarNames = result;
-
- }
-
- try {
-
- // Register the JAR for tracking
-
- long lastModified =
- ((ResourceAttributes) resources.getAttributes(jar))
- .getLastModified();
-
- String[] result = new String[paths.length + 1];
- for (i = 0; i < paths.length; i++) {
- result[i] = paths[i];
- }
- result[paths.length] = jar;
- paths = result;
-
- long[] result3 = new long[lastModifiedDates.length + 1];
- for (i = 0; i < lastModifiedDates.length; i++) {
- result3[i] = lastModifiedDates[i];
- }
- result3[lastModifiedDates.length] = lastModified;
- lastModifiedDates = result3;
-
- } catch (NamingException e) {
- // Ignore
- }
-
- // If the JAR currently contains invalid classes, don't actually use it
- // for classloading
- if (!validateJarFile(file))
- return;
-
- JarFile[] result2 = new JarFile[jarFiles.length + 1];
- for (i = 0; i < jarFiles.length; i++) {
- result2[i] = jarFiles[i];
- }
- result2[jarFiles.length] = jarFile;
- jarFiles = result2;
-
- // Add the file to the list
- File[] result4 = new File[jarRealFiles.length + 1];
- for (i = 0; i < jarRealFiles.length; i++) {
- result4[i] = jarRealFiles[i];
- }
- result4[jarRealFiles.length] = file;
- jarRealFiles = result4;
- }
-
-
- /**
- * Return a String array of the current repositories for this class
- * loader. If there are no repositories, a zero-length array is
- * returned.For security reason, returns a clone of the Array (since
- * String are immutable).
- */
- public String[] findRepositories() {
-
- return ((String[])repositories.clone());
-
- }
-
-
- /**
- * Have one or more classes or resources been modified so that a reload
- * is appropriate?
- */
- public boolean modified() {
-
- if (log.isDebugEnabled())
- log.debug("modified()");
-
- // Checking for modified loaded resources
- int length = paths.length;
-
- // A rare race condition can occur in the updates of the two arrays
- // It's totally ok if the latest class added is not checked (it will
- // be checked the next time
- int length2 = lastModifiedDates.length;
- if (length > length2)
- length = length2;
-
- for (int i = 0; i < length; i++) {
- try {
- long lastModified =
- ((ResourceAttributes) resources.getAttributes(paths[i]))
- .getLastModified();
- if (lastModified != lastModifiedDates[i]) {
- if( log.isDebugEnabled() )
- log.debug(" Resource '" + paths[i]
- + "' was modified; Date is now: "
- + new java.util.Date(lastModified) + " Was: "
- + new java.util.Date(lastModifiedDates[i]));
- return (true);
- }
- } catch (NamingException e) {
- log.error(" Resource '" + paths[i] + "' is missing");
- return (true);
- }
- }
-
- length = jarNames.length;
-
- // Check if JARs have been added or removed
- if (getJarPath() != null) {
-
- try {
- NamingEnumeration enum_ = resources.listBindings(getJarPath());
- int i = 0;
- while (enum_.hasMoreElements() && (i < length)) {
- NameClassPair ncPair = (NameClassPair) enum_.nextElement();
- String name = ncPair.getName();
- // Ignore non JARs present in the lib folder
- if (!name.endsWith(".jar"))
- continue;
- if (!name.equals(jarNames[i])) {
- // Missing JAR
- log.info(" Additional JARs have been added : '"
- + name + "'");
- return (true);
- }
- i++;
- }
- if (enum_.hasMoreElements()) {
- while (enum_.hasMoreElements()) {
- NameClassPair ncPair =
- (NameClassPair) enum_.nextElement();
- String name = ncPair.getName();
- // Additional non-JAR files are allowed
- if (name.endsWith(".jar")) {
- // There was more JARs
- log.info(" Additional JARs have been added");
- return (true);
- }
- }
- } else if (i < jarNames.length) {
- // There was less JARs
- log.info(" Additional JARs have been added");
- return (true);
- }
- } catch (NamingException e) {
- if (log.isDebugEnabled())
- log.debug(" Failed tracking modifications of '"
- + getJarPath() + "'");
- } catch (ClassCastException e) {
- log.error(" Failed tracking modifications of '"
- + getJarPath() + "' : " + e.getMessage());
- }
-
- }
-
- // No classes have been modified
- return (false);
-
- }
-
-
- /**
- * Render a String representation of this object.
- */
- public String toString() {
-
- StringBuffer sb = new StringBuffer("WebappClassLoader\r\n");
- sb.append(" delegate: ");
- sb.append(delegate);
- sb.append("\r\n");
- sb.append(" repositories:\r\n");
- if (repositories != null) {
- for (int i = 0; i < repositories.length; i++) {
- sb.append(" ");
- sb.append(repositories[i]);
- sb.append("\r\n");
- }
- }
- if (this.parent != null) {
- sb.append("----------> Parent Classloader:\r\n");
- sb.append(this.parent.toString());
- sb.append("\r\n");
- }
- return (sb.toString());
-
- }
-
-
- // ---------------------------------------------------- ClassLoader Methods
-
-
- /**
- * Add the specified URL to the classloader.
- */
- protected void addURL(URL url) {
- super.addURL(url);
- hasExternalRepositories = true;
- repositoryURLs = null;
- }
-
-
- /**
- * Find the specified class in our local repositories, if possible. If
- * not found, throw <code>ClassNotFoundException</code>.
- *
- * @param name Name of the class to be loaded
- *
- * @exception ClassNotFoundException if the class was not found
- */
- public Class findClass(String name) throws ClassNotFoundException {
-
- if (log.isDebugEnabled())
- log.debug(" findClass(" + name + ")");
-
- // (1) Permission to define this class when using a SecurityManager
- if (securityManager != null) {
- int i = name.lastIndexOf('.');
- if (i >= 0) {
- try {
- if (log.isTraceEnabled())
- log.trace(" securityManager.checkPackageDefinition");
- securityManager.checkPackageDefinition(name.substring(0,i));
- } catch (Exception se) {
- if (log.isTraceEnabled())
- log.trace(" -->Exception-->ClassNotFoundException", se);
- throw new ClassNotFoundException(name, se);
- }
- }
- }
-
- // Ask our superclass to locate this class, if possible
- // (throws ClassNotFoundException if it is not found)
- Class clazz = null;
- try {
- if (log.isTraceEnabled())
- log.trace(" findClassInternal(" + name + ")");
- try {
- clazz = findClassInternal(name);
- } catch(ClassNotFoundException cnfe) {
- if (!hasExternalRepositories) {
- throw cnfe;
- }
- } catch(AccessControlException ace) {
- throw new ClassNotFoundException(name, ace);
- } catch (RuntimeException e) {
- if (log.isTraceEnabled())
- log.trace(" -->RuntimeException Rethrown", e);
- throw e;
- }
- if ((clazz == null) && hasExternalRepositories) {
- try {
- clazz = super.findClass(name);
- } catch(AccessControlException ace) {
- throw new ClassNotFoundException(name, ace);
- } catch (RuntimeException e) {
- if (log.isTraceEnabled())
- log.trace(" -->RuntimeException Rethrown", e);
- throw e;
- }
- }
- if (clazz == null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning ClassNotFoundException");
- throw new ClassNotFoundException(name);
- }
- } catch (ClassNotFoundException e) {
- if (log.isTraceEnabled())
- log.trace(" --> Passing on ClassNotFoundException");
- throw e;
- }
-
- // Return the class we have located
- if (log.isTraceEnabled())
- log.debug(" Returning class " + clazz);
- if ((log.isTraceEnabled()) && (clazz != null))
- log.debug(" Loaded by " + clazz.getClassLoader());
- return (clazz);
-
- }
-
-
- /**
- * Find the specified resource in our local repository, and return a
- * <code>URL</code> refering to it, or <code>null</code> if this resource
- * cannot be found.
- *
- * @param name Name of the resource to be found
- */
- public URL findResource(final String name) {
-
- if (log.isDebugEnabled())
- log.debug(" findResource(" + name + ")");
-
- URL url = null;
-
- ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
- if (entry == null) {
- entry = findResourceInternal(name, name);
- }
- if (entry != null) {
- url = entry.source;
- }
-
- if ((url == null) && hasExternalRepositories)
- url = super.findResource(name);
-
- if (log.isDebugEnabled()) {
- if (url != null)
- log.debug(" --> Returning '" + url.toString() + "'");
- else
- log.debug(" --> Resource not found, returning null");
- }
- return (url);
-
- }
-
-
- /**
- * Return an enumeration of <code>URLs</code> representing all of the
- * resources with the given name. If no resources with this name are
- * found, return an empty enumeration.
- *
- * @param name Name of the resources to be found
- *
- * @exception IOException if an input/output error occurs
- */
- public Enumeration findResources(String name) throws IOException {
-
- if (log.isDebugEnabled())
- log.debug(" findResources(" + name + ")");
-
- Vector result = new Vector();
-
- int jarFilesLength = jarFiles.length;
- int repositoriesLength = repositories.length;
-
- int i;
-
- // Looking at the repositories
- for (i = 0; i < repositoriesLength; i++) {
- try {
- String fullPath = repositories[i] + name;
- resources.lookup(fullPath);
- // Note : Not getting an exception here means the resource was
- // found
- try {
- result.addElement(getURI(new File(files[i], name)));
- } catch (MalformedURLException e) {
- // Ignore
- }
- } catch (NamingException e) {
- }
- }
-
- // Looking at the JAR files
- synchronized (jarFiles) {
- openJARs();
- for (i = 0; i < jarFilesLength; i++) {
- JarEntry jarEntry = jarFiles[i].getJarEntry(name);
- if (jarEntry != null) {
- try {
- String jarFakeUrl = getURI(jarRealFiles[i]).toString();
- jarFakeUrl = "jar:" + jarFakeUrl + "!/" + name;
- result.addElement(new URL(jarFakeUrl));
- } catch (MalformedURLException e) {
- // Ignore
- }
- }
- }
- }
-
- // Adding the results of a call to the superclass
- if (hasExternalRepositories) {
-
- Enumeration otherResourcePaths = super.findResources(name);
-
- while (otherResourcePaths.hasMoreElements()) {
- result.addElement(otherResourcePaths.nextElement());
- }
-
- }
-
- return result.elements();
-
- }
-
-
- /**
- * Find the resource with the given name. A resource is some data
- * (images, audio, text, etc.) that can be accessed by class code in a
- * way that is independent of the location of the code. The name of a
- * resource is a "/"-separated path name that identifies the resource.
- * If the resource cannot be found, return <code>null</code>.
- * <p>
- * This method searches according to the following algorithm, returning
- * as soon as it finds the appropriate URL. If the resource cannot be
- * found, returns <code>null</code>.
- * <ul>
- * <li>If the <code>delegate</code> property is set to <code>true</code>,
- * call the <code>getResource()</code> method of the parent class
- * loader, if any.</li>
- * <li>Call <code>findResource()</code> to find this resource in our
- * locally defined repositories.</li>
- * <li>Call the <code>getResource()</code> method of the parent class
- * loader, if any.</li>
- * </ul>
- *
- * @param name Name of the resource to return a URL for
- */
- public URL getResource(String name) {
-
- if (log.isDebugEnabled())
- log.debug("getResource(" + name + ")");
- URL url = null;
-
- // (1) Delegate to parent if requested
- if (delegate) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- url = loader.getResource(name);
- if (url != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return (url);
- }
- }
-
- // (2) Search local repositories
- url = findResource(name);
- if (url != null) {
- // Locating the repository for special handling in the case
- // of a JAR
- ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
- try {
- String repository = entry.codeBase.toString();
- if ((repository.endsWith(".jar"))
- && (!(name.endsWith(".class")))) {
- // Copy binary content to the work directory if not present
- File resourceFile = new File(loaderDir, name);
- url = resourceFile.toURL();
- }
- } catch (Exception e) {
- // Ignore
- }
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return (url);
- }
-
- // (3) Delegate to parent unconditionally if not already attempted
- if( !delegate ) {
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- url = loader.getResource(name);
- if (url != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return (url);
- }
- }
-
- // (4) Resource was not found
- if (log.isDebugEnabled())
- log.debug(" --> Resource not found, returning null");
- return (null);
-
- }
-
-
- /**
- * Find the resource with the given name, and return an input stream
- * that can be used for reading it. The search order is as described
- * for <code>getResource()</code>, after checking to see if the resource
- * data has been previously cached. If the resource cannot be found,
- * return <code>null</code>.
- *
- * @param name Name of the resource to return an input stream for
- */
- public InputStream getResourceAsStream(String name) {
-
- if (log.isDebugEnabled())
- log.debug("getResourceAsStream(" + name + ")");
- InputStream stream = null;
-
- // (0) Check for a cached copy of this resource
- stream = findLoadedResource(name);
- if (stream != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from cache");
- return (stream);
- }
-
- // (1) Delegate to parent if requested
- if (delegate) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- stream = loader.getResourceAsStream(name);
- if (stream != null) {
- // FIXME - cache???
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from parent");
- return (stream);
- }
- }
-
- // (2) Search local repositories
- if (log.isDebugEnabled())
- log.debug(" Searching local repositories");
- URL url = findResource(name);
- if (url != null) {
- // FIXME - cache???
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from local");
- stream = findLoadedResource(name);
- try {
- if (hasExternalRepositories && (stream == null))
- stream = url.openStream();
- } catch (IOException e) {
- ; // Ignore
- }
- if (stream != null)
- return (stream);
- }
-
- // (3) Delegate to parent unconditionally
- if (!delegate) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader unconditionally " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- stream = loader.getResourceAsStream(name);
- if (stream != null) {
- // FIXME - cache???
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from parent");
- return (stream);
- }
- }
-
- // (4) Resource was not found
- if (log.isDebugEnabled())
- log.debug(" --> Resource not found, returning null");
- return (null);
-
- }
-
-
- /**
- * Load the class with the specified name. This method searches for
- * classes in the same manner as <code>loadClass(String, boolean)</code>
- * with <code>false</code> as the second argument.
- *
- * @param name Name of the class to be loaded
- *
- * @exception ClassNotFoundException if the class was not found
- */
- public Class loadClass(String name) throws ClassNotFoundException {
-
- return (loadClass(name, false));
-
- }
-
-
- /**
- * Load the class with the specified name, searching using the following
- * algorithm until it finds and returns the class. If the class cannot
- * be found, returns <code>ClassNotFoundException</code>.
- * <ul>
- * <li>Call <code>findLoadedClass(String)</code> to check if the
- * class has already been loaded. If it has, the same
- * <code>Class</code> object is returned.</li>
- * <li>If the <code>delegate</code> property is set to <code>true</code>,
- * call the <code>loadClass()</code> method of the parent class
- * loader, if any.</li>
- * <li>Call <code>findClass()</code> to find this class in our locally
- * defined repositories.</li>
- * <li>Call the <code>loadClass()</code> method of our parent
- * class loader, if any.</li>
- * </ul>
- * If the class was found using the above steps, and the
- * <code>resolve</code> flag is <code>true</code>, this method will then
- * call <code>resolveClass(Class)</code> on the resulting Class object.
- *
- * @param name Name of the class to be loaded
- * @param resolve If <code>true</code> then resolve the class
- *
- * @exception ClassNotFoundException if the class was not found
- */
- public Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
-
- if (log.isDebugEnabled())
- log.debug("loadClass(" + name + ", " + resolve + ")");
- Class clazz = null;
-
- // Don't load classes if class loader is stopped
- if (!started) {
- log.info(sm.getString("webappClassLoader.stopped"));
- throw new ThreadDeath();
- }
-
- // (0) Check our previously loaded local class cache
- clazz = findLoadedClass0(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
-
- // (0.1) Check our previously loaded class cache
- clazz = findLoadedClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
-
- // (0.2) Try loading the class with the system class loader, to prevent
- // the webapp from overriding J2SE classes
- // GOOGLE: use the bootstrap loader, not the system loader; it breaks
- // embedding.
- try {
- // clazz = system.loadClass(name);
- clazz = Class.forName(name, false, null);
- if (clazz != null) {
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- // Ignore
- }
-
- // (0.5) Permission to access this class when using a SecurityManager
- if (securityManager != null) {
- int i = name.lastIndexOf('.');
- if (i >= 0) {
- try {
- securityManager.checkPackageAccess(name.substring(0,i));
- } catch (SecurityException se) {
- String error = "Security Violation, attempt to use " +
- "Restricted Class: " + name;
- log.info(error, se);
- throw new ClassNotFoundException(error, se);
- }
- }
- }
-
- boolean delegateLoad = delegate || filter(name);
-
- // (1) Delegate to our parent if requested
- if (delegateLoad) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader1 " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- try {
- clazz = loader.loadClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- ;
- }
- }
-
- // (2) Search local repositories
- if (log.isDebugEnabled())
- log.debug(" Searching local repositories");
- try {
- clazz = findClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from local repository");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- ;
- }
-
- // (3) Delegate to parent unconditionally
- if (!delegateLoad) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader at end: " + parent);
- ClassLoader loader = parent;
- if (loader == null)
- loader = system;
- try {
- clazz = loader.loadClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
- } catch (ClassNotFoundException e) {
- ;
- }
- }
-
- throw new ClassNotFoundException(name);
- }
-
-
- /**
- * Get the Permissions for a CodeSource. If this instance
- * of WebappClassLoader is for a web application context,
- * add read FilePermission or JndiPermissions for the base
- * directory (if unpacked),
- * the context URL, and jar file resources.
- *
- * @param codeSource where the code was loaded from
- * @return PermissionCollection for CodeSource
- */
- protected PermissionCollection getPermissions(CodeSource codeSource) {
-
- String codeUrl = codeSource.getLocation().toString();
- PermissionCollection pc;
- if ((pc = (PermissionCollection)loaderPC.get(codeUrl)) == null) {
- pc = super.getPermissions(codeSource);
- if (pc != null) {
- Iterator perms = permissionList.iterator();
- while (perms.hasNext()) {
- Permission p = (Permission)perms.next();
- pc.add(p);
- }
- loaderPC.put(codeUrl,pc);
- }
- }
- return (pc);
-
- }
-
-
- /**
- * Returns the search path of URLs for loading classes and resources.
- * This includes the original list of URLs specified to the constructor,
- * along with any URLs subsequently appended by the addURL() method.
- * @return the search path of URLs for loading classes and resources.
- */
- public URL[] getURLs() {
-
- if (repositoryURLs != null) {
- return repositoryURLs;
- }
-
- URL[] external = super.getURLs();
-
- int filesLength = files.length;
- int jarFilesLength = jarRealFiles.length;
- int length = filesLength + jarFilesLength + external.length;
- int i;
-
- try {
-
- URL[] urls = new URL[length];
- for (i = 0; i < length; i++) {
- if (i < filesLength) {
- urls[i] = getURL(files[i]);
- } else if (i < filesLength + jarFilesLength) {
- urls[i] = getURL(jarRealFiles[i - filesLength]);
- } else {
- urls[i] = external[i - filesLength - jarFilesLength];
- }
- }
-
- repositoryURLs = urls;
-
- } catch (MalformedURLException e) {
- repositoryURLs = new URL[0];
- }
-
- return repositoryURLs;
-
- }
-
-
- // ------------------------------------------------------ Lifecycle Methods
-
-
- /**
- * Add a lifecycle event listener to this component.
- *
- * @param listener The listener to add
- */
- public void addLifecycleListener(LifecycleListener listener) {
- }
-
-
- /**
- * Get the lifecycle listeners associated with this lifecycle. If this
- * Lifecycle has no listeners registered, a zero-length array is returned.
- */
- public LifecycleListener[] findLifecycleListeners() {
- return new LifecycleListener[0];
- }
-
-
- /**
- * Remove a lifecycle event listener from this component.
- *
- * @param listener The listener to remove
- */
- public void removeLifecycleListener(LifecycleListener listener) {
- }
-
-
- /**
- * Start the class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- public void start() throws LifecycleException {
-
- started = true;
-
- }
-
-
- /**
- * Stop the class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- public void stop() throws LifecycleException {
-
- started = false;
-
- int length = files.length;
- for (int i = 0; i < length; i++) {
- files[i] = null;
- }
-
- length = jarFiles.length;
- for (int i = 0; i < length; i++) {
- try {
- if (jarFiles[i] != null) {
- jarFiles[i].close();
- }
- } catch (IOException e) {
- // Ignore
- }
- jarFiles[i] = null;
- }
-
- notFoundResources.clear();
- resourceEntries.clear();
- resources = null;
- repositories = null;
- repositoryURLs = null;
- files = null;
- jarFiles = null;
- jarRealFiles = null;
- jarPath = null;
- jarNames = null;
- lastModifiedDates = null;
- paths = null;
- hasExternalRepositories = false;
- parent = null;
-
- permissionList.clear();
- loaderPC.clear();
-
- if (loaderDir != null) {
- deleteDir(loaderDir);
- }
-
- org.apache.commons.logging.LogFactory.release(this);
-
- }
-
-
- /**
- * Used to periodically signal to the classloader to release
- * JAR resources.
- */
- public void closeJARs(boolean force) {
- if (jarFiles.length > 0) {
- try {
- synchronized (jarFiles) {
- if (force || (System.currentTimeMillis()
- > (lastJarAccessed + 90000))) {
- for (int i = 0; i < jarFiles.length; i++) {
- if (jarFiles[i] != null) {
- jarFiles[i].close();
- jarFiles[i] = null;
- }
- }
- }
- }
- } catch (IOException e) {
- log("Failed to close JAR", e);
- }
- }
- }
-
-
- // ------------------------------------------------------ Protected Methods
-
-
- /**
- * Used to periodically signal to the classloader to release JAR resources.
- */
- protected void openJARs() {
- if (started && (jarFiles.length > 0)) {
- lastJarAccessed = System.currentTimeMillis();
- if (jarFiles[0] == null) {
- try {
- for (int i = 0; i < jarFiles.length; i++) {
- jarFiles[i] = new JarFile(jarRealFiles[i]);
- }
- } catch (IOException e) {
- log("Failed to open JAR", e);
- }
- }
- }
- }
-
-
- /**
- * Find specified class in local repositories.
- *
- * @return the loaded class, or null if the class isn't found
- */
- protected Class findClassInternal(String name)
- throws ClassNotFoundException {
-
- if (!validate(name))
- throw new ClassNotFoundException(name);
-
- String tempPath = name.replace('.', '/');
- String classPath = tempPath + ".class";
-
- ResourceEntry entry = null;
-
- entry = findResourceInternal(name, classPath);
-
- if ((entry == null) || (entry.binaryContent == null))
- throw new ClassNotFoundException(name);
-
- Class clazz = entry.loadedClass;
- if (clazz != null)
- return clazz;
-
- // Looking up the package
- String packageName = null;
- int pos = name.lastIndexOf('.');
- if (pos != -1)
- packageName = name.substring(0, pos);
-
- Package pkg = null;
-
- if (packageName != null) {
-
- pkg = getPackage(packageName);
-
- // Define the package (if null)
- if (pkg == null) {
- if (entry.manifest == null) {
- definePackage(packageName, null, null, null, null, null,
- null, null);
- } else {
- definePackage(packageName, entry.manifest, entry.codeBase);
- }
- }
-
- }
-
- // Create the code source object
- CodeSource codeSource =
- new CodeSource(entry.codeBase, entry.certificates);
-
- if (securityManager != null) {
-
- // Checking sealing
- if (pkg != null) {
- boolean sealCheck = true;
- if (pkg.isSealed()) {
- sealCheck = pkg.isSealed(entry.codeBase);
- } else {
- sealCheck = (entry.manifest == null)
- || !isPackageSealed(packageName, entry.manifest);
- }
- if (!sealCheck)
- throw new SecurityException
- ("Sealing violation loading " + name + " : Package "
- + packageName + " is sealed.");
- }
-
- }
-
- if (entry.loadedClass == null) {
- synchronized (this) {
- if (entry.loadedClass == null) {
- clazz = defineClass(name, entry.binaryContent, 0,
- entry.binaryContent.length,
- codeSource);
- entry.loadedClass = clazz;
- entry.binaryContent = null;
- entry.source = null;
- entry.codeBase = null;
- entry.manifest = null;
- entry.certificates = null;
- } else {
- clazz = entry.loadedClass;
- }
- }
- } else {
- clazz = entry.loadedClass;
- }
-
- return clazz;
-
- }
-
- /**
- * Find specified resource in local repositories. This block
- * will execute under an AccessControl.doPrivilege block.
- *
- * @return the loaded resource, or null if the resource isn't found
- */
- private ResourceEntry findResourceInternal(File file, String path){
- ResourceEntry entry = new ResourceEntry();
- try {
- entry.source = getURI(new File(file, path));
- entry.codeBase = getURL(new File(file, path));
- } catch (MalformedURLException e) {
- return null;
- }
- return entry;
- }
-
-
- /**
- * Find specified resource in local repositories.
- *
- * @return the loaded resource, or null if the resource isn't found
- */
- protected ResourceEntry findResourceInternal(String name, String path) {
-
- if (!started) {
- log.info(sm.getString("webappClassLoader.stopped"));
- return null;
- }
-
- if ((name == null) || (path == null))
- return null;
-
- ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
- if (entry != null)
- return entry;
-
- int contentLength = -1;
- InputStream binaryStream = null;
-
- int jarFilesLength = jarFiles.length;
- int repositoriesLength = repositories.length;
-
- int i;
-
- Resource resource = null;
-
- for (i = 0; (entry == null) && (i < repositoriesLength); i++) {
- try {
-
- String fullPath = repositories[i] + path;
-
- Object lookupResult = resources.lookup(fullPath);
- if (lookupResult instanceof Resource) {
- resource = (Resource) lookupResult;
- }
-
- // Note : Not getting an exception here means the resource was
- // found
- if (securityManager != null) {
- PrivilegedAction dp =
- new PrivilegedFindResource(files[i], path);
- entry = (ResourceEntry)AccessController.doPrivileged(dp);
- } else {
- entry = findResourceInternal(files[i], path);
- }
-
- ResourceAttributes attributes =
- (ResourceAttributes) resources.getAttributes(fullPath);
- contentLength = (int) attributes.getContentLength();
- entry.lastModified = attributes.getLastModified();
-
- if (resource != null) {
-
- try {
- binaryStream = resource.streamContent();
- } catch (IOException e) {
- return null;
- }
-
- // Register the full path for modification checking
- // Note: Only syncing on a 'constant' object is needed
- synchronized (allPermission) {
-
- int j;
-
- long[] result2 =
- new long[lastModifiedDates.length + 1];
- for (j = 0; j < lastModifiedDates.length; j++) {
- result2[j] = lastModifiedDates[j];
- }
- result2[lastModifiedDates.length] = entry.lastModified;
- lastModifiedDates = result2;
-
- String[] result = new String[paths.length + 1];
- for (j = 0; j < paths.length; j++) {
- result[j] = paths[j];
- }
- result[paths.length] = fullPath;
- paths = result;
-
- }
-
- }
-
- } catch (NamingException e) {
- }
- }
-
- if ((entry == null) && (notFoundResources.containsKey(name)))
- return null;
-
- JarEntry jarEntry = null;
-
- synchronized (jarFiles) {
-
- openJARs();
- for (i = 0; (entry == null) && (i < jarFilesLength); i++) {
-
- jarEntry = jarFiles[i].getJarEntry(path);
-
- if (jarEntry != null) {
-
- entry = new ResourceEntry();
- try {
- entry.codeBase = getURL(jarRealFiles[i]);
- String jarFakeUrl = getURI(jarRealFiles[i]).toString();
- jarFakeUrl = "jar:" + jarFakeUrl + "!/" + path;
- entry.source = new URL(jarFakeUrl);
- entry.lastModified = jarRealFiles[i].lastModified();
- } catch (MalformedURLException e) {
- return null;
- }
- contentLength = (int) jarEntry.getSize();
- try {
- entry.manifest = jarFiles[i].getManifest();
- binaryStream = jarFiles[i].getInputStream(jarEntry);
- } catch (IOException e) {
- return null;
- }
-
- // Extract resources contained in JAR to the workdir
- if (!(path.endsWith(".class"))) {
- byte[] buf = new byte[1024];
- File resourceFile = new File
- (loaderDir, jarEntry.getName());
- if (!resourceFile.exists()) {
- Enumeration entries = jarFiles[i].entries();
- while (entries.hasMoreElements()) {
- JarEntry jarEntry2 =
- (JarEntry) entries.nextElement();
- if (!(jarEntry2.isDirectory())
- && (!jarEntry2.getName().endsWith
- (".class"))) {
- resourceFile = new File
- (loaderDir, jarEntry2.getName());
- // No need to check mkdirs result because an
- // IOException will occur anyway
- resourceFile.getParentFile().mkdirs();
- FileOutputStream os = null;
- InputStream is = null;
- try {
- is = jarFiles[i].getInputStream
- (jarEntry2);
- os = new FileOutputStream
- (resourceFile);
- while (true) {
- int n = is.read(buf);
- if (n <= 0) {
- break;
- }
- os.write(buf, 0, n);
- }
- } catch (IOException e) {
- // Ignore
- } finally {
- try {
- if (is != null) {
- is.close();
- }
- } catch (IOException e) {
- }
- try {
- if (os != null) {
- os.close();
- }
- } catch (IOException e) {
- }
- }
- }
- }
- }
- }
-
- }
-
- }
-
- if (entry == null) {
- synchronized (notFoundResources) {
- notFoundResources.put(name, name);
- }
- return null;
- }
-
- if (binaryStream != null) {
-
- byte[] binaryContent = new byte[contentLength];
-
- try {
- int pos = 0;
-
- while (true) {
- int n = binaryStream.read(binaryContent, pos,
- binaryContent.length - pos);
- if (n <= 0)
- break;
- pos += n;
- }
- binaryStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
-
- entry.binaryContent = binaryContent;
-
- // The certificates are only available after the JarEntry
- // associated input stream has been fully read
- if (jarEntry != null) {
- entry.certificates = jarEntry.getCertificates();
- }
-
- }
-
- }
-
- // Add the entry in the local resource repository
- synchronized (resourceEntries) {
- // Ensures that all the threads which may be in a race to load
- // a particular class all end up with the same ResourceEntry
- // instance
- ResourceEntry entry2 = (ResourceEntry) resourceEntries.get(name);
- if (entry2 == null) {
- resourceEntries.put(name, entry);
- } else {
- entry = entry2;
- }
- }
-
- return entry;
-
- }
-
-
- /**
- * Returns true if the specified package name is sealed according to the
- * given manifest.
- */
- protected boolean isPackageSealed(String name, Manifest man) {
-
- String path = name + "/";
- Attributes attr = man.getAttributes(path);
- String sealed = null;
- if (attr != null) {
- sealed = attr.getValue(Name.SEALED);
- }
- if (sealed == null) {
- if ((attr = man.getMainAttributes()) != null) {
- sealed = attr.getValue(Name.SEALED);
- }
- }
- return "true".equalsIgnoreCase(sealed);
-
- }
-
-
- /**
- * Finds the resource with the given name if it has previously been
- * loaded and cached by this class loader, and return an input stream
- * to the resource data. If this resource has not been cached, return
- * <code>null</code>.
- *
- * @param name Name of the resource to return
- */
- protected InputStream findLoadedResource(String name) {
-
- ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
- if (entry != null) {
- if (entry.binaryContent != null)
- return new ByteArrayInputStream(entry.binaryContent);
- }
- return (null);
-
- }
-
-
- /**
- * Finds the class with the given name if it has previously been
- * loaded and cached by this class loader, and return the Class object.
- * If this class has not been cached, return <code>null</code>.
- *
- * @param name Name of the resource to return
- */
- protected Class findLoadedClass0(String name) {
-
- ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
- if (entry != null) {
- return entry.loadedClass;
- }
- return (null); // FIXME - findLoadedResource()
-
- }
-
-
- /**
- * Refresh the system policy file, to pick up eventual changes.
- */
- protected void refreshPolicy() {
-
- try {
- // The policy file may have been modified to adjust
- // permissions, so we're reloading it when loading or
- // reloading a Context
- Policy policy = Policy.getPolicy();
- policy.refresh();
- } catch (AccessControlException e) {
- // Some policy files may restrict this, even for the core,
- // so this exception is ignored
- }
-
- }
-
-
- /**
- * Filter classes.
- *
- * @param name class name
- * @return true if the class should be filtered
- */
- protected boolean filter(String name) {
-
- if (name == null)
- return false;
-
- // Looking up the package
- String packageName = null;
- int pos = name.lastIndexOf('.');
- if (pos != -1)
- packageName = name.substring(0, pos);
- else
- return false;
-
- for (int i = 0; i < packageTriggers.length; i++) {
- if (packageName.startsWith(packageTriggers[i]))
- return true;
- }
-
- return false;
-
- }
-
-
- /**
- * Validate a classname. As per SRV.9.7.2, we must restict loading of
- * classes from J2SE (java.*) and classes of the servlet API
- * (javax.servlet.*). That should enhance robustness and prevent a number
- * of user error (where an older version of servlet.jar would be present
- * in /WEB-INF/lib).
- *
- * @param name class name
- * @return true if the name is valid
- */
- protected boolean validate(String name) {
-
- if (name == null)
- return false;
- if (name.startsWith("java."))
- return false;
-
- return true;
-
- }
-
-
- /**
- * Check the specified JAR file, and return <code>true</code> if it does
- * not contain any of the trigger classes.
- *
- * @param jarfile The JAR file to be checked
- *
- * @exception IOException if an input/output error occurs
- */
- private boolean validateJarFile(File jarfile)
- throws IOException {
-
- if (triggers == null)
- return (true);
- JarFile jarFile = new JarFile(jarfile);
- for (int i = 0; i < triggers.length; i++) {
- Class clazz = null;
- try {
- if (parent != null) {
- clazz = parent.loadClass(triggers[i]);
- } else {
- clazz = Class.forName(triggers[i]);
- }
- } catch (Throwable t) {
- clazz = null;
- }
- if (clazz == null)
- continue;
- String name = triggers[i].replace('.', '/') + ".class";
- if (log.isDebugEnabled())
- log.debug(" Checking for " + name);
- JarEntry jarEntry = jarFile.getJarEntry(name);
- if (jarEntry != null) {
- log.info("validateJarFile(" + jarfile +
- ") - jar not loaded. See Servlet Spec 2.3, "
- + "section 9.7.2. Offending class: " + name);
- jarFile.close();
- return (false);
- }
- }
- jarFile.close();
- return (true);
-
- }
-
-
- /**
- * Get URL.
- */
- protected URL getURL(File file)
- throws MalformedURLException {
-
- File realFile = file;
- try {
- realFile = realFile.getCanonicalFile();
- } catch (IOException e) {
- // Ignore
- }
- return realFile.toURL();
-
- }
-
-
- /**
- * Get URL.
- */
- protected URL getURI(File file)
- throws MalformedURLException {
-
- return jdkCompat.getURI(file);
-
- }
-
-
- /**
- * Delete the specified directory, including all of its contents and
- * subdirectories recursively.
- *
- * @param dir File object representing the directory to be deleted
- */
- protected static void deleteDir(File dir) {
-
- String files[] = dir.list();
- if (files == null) {
- files = new String[0];
- }
- for (int i = 0; i < files.length; i++) {
- File file = new File(dir, files[i]);
- if (file.isDirectory()) {
- deleteDir(file);
- } else {
- file.delete();
- }
- }
- dir.delete();
-
- }
-
-
- /**
- * Log a debugging output message.
- *
- * @param message Message to be logged
- */
- private void log(String message) {
-
- System.out.println("WebappClassLoader: " + message);
-
- }
-
-
- /**
- * Log a debugging output message with an exception.
- *
- * @param message Message to be logged
- * @param throwable Exception to be logged
- */
- private void log(String message, Throwable throwable) {
-
- System.out.println("WebappClassLoader: " + message);
- throwable.printStackTrace(System.out);
-
- }
-
-}
diff --git a/dev/core/test/com/google/gwt/dev/GWTCompilerTest.java b/dev/core/test/com/google/gwt/dev/GWTCompilerTest.java
deleted file mode 100644
index 8955714..0000000
--- a/dev/core/test/com/google/gwt/dev/GWTCompilerTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2009 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;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.GWTCompiler.GWTCompilerOptionsImpl;
-import com.google.gwt.dev.jjs.JsOutputOption;
-
-import java.io.File;
-
-/**
- * Test for deprecated {@link GWTShell}.
- */
-@SuppressWarnings("deprecation")
-public class GWTCompilerTest extends ArgProcessorTestBase {
-
- private final GWTCompiler.ArgProcessor argProcessor;
- private final GWTCompilerOptionsImpl options = new GWTCompilerOptionsImpl();
-
- public GWTCompilerTest() {
- argProcessor = new GWTCompiler.ArgProcessor(options);
- }
-
- public void testAllValidArgs() {
- assertProcessSuccess(argProcessor, "-logLevel", "DEBUG", "-style",
- "PRETTY", "-ea", "-XdisableAggressiveOptimization", "-out", "myWww",
- "-gen", "myGen", "c.g.g.h.H", "my.Module");
-
- assertEquals(new File("myGen").getAbsoluteFile(),
- options.getGenDir().getAbsoluteFile());
- assertEquals(new File("myWww"), options.getOutDir());
-
- assertEquals(TreeLogger.DEBUG, options.getLogLevel());
- assertEquals(JsOutputOption.PRETTY, options.getOutput());
- assertTrue(options.isEnableAssertions());
- assertFalse(options.isAggressivelyOptimize());
-
- assertEquals(2, options.getModuleNames().size());
- assertEquals("c.g.g.h.H", options.getModuleNames().get(0));
- assertEquals("my.Module", options.getModuleNames().get(1));
- }
-
- public void testDefaultArgs() {
- assertProcessSuccess(argProcessor, "c.g.g.h.H");
-
- assertEquals(null, options.getGenDir());
- assertEquals(new File("").getAbsoluteFile(),
- options.getOutDir().getAbsoluteFile());
-
- assertEquals(TreeLogger.INFO, options.getLogLevel());
- assertEquals(JsOutputOption.OBFUSCATED, options.getOutput());
- assertFalse(options.isEnableAssertions());
- assertTrue(options.isAggressivelyOptimize());
-
- assertEquals(1, options.getModuleNames().size());
- assertEquals("c.g.g.h.H", options.getModuleNames().get(0));
- }
-
- public void testForbiddenArgs() {
- assertProcessFailure(argProcessor, "-localWorkers", "2");
- assertProcessFailure(argProcessor, "-extra", "extra");
- assertProcessFailure(argProcessor, "-war", "war");
- assertProcessFailure(argProcessor, "-work", "work");
- }
-}
diff --git a/dev/core/test/com/google/gwt/dev/GWTShellTest.java b/dev/core/test/com/google/gwt/dev/GWTShellTest.java
deleted file mode 100644
index 557189e..0000000
--- a/dev/core/test/com/google/gwt/dev/GWTShellTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2009 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;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.GWTShell.ShellOptionsImpl;
-import com.google.gwt.dev.HostedModeTest.MySCL;
-import com.google.gwt.dev.jjs.JsOutputOption;
-import com.google.gwt.dev.shell.BrowserWidgetHostChecker;
-
-import java.io.File;
-
-/**
- * Test for deprecated {@link GWTShell}.
- */
-@SuppressWarnings("deprecation")
-public class GWTShellTest extends ArgProcessorTestBase {
-
- private final GWTShell.ArgProcessor argProcessor;
- private final ShellOptionsImpl options = new ShellOptionsImpl();
-
- public GWTShellTest() {
- argProcessor = new GWTShell.ArgProcessor(options, false, false);
- }
-
- public void testAllValidArgs() {
- assertProcessSuccess(argProcessor, "-port", "8080", "-whitelist", "white",
- "-blacklist", "black", "-logLevel", "DEBUG", "-noserver", "-out",
- "myWww", "-gen", "myGen", "http://www.google.com/", "foo");
-
- assertNotNull(BrowserWidgetHostChecker.matchWhitelisted("white"));
- assertNotNull(BrowserWidgetHostChecker.matchBlacklisted("black"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/foo"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/foo"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/foo"));
- assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://www.evildomain.org/foo?http://localhost"));
- assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1"));
- assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88"));
- assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/"));
- assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/foo"));
-
- assertEquals(new File("myGen").getAbsoluteFile(),
- options.getGenDir().getAbsoluteFile());
- assertEquals(new File("myWww"), options.getOutDir());
-
- assertEquals(TreeLogger.DEBUG, options.getLogLevel());
-
- assertEquals(8080, options.getPort());
- assertTrue(options.isNoServer());
- assertEquals(2, options.getStartupURLs().size());
- assertEquals("http://www.google.com/", options.getStartupURLs().get(0));
- assertEquals("foo", options.getStartupURLs().get(1));
- }
-
- public void testDefaultArgs() {
- assertProcessSuccess(argProcessor);
-
- assertEquals(null, options.getGenDir());
- assertEquals(new File("").getAbsoluteFile(),
- options.getOutDir().getAbsoluteFile());
-
- assertEquals(TreeLogger.INFO, options.getLogLevel());
- assertEquals(JsOutputOption.OBFUSCATED, options.getOutput());
- assertFalse(options.isEnableAssertions());
- assertTrue(options.isAggressivelyOptimize());
-
- assertEquals(8888, options.getPort());
- assertFalse(options.isNoServer());
- assertEquals(0, options.getStartupURLs().size());
- }
-
- public void testForbiddenArgs() {
- assertProcessFailure(argProcessor, "-localWorkers", "2");
- assertProcessFailure(argProcessor, "-extra", "extra");
- assertProcessFailure(argProcessor, "-war", "war");
- assertProcessFailure(argProcessor, "-work", "work");
- assertProcessFailure(argProcessor, "-server", MySCL.class.getName());
- }
-}
diff --git a/eclipse/dev/.classpath b/eclipse/dev/.classpath
index fa17a0d..4b1f5b4 100644
--- a/eclipse/dev/.classpath
+++ b/eclipse/dev/.classpath
@@ -12,35 +12,16 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/ant-launcher-1.6.5.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/catalina-optional-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-beanutils-1.6.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-collections-3.1.jar" sourcepath="/GWT_TOOLS/lib/tomcat/commons-collections-3.1-src.zip"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-digester-1.5.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-el-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-logging-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-modeler-1.1.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/jakarta-regexp-1.3.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/jasper-compiler-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/jasper-runtime-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/jsp-api-2.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/mx4j-jmx-1.1.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/naming-common-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/naming-factory-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/naming-java-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/naming-resources-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/servlet-api-2.5.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/servlet-api-2.4.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/servlets-common-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/servlets-default-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/servlets-invoker-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/tomcat-coyote-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/tomcat-http11-1.0.jar" sourcepath="/GWT_TOOLS/lib/tomcat/tomcat-http11-1.0.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/tomcat-jk2-2.1.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/tomcat-util-5.1.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-2.9/htmlunit-core-js-2.9.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-2.9/htmlunit-core-js-2.9-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-2.9/htmlunit-2.9.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-2.9/htmlunit-2.9-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/guava/guava-10.0.1/guava-10.0.1-rebased.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/jscomp/sourcemap-rebased.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/jscomp/r1649/compiler-rebased.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/apache/commons/commons-collections-3.2.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>