+ * The return value of {@code Lists.newArrayList(E[])} has GWT
+ * serializable type. It is also useful in specifying contracts of interface
+ * methods. In the following example,
+ *
+ *
+ * The {@code newArrayList(E[])} method of all implementations of {@code
+ * ListFactory} is expected to return a value with a GWT serializable type.
+ *
+ *
Note that a {@code GwtCompatible} type may have some {@link
+ * GwtIncompatible} methods.
+ *
+ * @author Charles Fry
+ * @author Hayward Chan
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+// @Documented - uncomment when GWT support is official
+@GwtCompatible
+public @interface GwtCompatible {
+
+ /**
+ * When {@code true}, the annotated type or the type of the method return
+ * value is GWT serializable.
+ *
+ * @see
+ * Documentation about GWT serialization
+ */
+ boolean serializable() default false;
+
+ /**
+ * When {@code true}, the annotated type is emulated in GWT. The emulated
+ * source (also known as super-source) is different from the implementation
+ * used by the JVM.
+ *
+ * @see
+ * Documentation about GWT emulated source
+ */
+ boolean emulated() default false;
+}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/GwtIncompatible.java b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/GwtIncompatible.java
new file mode 100644
index 00000000000..dae25ba6fbf
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/GwtIncompatible.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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 org.elasticsearch.util.gcommon.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The presence of this annotation on a method indicates that the method may
+ * not be used with the
+ * Google Web Toolkit (GWT),
+ * even though its type is annotated as {@link GwtCompatible} and accessible in
+ * GWT. They can cause GWT compilation errors or simply unexpected exceptions
+ * when used in GWT.
+ *
+ *
Note that this annotation should only be applied to methods of types which
+ * are annotated as {@link GwtCompatible}.
+ *
+ * @author Charles Fry
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+// @Documented - uncomment when GWT support is official
+@GwtCompatible
+public @interface GwtIncompatible {
+
+ /**
+ * Describes why the annotated element is incompatible with GWT. Since this is
+ * generally due to a dependence on a type/method which GWT doesn't support,
+ * it is sufficient to simply reference the unsupported type/method. E.g.
+ * "Class.isInstance".
+ */
+ String value();
+
+}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/VisibleForTesting.java b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/VisibleForTesting.java
new file mode 100644
index 00000000000..57f03301aa9
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/annotations/VisibleForTesting.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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 org.elasticsearch.util.gcommon.annotations;
+
+/**
+ * An annotation that indicates that the visibility of a type or member has
+ * been relaxed to make the code testable.
+ *
+ * @author Johannes Henkel
+ */
+@GwtCompatible
+public @interface VisibleForTesting {}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizablePhantomReference.java b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizablePhantomReference.java
new file mode 100644
index 00000000000..d61f98f3efc
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizablePhantomReference.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 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 org.elasticsearch.util.gcommon.base;
+
+import java.lang.ref.PhantomReference;
+
+/**
+ * Phantom reference with a {@code finalizeReferent()} method which a
+ * background thread invokes after the garbage collector reclaims the
+ * referent. This is a simpler alternative to using a {@link
+ * java.lang.ref.ReferenceQueue}.
+ *
+ *
Unlike a normal phantom reference, this reference will be cleared
+ * automatically.
+ *
+ * @author Bob Lee
+ */
+public abstract class FinalizablePhantomReference
+ extends PhantomReference implements FinalizableReference {
+
+ /**
+ * Constructs a new finalizable phantom reference.
+ *
+ * @param referent to phantom reference
+ * @param queue that should finalize the referent
+ */
+ protected FinalizablePhantomReference(T referent,
+ FinalizableReferenceQueue queue) {
+ super(referent, queue.queue);
+ queue.cleanUp();
+ }
+}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReference.java b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReference.java
new file mode 100644
index 00000000000..0377bfb1e4c
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReference.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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 org.elasticsearch.util.gcommon.base;
+
+/**
+ * Implemented by references that have code to run after garbage collection of
+ * their referents.
+ *
+ * @see FinalizableReferenceQueue
+ * @author Bob Lee
+ */
+public interface FinalizableReference {
+
+ /**
+ * Invoked on a background thread after the referent has been garbage
+ * collected unless security restrictions prevented starting a background
+ * thread, in which case this method is invoked when new references
+ * are created.
+ */
+ void finalizeReferent();
+}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReferenceQueue.java b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReferenceQueue.java
new file mode 100644
index 00000000000..19559ec2b91
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/util/gcommon/base/FinalizableReferenceQueue.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 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 org.elasticsearch.util.gcommon.base;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A reference queue with an associated background thread that dequeues
+ * references and invokes {@link FinalizableReference#finalizeReferent()} on
+ * them.
+ *
+ *
Keep a strong reference to this object until all of the associated
+ * referents have been finalized. If this object is garbage collected earlier,
+ * the backing thread will not invoke {@code finalizeReferent()} on the
+ * remaining references.
+ *
+ * @author Bob Lee
+ */
+public class FinalizableReferenceQueue {
+
+ /*
+ * The Finalizer thread keeps a phantom reference to this object. When the
+ * client (ReferenceMap, for example) no longer has a strong reference to
+ * this object, the garbage collector will reclaim it and enqueue the
+ * phantom reference. The enqueued reference will trigger the Finalizer to
+ * stop.
+ *
+ * If this library is loaded in the system class loader,
+ * FinalizableReferenceQueue can load Finalizer directly with no problems.
+ *
+ * If this library is loaded in an application class loader, it's important
+ * that Finalizer not have a strong reference back to the class loader.
+ * Otherwise, you could have a graph like this:
+ *
+ * Finalizer Thread
+ * runs instance of -> Finalizer.class
+ * loaded by -> Application class loader
+ * which loaded -> ReferenceMap.class
+ * which has a static -> FinalizableReferenceQueue instance
+ *
+ * Even if no other references to classes from the application class loader
+ * remain, the Finalizer thread keeps an indirect strong reference to the
+ * queue in ReferenceMap, which keeps the Finalizer running, and as a result,
+ * the application class loader can never be reclaimed.
+ *
+ * This means that dynamically loaded web applications and OSGi bundles can't
+ * be unloaded.
+ *
+ * If the library is loaded in an application class loader, we try to break
+ * the cycle by loading Finalizer in its own independent class loader:
+ *
+ * System class loader
+ * -> Application class loader
+ * -> ReferenceMap
+ * -> FinalizableReferenceQueue
+ * -> etc.
+ * -> Decoupled class loader
+ * -> Finalizer
+ *
+ * Now, Finalizer no longer keeps an indirect strong reference to the
+ * static FinalizableReferenceQueue field in ReferenceMap. The application
+ * class loader can be reclaimed at which point the Finalizer thread will
+ * stop and its decoupled class loader can also be reclaimed.
+ *
+ * If any of this fails along the way, we fall back to loading Finalizer
+ * directly in the application class loader.
+ */
+
+ private static final Logger logger
+ = Logger.getLogger(FinalizableReferenceQueue.class.getName());
+
+ private static final String FINALIZER_CLASS_NAME
+ = "org.elasticsearch.util.gcommon.base.internal.Finalizer";
+
+ /** Reference to Finalizer.startFinalizer(). */
+ private static final Method startFinalizer;
+ static {
+ Class> finalizer = loadFinalizer(
+ new SystemLoader(), new DecoupledLoader(), new DirectLoader());
+ startFinalizer = getStartFinalizer(finalizer);
+ }
+
+ /**
+ * The actual reference queue that our background thread will poll.
+ */
+ final ReferenceQueue