Merging releases/1.6@4147:4198 into trunk.
svn merge --accept postpone -r4147:4198https://google-web-toolkit.googlecode.com/svn/releases/1.6 .
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4202 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/ExternalPermutationWorkerFactory.java b/dev/core/src/com/google/gwt/dev/ExternalPermutationWorkerFactory.java
index 392afea..137144d 100644
--- a/dev/core/src/com/google/gwt/dev/ExternalPermutationWorkerFactory.java
+++ b/dev/core/src/com/google/gwt/dev/ExternalPermutationWorkerFactory.java
@@ -342,6 +342,7 @@
List<PermutationWorker> toReturn = new ArrayList<PermutationWorker>(
numWorkers);
+ // TODO(spoon): clean up already-launched processes if we get an exception?
for (int i = 0; i < numWorkers; i++) {
String cookie = launchExternalWorker(logger, sock.getLocalPort());
cookies.add(cookie);
diff --git a/dev/core/src/com/google/gwt/dev/PermutationWorkerFactory.java b/dev/core/src/com/google/gwt/dev/PermutationWorkerFactory.java
index 4448c3d..0322072 100644
--- a/dev/core/src/com/google/gwt/dev/PermutationWorkerFactory.java
+++ b/dev/core/src/com/google/gwt/dev/PermutationWorkerFactory.java
@@ -17,7 +17,6 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.util.Util;
@@ -26,16 +25,9 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
/**
* Represents a factory for implementations of an endpoint that will invoke
@@ -46,73 +38,167 @@
public abstract class PermutationWorkerFactory {
/**
- * This callable is responsible for compiling one permutation. It waits for an
- * available worker, uses it, and returns it to the pool when finished.
+ * Coordinates the actions of a set of {@link PermutationWorker}s, running
+ * each in its own thread.
*/
- private static class CompileOnePermutation implements Callable<ResultStatus> {
- private final BlockingQueue<PermutationWorker> availableWorkers;
- private final TreeLogger logger;
- private final Permutation permutation;
- private final File resultFile;
+ private static class Manager {
- public CompileOnePermutation(TreeLogger logger, Permutation permutation,
- File resultFile, BlockingQueue<PermutationWorker> availableWorkers) {
- this.logger = logger;
- this.permutation = permutation;
- this.resultFile = resultFile;
- this.availableWorkers = availableWorkers;
+ private static final Work POISON_PILL = new Work(null, null, null);
+
+ private static enum Result {
+ SUCCESS, FAIL, WORKER_DEATH
}
- public ResultStatus call() {
- // Find a free worker
- PermutationWorker worker;
+ /**
+ * Runs a {@link PermutationWorker} on its own thread.
+ */
+ private class WorkerThread implements Runnable {
+ private final PermutationWorker worker;
+
+ public WorkerThread(PermutationWorker worker) {
+ this.worker = worker;
+ }
+
+ public void run() {
+ Result threadDeathResult = Result.FAIL;
+ try {
+ while (true) {
+ Work work = workQueue.take();
+ if (work == POISON_PILL) {
+ return;
+ }
+ TreeLogger logger = work.getLogger();
+ try {
+ PermutationResult result = worker.compile(logger, work.getPerm());
+ Util.writeObjectAsFile(logger, work.getResultFile(), result);
+ logger.log(TreeLogger.DEBUG, "Successfully compiled permutation");
+ resultsQueue.put(Result.SUCCESS);
+ } catch (TransientWorkerException e) {
+ logger.log(TreeLogger.DEBUG,
+ "Worker died, will retry Permutation", e);
+ workQueue.add(work);
+ threadDeathResult = Result.WORKER_DEATH;
+ return;
+ } catch (UnableToCompleteException e) {
+ logger.log(TreeLogger.ERROR,
+ "Unrecoverable exception, shutting down", e);
+ threadDeathResult = Result.FAIL;
+ return;
+ }
+ }
+ } catch (InterruptedException e) {
+ return;
+ } finally {
+ // Record why I died.
+ try {
+ resultsQueue.put(threadDeathResult);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+
+ public static void run(TreeLogger logger, List<Work> work,
+ List<PermutationWorker> workers) throws UnableToCompleteException {
+ new Manager().doRun(logger, work, workers);
+ }
+
+ /**
+ * The queue of work to do.
+ */
+ BlockingQueue<Work> workQueue;
+
+ /**
+ * The queue of work to do.
+ */
+ BlockingQueue<Result> resultsQueue;
+
+ private Manager() {
+ }
+
+ private void doRun(TreeLogger logger, List<Work> work,
+ List<PermutationWorker> workers) throws UnableToCompleteException {
+
+ // Initialize state.
+ workQueue = new LinkedBlockingQueue<Work>(work);
+ resultsQueue = new LinkedBlockingQueue<Result>();
+
+ List<Thread> threads = new ArrayList<Thread>(workers.size());
try {
- worker = availableWorkers.take();
+ for (PermutationWorker worker : workers) {
+ Thread thread = new Thread(new WorkerThread(worker));
+ threads.add(thread);
+ thread.start();
+ }
+
+ int workToDo = work.size();
+ int aliveWorkers = workers.size();
+ waitForWorkers : while (workToDo > 0 && aliveWorkers > 0) {
+ Result take = resultsQueue.take();
+ switch (take) {
+ case SUCCESS:
+ --workToDo;
+ break;
+ case FAIL:
+ break waitForWorkers;
+ case WORKER_DEATH:
+ --aliveWorkers;
+ break;
+ default:
+ throw new IncompatibleClassChangeError(Result.class.toString());
+ }
+ }
+
+ workQueue.clear();
+ for (int i = 0; i < aliveWorkers; ++i) {
+ workQueue.add(POISON_PILL);
+ }
+
+ if (workToDo > 0) {
+ logger.log(TreeLogger.ERROR,
+ "Not all permutation were compiled , completed ("
+ + (work.size() - workToDo) + "/" + work.size() + ")");
+ throw new UnableToCompleteException();
+ }
} catch (InterruptedException e) {
- logger.log(TreeLogger.DEBUG, "Worker interrupted", e);
- return ResultStatus.HARD_FAILURE;
- }
-
- if (worker == noMoreWorkersWorker) {
- // Shutting down
- return ResultStatus.HARD_FAILURE;
- }
-
- // Invoke the worker
- try {
- PermutationResult result = worker.compile(logger, permutation);
- Util.writeObjectAsFile(logger, resultFile, result);
- logger.log(TreeLogger.DEBUG, "Successfully compiled permutation");
- availableWorkers.add(worker);
- return ResultStatus.SUCCESS;
- } catch (TransientWorkerException e) {
- logger.log(TreeLogger.DEBUG, "Worker died, will retry Permutation", e);
- return ResultStatus.TRANSIENT_FAILURE;
- } catch (UnableToCompleteException e) {
- logger.log(TreeLogger.ERROR, "Unrecoverable exception, shutting down",
- e);
- return ResultStatus.HARD_FAILURE;
+ logger.log(TreeLogger.ERROR,
+ "Exiting without results due to interruption", e);
+ throw new UnableToCompleteException();
+ } finally {
+ // Interrupt any outstanding threads.
+ for (Thread thread : threads) {
+ thread.interrupt();
+ }
}
}
}
- private static enum ResultStatus {
- /**
- * A failure bad enough to merit shutting down the compilation.
- */
- HARD_FAILURE,
+ /**
+ * Represents work to do.
+ */
+ private static class Work {
+ private final TreeLogger logger;
+ private final Permutation perm;
+ private final File resultFile;
- /**
- * A successful compile.
- */
- SUCCESS,
+ public Work(TreeLogger logger, Permutation perm, File resultFile) {
+ this.logger = logger;
+ this.perm = perm;
+ this.resultFile = resultFile;
+ }
- /**
- * A worker died while processing this permutation, but it is worth trying
- * to compile it with another worker.
- */
- TRANSIENT_FAILURE
- };
+ public TreeLogger getLogger() {
+ return logger;
+ }
+
+ public Permutation getPerm() {
+ return perm;
+ }
+
+ public File getResultFile() {
+ return resultFile;
+ }
+ }
/**
* The name of the system property used to define the workers.
@@ -128,21 +214,6 @@
private static List<PermutationWorkerFactory> lazyFactories;
- private static final PermutationWorker noMoreWorkersWorker = new PermutationWorker() {
-
- public PermutationResult compile(TreeLogger logger, Permutation permutation)
- throws TransientWorkerException, UnableToCompleteException {
- throw new UnableToCompleteException();
- }
-
- public String getName() {
- return "Marker worker indicating no more workers";
- }
-
- public void shutdown() {
- }
- };
-
/**
* Compiles all Permutations in a Precompilation and returns an array of Files
* that can be consumed by Link using the system-default
@@ -175,103 +246,35 @@
assert Arrays.asList(precompilation.getPermutations()).containsAll(
Arrays.asList(permutations));
- // We may have a mixed collection of workers from different factories
+ // Create the work.
+ List<Work> work = new ArrayList<Work>(permutations.length);
+ for (int i = 0; i < permutations.length; ++i) {
+ Permutation perm = permutations[i];
+ TreeLogger permLogger = logger.branch(TreeLogger.DEBUG,
+ "Worker permutation " + perm.getId() + " of " + permutations.length);
+ work.add(new Work(permLogger, perm, resultFiles[i]));
+ }
+
+ // Create the workers.
List<PermutationWorker> workers = new ArrayList<PermutationWorker>();
-
- /*
- * We can have errors below this point, there's a finally block to handle
- * cleanup of workers.
- */
try {
- createWorkers(logger, precompilation.getUnifiedAst(),
- permutations.length, localWorkers, workers);
- ExecutorService executor = Executors.newFixedThreadPool(workers.size());
+ createWorkers(logger, precompilation.getUnifiedAst(), work.size(),
+ localWorkers, workers);
- // List of available workers.
- // The extra space is for inserting nulls at shutdown time
- BlockingQueue<PermutationWorker> availableWorkers = new ArrayBlockingQueue<PermutationWorker>(
- 2 * workers.size());
- availableWorkers.addAll(workers);
-
- try {
-
- // Submit all tasks to the executor
-
- // The permutation compiles not yet finished
- Queue<CompileOnePermutation> tasksOutstanding = new LinkedList<CompileOnePermutation>();
-
- // The futures for the results of those compiles
- Queue<Future<ResultStatus>> resultFutures = new LinkedList<Future<ResultStatus>>();
-
- for (int i = 0; i < permutations.length; ++i) {
- TreeLogger permLogger = logger.branch(TreeLogger.DEBUG,
- "Worker permutation " + permutations[i].getId() + " of "
- + permutations.length);
- CompileOnePermutation task = new CompileOnePermutation(permLogger,
- permutations[i], resultFiles[i], availableWorkers);
- tasksOutstanding.add(task);
- resultFutures.add(executor.submit(task));
- }
-
- // Count the number of dead workers
- int numDeadWorkers = 0;
- int successCount = 0;
-
- while (!resultFutures.isEmpty() && numDeadWorkers < workers.size()) {
- assert resultFutures.size() == tasksOutstanding.size();
-
- CompileOnePermutation task = tasksOutstanding.remove();
- Future<ResultStatus> future = resultFutures.remove();
- ResultStatus result;
- try {
- result = future.get();
- } catch (InterruptedException e) {
- logger.log(TreeLogger.ERROR,
- "Exiting without results due to interruption", e);
- throw new UnableToCompleteException();
- } catch (ExecutionException e) {
- logger.log(TreeLogger.ERROR, "A compilation failed", e);
- throw new UnableToCompleteException();
- }
-
- if (result == ResultStatus.SUCCESS) {
- ++successCount;
- } else if (result == ResultStatus.TRANSIENT_FAILURE) {
- // A worker died. Resubmit for the remaining workers.
- ++numDeadWorkers;
- tasksOutstanding.add(task);
- resultFutures.add(executor.submit(task));
- } else if (result == ResultStatus.HARD_FAILURE) {
- // Shut down.
- break;
- } else {
- throw new InternalCompilerException("Unknown result type");
- }
- }
-
- // Too many permutations is a coding error
- assert successCount <= permutations.length;
-
- if (successCount < permutations.length) {
- // Likely as not, all of the workers died
- logger.log(TreeLogger.ERROR, "Not all permutation were compiled "
- + successCount + " of " + permutations.length);
- throw new UnableToCompleteException();
- }
- } finally {
- // Shut down the executor
- executor.shutdown();
-
- // Inform any residual CompileOnePermutation's that there aren't any
- // more workers
- for (int i = 0; i < workers.size(); i++) {
- availableWorkers.add(noMoreWorkersWorker);
+ // Get it done!
+ Manager.run(logger, work, workers);
+ } finally {
+ Throwable caught = null;
+ for (PermutationWorker worker : workers) {
+ try {
+ worker.shutdown();
+ } catch (Throwable e) {
+ caught = e;
}
}
- } finally {
- // Shut down all workers
- for (PermutationWorker worker : workers) {
- worker.shutdown();
+ if (caught != null) {
+ throw new RuntimeException(
+ "One of the workers threw an exception while shutting down", caught);
}
}
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
index 826184d..210995c 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
@@ -189,6 +189,12 @@
public abstract boolean isGenerated();
/**
+ *
+ * @return true if the Compilation Unit is from a super-source.
+ */
+ public abstract boolean isSuperSource();
+
+ /**
* Overridden to finalize; always returns {@link #getDisplayLocation()}.
*/
public final String toString() {
diff --git a/dev/core/src/com/google/gwt/dev/javac/JavaSourceFile.java b/dev/core/src/com/google/gwt/dev/javac/JavaSourceFile.java
index c1bf5f7..571b501 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JavaSourceFile.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JavaSourceFile.java
@@ -63,6 +63,11 @@
}
/**
+ * @return true if the corresponding source comes from super-source.
+ */
+ public abstract boolean isSuperSource();
+
+ /**
* Returns the Java code contained in this source file. May return
* <code>null</code> if this {@link JavaSourceFile} has been invalidated by
* its containing {@link JavaSourceOracle}. This method may be expensive as
@@ -76,4 +81,5 @@
public final String toString() {
return getLocation();
}
+
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/impl/FileCompilationUnit.java b/dev/core/src/com/google/gwt/dev/javac/impl/FileCompilationUnit.java
index d2fee22..568791a 100644
--- a/dev/core/src/com/google/gwt/dev/javac/impl/FileCompilationUnit.java
+++ b/dev/core/src/com/google/gwt/dev/javac/impl/FileCompilationUnit.java
@@ -63,4 +63,9 @@
public boolean isGenerated() {
return false;
}
+
+ @Override
+ public boolean isSuperSource() {
+ return false;
+ }
}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/javac/impl/JavaSourceOracleImpl.java b/dev/core/src/com/google/gwt/dev/javac/impl/JavaSourceOracleImpl.java
index 88e2406..e2d7145 100644
--- a/dev/core/src/com/google/gwt/dev/javac/impl/JavaSourceOracleImpl.java
+++ b/dev/core/src/com/google/gwt/dev/javac/impl/JavaSourceOracleImpl.java
@@ -85,6 +85,11 @@
}
@Override
+ public boolean isSuperSource() {
+ return resource.wasRerooted();
+ }
+
+ @Override
public String readSource() {
if (resource != null) {
InputStream contents = resource.openContents();
diff --git a/dev/core/src/com/google/gwt/dev/javac/impl/SourceFileCompilationUnit.java b/dev/core/src/com/google/gwt/dev/javac/impl/SourceFileCompilationUnit.java
index 7f543af..c3e7c9e 100644
--- a/dev/core/src/com/google/gwt/dev/javac/impl/SourceFileCompilationUnit.java
+++ b/dev/core/src/com/google/gwt/dev/javac/impl/SourceFileCompilationUnit.java
@@ -63,6 +63,11 @@
}
@Override
+ public boolean isSuperSource() {
+ return sourceFile.isSuperSource();
+ }
+
+ @Override
protected void dumpSource() {
sourceCode = null;
}
diff --git a/dev/core/src/com/google/gwt/dev/resource/Resource.java b/dev/core/src/com/google/gwt/dev/resource/Resource.java
index 6d61cce..0a49ff6 100644
--- a/dev/core/src/com/google/gwt/dev/resource/Resource.java
+++ b/dev/core/src/com/google/gwt/dev/resource/Resource.java
@@ -64,8 +64,8 @@
}
/**
- * Returns the contents of the resource. May return <code>null</code> if
- * this {@link Resource} has been invalidated by its containing
+ * Returns the contents of the resource. May return <code>null</code> if this
+ * {@link Resource} has been invalidated by its containing
* {@link ResourceOracle}. The caller is responsible for closing the stream.
*/
public abstract InputStream openContents();
@@ -77,4 +77,7 @@
public final String toString() {
return getLocation();
}
+
+ public abstract boolean wasRerooted();
+
}
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/FileResource.java b/dev/core/src/com/google/gwt/dev/resource/impl/FileResource.java
index dab8e71..a3183cc 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/FileResource.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/FileResource.java
@@ -94,6 +94,11 @@
}
}
+ @Override
+ public boolean wasRerooted() {
+ return false;
+ }
+
private long lastModifiedSeconds(File file) {
return file.lastModified() / 1000;
}
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
index 780c965..6097117 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
@@ -123,6 +123,11 @@
public InputStream openContents() {
return resource.openContents();
}
+
+ @Override
+ public boolean wasRerooted() {
+ return true;
+ }
}
public static ClassPathEntry createEntryForUrl(TreeLogger logger, URL url)
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
index 1920e86..3c15743 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
@@ -90,4 +90,9 @@
return null;
}
}
+
+ @Override
+ public boolean wasRerooted() {
+ return false;
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
index 81022e1..4eb38c1 100644
--- a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
+++ b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
@@ -51,8 +51,8 @@
/**
* An isolated {@link ClassLoader} for running all user code. All user files are
- * compiled from source code byte a {@link ByteCodeCompiler}. After
- * compilation, some byte code rewriting is performed to support
+ * compiled from source code byte a {@link ByteCodeCompiler}. After compilation,
+ * some byte code rewriting is performed to support
* <code>JavaScriptObject</code> and its subtypes.
*
* TODO: we should refactor this class to move the getClassInfoByDispId,
@@ -64,8 +64,8 @@
DispatchIdOracle {
/**
- * Oracle that can answer questions about
- * {@link DispatchClassInfo DispatchClassInfos}.
+ * Oracle that can answer questions about {@link DispatchClassInfo
+ * DispatchClassInfos}.
*/
private final class DispatchClassInfoOracle {
@@ -564,8 +564,8 @@
* was previously cached and has not been garbage collected.
*
* @param javaObject the Object being wrapped
- * @return the mapped wrapper, or <code>null</code> if the Java object
- * mapped or if the wrapper has been garbage collected
+ * @return the mapped wrapper, or <code>null</code> if the Java object mapped
+ * or if the wrapper has been garbage collected
*/
public Object getWrapperForObject(Object javaObject) {
return weakJavaWrapperCache.get(javaObject);
@@ -705,8 +705,13 @@
lookupClassName);
if (compiledClass != null) {
byte[] classBytes = compiledClass.getBytes();
- classBytes = emmaStrategy.getEmmaClassBytes(classBytes, lookupClassName,
- compiledClass.getUnit().getLastModified());
+ if (!compiledClass.getUnit().isSuperSource()) {
+ classBytes = emmaStrategy.getEmmaClassBytes(classBytes,
+ lookupClassName, compiledClass.getUnit().getLastModified());
+ } else {
+ logger.log(TreeLogger.SPAM, "no emma instrumentation for "
+ + lookupClassName + " because it is from super-source");
+ }
if (classRewriter != null) {
byte[] newBytes = classRewriter.rewrite(className, classBytes);
if (CLASS_DUMP) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
index 06ba50e..6433045 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
@@ -127,6 +127,11 @@
return file != null;
}
+ @Override
+ public boolean isSuperSource() {
+ return false;
+ }
+
public void setFile(File file) {
assert (file.exists() && file.canRead());
this.file = file;
diff --git a/dev/core/test/com/google/gwt/dev/javac/MockCompilationUnit.java b/dev/core/test/com/google/gwt/dev/javac/MockCompilationUnit.java
index 4014c8d..7a0b99b 100644
--- a/dev/core/test/com/google/gwt/dev/javac/MockCompilationUnit.java
+++ b/dev/core/test/com/google/gwt/dev/javac/MockCompilationUnit.java
@@ -52,4 +52,9 @@
public boolean isGenerated() {
return true;
}
+
+ @Override
+ public boolean isSuperSource() {
+ return false;
+ }
}
diff --git a/dev/core/test/com/google/gwt/dev/javac/impl/MockJavaSourceFile.java b/dev/core/test/com/google/gwt/dev/javac/impl/MockJavaSourceFile.java
index 1018edb..c7d0bbb 100644
--- a/dev/core/test/com/google/gwt/dev/javac/impl/MockJavaSourceFile.java
+++ b/dev/core/test/com/google/gwt/dev/javac/impl/MockJavaSourceFile.java
@@ -70,7 +70,13 @@
}
@Override
+ public boolean isSuperSource() {
+ return false;
+ }
+
+ @Override
public String readSource() {
return source;
}
+
}
diff --git a/dev/core/test/com/google/gwt/dev/javac/impl/MockResource.java b/dev/core/test/com/google/gwt/dev/javac/impl/MockResource.java
index b35cfda..bcce637 100644
--- a/dev/core/test/com/google/gwt/dev/javac/impl/MockResource.java
+++ b/dev/core/test/com/google/gwt/dev/javac/impl/MockResource.java
@@ -57,5 +57,10 @@
return new ByteArrayInputStream(Util.getBytes(getContent().toString()));
}
+ @Override
+ public boolean wasRerooted() {
+ return false;
+ }
+
protected abstract CharSequence getContent();
}
diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/MockAbstractResource.java b/dev/core/test/com/google/gwt/dev/resource/impl/MockAbstractResource.java
index 992fdcb..afca6d4 100644
--- a/dev/core/test/com/google/gwt/dev/resource/impl/MockAbstractResource.java
+++ b/dev/core/test/com/google/gwt/dev/resource/impl/MockAbstractResource.java
@@ -69,4 +69,9 @@
public void setStale(boolean isStale) {
this.isStale = isStale;
}
+
+ @Override
+ public boolean wasRerooted() {
+ return false;
+ }
}
\ No newline at end of file
diff --git a/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java b/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
index ede0be2..3d71400 100644
--- a/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
+++ b/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
@@ -123,6 +123,12 @@
public InputStream openContents() {
return new ByteArrayInputStream(Util.getBytes("w00t!"));
}
+
+ @Override
+ public boolean wasRerooted() {
+ return false;
+ }
+
};
}
return null;
diff --git a/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiContainerTest.java b/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiContainerTest.java
index b7c87d2..bf21c88 100644
--- a/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiContainerTest.java
+++ b/tools/api-checker/test/com/google/gwt/tools/apichecker/ApiContainerTest.java
@@ -68,6 +68,11 @@
public boolean isGenerated() {
return false;
}
+
+ @Override
+ public boolean isSuperSource() {
+ return false;
+ }
}
@SuppressWarnings("unused")
diff --git a/user/src/com/google/gwt/user/client/Event.java b/user/src/com/google/gwt/user/client/Event.java
index 94b3043..f4dccd6 100644
--- a/user/src/com/google/gwt/user/client/Event.java
+++ b/user/src/com/google/gwt/user/client/Event.java
@@ -283,12 +283,8 @@
* Gets whether the ALT key was depressed when the given event occurred.
*
* @return <code>true</code> if ALT was depressed when the event occurred
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getAltKey() throws AssertionError {
+ public final boolean getAltKey() {
return DOM.eventGetAltKey(this);
}
@@ -297,10 +293,8 @@
*
* @return a bit-field, defined by {@link Event#BUTTON_LEFT},
* {@link Event#BUTTON_MIDDLE}, and {@link Event#BUTTON_RIGHT}
- * @throws AssertionError if event type is not one of
- * {@link Event#ONMOUSEDOWN} or {@link Event#ONMOUSEUP}
*/
- public final int getButton() throws AssertionError {
+ public final int getButton() {
return DOM.eventGetButton(this);
}
@@ -308,12 +302,8 @@
* Gets the mouse x-position within the browser window's client area.
*
* @return the mouse x-position
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final int getClientX() throws AssertionError {
+ public final int getClientX() {
return DOM.eventGetClientX(this);
}
@@ -321,12 +311,8 @@
* Gets the mouse y-position within the browser window's client area.
*
* @return the mouse y-position
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final int getClientY() throws AssertionError {
+ public final int getClientY() {
return DOM.eventGetClientY(this);
}
@@ -334,12 +320,8 @@
* Gets whether the CTRL key was depressed when the given event occurred.
*
* @return <code>true</code> if CTRL was depressed when the event occurred
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getCtrlKey() throws AssertionError {
+ public final boolean getCtrlKey() {
return DOM.eventGetCtrlKey(this);
}
@@ -358,10 +340,8 @@
* {@link Event#ONMOUSEOVER}).
*
* @return the element from which the mouse pointer was moved
- * @throws AssertionError if event type is not one of
- * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public final Element getFromElement() throws AssertionError {
+ public final Element getFromElement() {
return DOM.eventGetFromElement(this);
}
@@ -375,10 +355,9 @@
* </p>
*
* @return the Unicode character or key code.
- * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS}
* @see com.google.gwt.user.client.ui.KeyboardListener
*/
- public final int getKeyCode() throws AssertionError {
+ public final int getKeyCode() {
return DOM.eventGetKeyCode(this);
}
@@ -386,12 +365,8 @@
* Gets whether the META key was depressed when the given event occurred.
*
* @return <code>true</code> if META was depressed when the event occurred
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getMetaKey() throws AssertionError {
+ public final boolean getMetaKey() {
return DOM.eventGetMetaKey(this);
}
@@ -408,9 +383,8 @@
* </p>
*
* @return The velocity of the mouse wheel.
- * @throws AssertionError if event type is not {@link Event#ONMOUSEWHEEL}
*/
- public final int getMouseWheelVelocityY() throws AssertionError {
+ public final int getMouseWheelVelocityY() {
return DOM.eventGetMouseWheelVelocityY(this);
}
@@ -418,9 +392,8 @@
* Gets the key-repeat state of this event.
*
* @return <code>true</code> if this key event was an auto-repeat
- * @throws AssertionError if event type is not {@link Event#ONKEYDOWN}
*/
- public final boolean getRepeat() throws AssertionError {
+ public final boolean getRepeat() {
return DOM.eventGetRepeat(this);
}
@@ -433,7 +406,7 @@
* {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
* {@link Event#ONCONTEXTMENU}
*/
- public final int getScreenX() throws AssertionError {
+ public final int getScreenX() {
return DOM.eventGetScreenX(this);
}
@@ -441,12 +414,8 @@
* Gets the mouse y-position on the user's display.
*
* @return the mouse y-position
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL},
- * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final int getScreenY() throws AssertionError {
+ public final int getScreenY() {
return DOM.eventGetScreenY(this);
}
@@ -454,12 +423,8 @@
* Gets whether the shift key was depressed when the given event occurred.
*
* @return <code>true</code> if shift was depressed when the event occurred
- * @throws AssertionError if event type is not one of
- * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
- * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
- * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getShiftKey() throws AssertionError {
+ public final boolean getShiftKey() {
return DOM.eventGetShiftKey(this);
}
@@ -489,10 +454,8 @@
* {@link Event#ONMOUSEOUT}).
*
* @return the element to which the mouse pointer was moved
- * @throws AssertionError if event type is not one of
- * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public final Element getToElement() throws AssertionError {
+ public final Element getToElement() {
return DOM.eventGetToElement(this);
}
diff --git a/user/src/com/google/gwt/user/client/ui/CheckBox.java b/user/src/com/google/gwt/user/client/ui/CheckBox.java
index 1b1a8f3..a9eba4f 100644
--- a/user/src/com/google/gwt/user/client/ui/CheckBox.java
+++ b/user/src/com/google/gwt/user/client/ui/CheckBox.java
@@ -219,6 +219,7 @@
}
public void setValue(Boolean value, boolean fireEvents) {
+ assert null != value : "Value must not be null";
if (isChecked() == value) {
return;
}
diff --git a/user/src/com/google/gwt/user/client/ui/DialogBox.java b/user/src/com/google/gwt/user/client/ui/DialogBox.java
index 3522241..f4b328e 100644
--- a/user/src/com/google/gwt/user/client/ui/DialogBox.java
+++ b/user/src/com/google/gwt/user/client/ui/DialogBox.java
@@ -204,8 +204,10 @@
@Override
public void hide() {
- resizeHandlerRegistration.removeHandler();
- resizeHandlerRegistration = null;
+ if (resizeHandlerRegistration != null) {
+ resizeHandlerRegistration.removeHandler();
+ resizeHandlerRegistration = null;
+ }
super.hide();
}
diff --git a/user/src/com/google/gwt/user/client/ui/HasValue.java b/user/src/com/google/gwt/user/client/ui/HasValue.java
index f3240e9..0c7d36f 100644
--- a/user/src/com/google/gwt/user/client/ui/HasValue.java
+++ b/user/src/com/google/gwt/user/client/ui/HasValue.java
@@ -20,6 +20,11 @@
/**
* An object that implements this interface should be a user input widget, where
* the user and programmer can both set and get the object's value.
+ * <p>
+ * It is a requirement that a value passed to {@link setValue} be
+ * {@link Object#equals} to that returned by an immediately succeeding call to
+ * {@link getValue}, or that both be null. Note that this is not a requirement
+ * that <code>setValue(null)</code> be supported by all implementors.
*
* @param <T> the type of value.
*/
@@ -33,8 +38,11 @@
T getValue();
/**
- * Sets this object's value without firing any events. Should call setValue(T
- * value, false).
+ * Sets this object's value without firing any events. This should be
+ * identical to calling setValue(value, false).
+ * <p>
+ * It is acceptable to fail assertions or throw (documented) unchecked
+ * exceptions in response to bad values.
*
* @param value the object's new value
*/
@@ -44,6 +52,9 @@
* Sets this object's value. Fires
* {@link com.google.gwt.event.logical.shared.ValueChangeEvent} when
* fireEvents is true and the new value does not equal the existing value.
+ * <p>
+ * It is acceptable to fail assertions or throw (documented) unchecked
+ * exceptions in response to bad values.
*
* @param value the object's new value
* @param fireEvents fire events if true and value is new
diff --git a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
index 3a8554e..3f7660a 100644
--- a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
+++ b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
@@ -301,6 +301,7 @@
}
public void setValue(String value, boolean fireEvents) {
+ assert null != value : "Value must not be null";
String oldValue = getText();
setText(value);
if (fireEvents) {
diff --git a/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java b/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
index 0d0d66e..fd3a5e1 100644
--- a/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
+++ b/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
@@ -51,6 +51,10 @@
assertEquals("", obj1, obj2);
}
+ public static void assertEquals(short expected, short actual) {
+ assertEquals("", expected, actual);
+ }
+
public static void assertEquals(String str, boolean obj1, boolean obj2) {
assertEquals(str, Boolean.valueOf(obj1), Boolean.valueOf(obj2));
}
@@ -107,6 +111,18 @@
fail(msg + " expected=" + obj1 + " actual=" + obj2);
}
+ public static void assertEquals(String str, short obj1, short obj2) {
+ assertEquals(str, new Short(obj1), new Short(obj2));
+ }
+
+ public static void assertEquals(String obj1, String obj2) {
+ assertEquals("", obj1, obj2);
+ }
+
+ public static void assertEquals(String message, String expected, String actual) {
+ assertEquals(message, (Object) expected, (Object) actual);
+ }
+
public static void assertFalse(boolean condition) {
assertFalse(null, condition);
}
@@ -181,6 +197,32 @@
throw new AssertionFailedError(message);
}
+ public static void failNotEquals(String message, Object expected,
+ Object actual) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected :<" + expected + "> was not:<" + actual + ">");
+ }
+
+ public static void failNotSame(String message, Object expected, Object actual) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected same:<" + expected + "> was not:<" + actual
+ + ">");
+ }
+
+ public static void failSame(String message) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected not same");
+ }
+
/**
* Utility class, no public constructor needed.
*/